Merge branch 'master' into feature/budget_phases
This commit is contained in:
@@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
||||
- Improve budget investment form https://github.com/consul/consul/pull/2280
|
||||
- Prevent edition of investments if budget is in the final phase https://github.com/consul/consul/pull/2223
|
||||
- Split 'routes.rb' file into multiple small files https://github.com/consul/consul/pull/1908
|
||||
- Design Improvements https://github.com/consul/consul/pull/2327
|
||||
|
||||
### Deprecated
|
||||
- Budget's `description_*` columns will be erased from database in next release. Please run rake task `budgets:phases:generate_missing` to migrate them. Details at Warning section of https://github.com/consul/consul/pull/2323
|
||||
|
||||
6
Gemfile
6
Gemfile
@@ -20,7 +20,7 @@ gem 'devise_security_extension', '~> 0.10.0'
|
||||
gem 'foundation-rails', '~> 6.2.4.0'
|
||||
gem 'foundation_rails_helper', '~> 2.0.0'
|
||||
gem 'graphiql-rails', '~> 1.4.1'
|
||||
gem 'graphql', '~> 1.7.7'
|
||||
gem 'graphql', '~> 1.7.8'
|
||||
gem 'groupdate', '~> 3.2.0'
|
||||
gem 'initialjs-rails', '~> 0.2.0.5'
|
||||
gem 'invisible_captcha', '~> 0.10.0'
|
||||
@@ -44,7 +44,7 @@ gem 'rollbar', '~> 2.15.5'
|
||||
gem 'rubyzip', '~> 1.2.0'
|
||||
gem 'sass-rails', '~> 5.0', '>= 5.0.4'
|
||||
gem 'savon', '~> 2.11.1'
|
||||
gem 'sitemap_generator', '~> 6.0.0'
|
||||
gem 'sitemap_generator', '~> 6.0.1'
|
||||
gem 'social-share-button', '~> 1.1'
|
||||
gem 'sprockets', '~> 3.7.1'
|
||||
gem 'turbolinks', '~> 2.5.3'
|
||||
@@ -66,7 +66,7 @@ group :development, :test do
|
||||
gem 'i18n-tasks', '~> 0.9.15'
|
||||
gem 'knapsack_pro', '~> 0.53.0'
|
||||
gem 'launchy', '~> 2.4.3'
|
||||
gem 'letter_opener_web', '~> 1.3.1'
|
||||
gem 'letter_opener_web', '~> 1.3.2'
|
||||
gem 'quiet_assets', '~> 1.1.0'
|
||||
gem 'spring', '~> 2.0.1'
|
||||
gem 'spring-commands-rspec', '~> 1.0.4'
|
||||
|
||||
@@ -522,7 +522,7 @@ DEPENDENCIES
|
||||
foundation-rails (~> 6.2.4.0)
|
||||
foundation_rails_helper (~> 2.0.0)
|
||||
graphiql-rails (~> 1.4.1)
|
||||
graphql (~> 1.7.7)
|
||||
graphql (~> 1.7.8)
|
||||
groupdate (~> 3.2.0)
|
||||
i18n-tasks (~> 0.9.15)
|
||||
initialjs-rails (~> 0.2.0.5)
|
||||
@@ -533,7 +533,7 @@ DEPENDENCIES
|
||||
kaminari (~> 1.1.1)
|
||||
knapsack_pro (~> 0.53.0)
|
||||
launchy (~> 2.4.3)
|
||||
letter_opener_web (~> 1.3.1)
|
||||
letter_opener_web (~> 1.3.2)
|
||||
mdl (~> 0.4.0)
|
||||
newrelic_rpm (~> 4.1.0.333)
|
||||
omniauth (~> 1.8.1)
|
||||
@@ -561,7 +561,7 @@ DEPENDENCIES
|
||||
sass-rails (~> 5.0, >= 5.0.4)
|
||||
savon (~> 2.11.1)
|
||||
scss_lint (~> 0.54.0)
|
||||
sitemap_generator (~> 6.0.0)
|
||||
sitemap_generator (~> 6.0.1)
|
||||
social-share-button (~> 1.1)
|
||||
spring (~> 2.0.1)
|
||||
spring-commands-rspec (~> 1.0.4)
|
||||
|
||||
@@ -83,4 +83,4 @@ App.Map =
|
||||
|
||||
toogleMap: ->
|
||||
$('.map').toggle()
|
||||
$('.location-map-remove-marker-button').toggle()
|
||||
$('.js-location-map-remove-marker').toggle()
|
||||
@@ -22,6 +22,7 @@
|
||||
// 20. Documents
|
||||
// 21. Related content
|
||||
// 22. Images
|
||||
// 23. Maps
|
||||
//
|
||||
|
||||
// 01. Global styles
|
||||
@@ -2427,10 +2428,6 @@ table {
|
||||
margin-bottom: 0 !important;
|
||||
padding: $line-height / 2;
|
||||
|
||||
&:first-child {
|
||||
border-top: 1px solid $border;
|
||||
}
|
||||
|
||||
@include breakpoint(medium) {
|
||||
|
||||
.score-actions {
|
||||
@@ -2439,6 +2436,10 @@ table {
|
||||
}
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-top: 1px solid $border;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #f9f9f9;
|
||||
|
||||
@@ -2478,8 +2479,8 @@ table {
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
|
||||
&.score-positive:before,
|
||||
&.score-negative:before {
|
||||
&.score-positive::before,
|
||||
&.score-negative::before {
|
||||
font-family: 'icons';
|
||||
left: 0;
|
||||
position: absolute;
|
||||
@@ -2488,7 +2489,7 @@ table {
|
||||
&.score-positive {
|
||||
color: $color-success;
|
||||
|
||||
&:before {
|
||||
&::before {
|
||||
color: $color-success;
|
||||
content: '\6c';
|
||||
}
|
||||
@@ -2497,7 +2498,7 @@ table {
|
||||
&.score-negative {
|
||||
color: $color-alert;
|
||||
|
||||
&:before {
|
||||
&::before {
|
||||
color: $color-alert;
|
||||
content: '\76';
|
||||
}
|
||||
@@ -2511,3 +2512,28 @@ table {
|
||||
.images .button {
|
||||
margin-top: $line-height / 2;
|
||||
}
|
||||
|
||||
// 23. Maps
|
||||
// -----------------
|
||||
|
||||
.location-map-remove-marker {
|
||||
border-bottom: 1px dotted #cf2a0e;
|
||||
color: $delete;
|
||||
display: inline-block;
|
||||
margin-top: $line-height / 2;
|
||||
|
||||
&:hover,
|
||||
&:active,
|
||||
&:focus {
|
||||
border-bottom: 1px solid #cf2a0e;
|
||||
color: #cf2a0e;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
|
||||
.leaflet-bar a {
|
||||
|
||||
&.leaflet-disabled {
|
||||
color: #525252 !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,6 +339,7 @@
|
||||
.topic-show,
|
||||
.milestone-content {
|
||||
|
||||
h1,
|
||||
p {
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ class Admin::BudgetsController < Admin::BaseController
|
||||
include FeatureFlags
|
||||
feature_flag :budgets
|
||||
|
||||
has_filters %w{current finished}, only: :index
|
||||
has_filters %w{open finished}, only: :index
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@ class ApplicationController < ActionController::Base
|
||||
|
||||
layout :set_layout
|
||||
respond_to :html
|
||||
helper_method :current_budget
|
||||
|
||||
private
|
||||
|
||||
@@ -120,4 +121,8 @@ class ApplicationController < ActionController::Base
|
||||
params[:filter] ||= "selected"
|
||||
end
|
||||
end
|
||||
|
||||
def current_budget
|
||||
Budget.current
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,7 +19,7 @@ class Management::BudgetsController < Management::BaseController
|
||||
end
|
||||
|
||||
def print_investments
|
||||
@budgets = Budget.current.order(created_at: :desc).page(params[:page])
|
||||
@budget = Budget.current
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
@@ -5,10 +5,10 @@ class Valuation::BudgetsController < Valuation::BaseController
|
||||
load_and_authorize_resource
|
||||
|
||||
def index
|
||||
@budgets = @budgets.current.order(created_at: :desc).page(params[:page])
|
||||
@investments_with_valuation_open = {}
|
||||
@budgets.each do |b|
|
||||
@investments_with_valuation_open[b.id] = b.investments
|
||||
@budget = Budget.current
|
||||
if @budget.present?
|
||||
@investments_with_valuation_open = {}
|
||||
@investments_with_valuation_open = @budget.investments
|
||||
.by_valuator(current_user.valuator.try(:id))
|
||||
.valuation_open
|
||||
.count
|
||||
|
||||
@@ -34,11 +34,11 @@ module MapLocationsHelper
|
||||
end
|
||||
|
||||
def map_location_remove_marker(map_location, text)
|
||||
content_tag :div, class: "text-right" do
|
||||
content_tag :div, class: "margin-bottom" do
|
||||
content_tag :a,
|
||||
id: map_location_remove_marker_link_id(map_location),
|
||||
href: "#",
|
||||
class: "location-map-remove-marker-button delete" do
|
||||
class: "js-location-map-remove-marker location-map-remove-marker" do
|
||||
text
|
||||
end
|
||||
end
|
||||
|
||||
@@ -29,7 +29,12 @@ class Budget < ActiveRecord::Base
|
||||
scope :balloting, -> { where(phase: "balloting") }
|
||||
scope :reviewing_ballots, -> { where(phase: "reviewing_ballots") }
|
||||
scope :finished, -> { where(phase: "finished") }
|
||||
scope :current, -> { where.not(phase: "finished") }
|
||||
|
||||
scope :open, -> { where.not(phase: "finished") }
|
||||
|
||||
def self.current
|
||||
where.not(phase: "drafting").last
|
||||
end
|
||||
|
||||
def current_phase
|
||||
phases.send(phase)
|
||||
@@ -99,10 +104,6 @@ class Budget < ActiveRecord::Base
|
||||
balloting_process? || finished?
|
||||
end
|
||||
|
||||
def current?
|
||||
!finished?
|
||||
end
|
||||
|
||||
def heading_price(heading)
|
||||
heading_ids.include?(heading.id) ? heading.price : -1
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
<% if @investments.any? %>
|
||||
<h3 class="inline-block"><%= page_entries_info @investments %></h3>
|
||||
<table>
|
||||
<table class="table-for-mobile">
|
||||
<thead>
|
||||
<tr>
|
||||
<th><%= t("admin.budget_investments.index.table_id") %></th>
|
||||
|
||||
@@ -1,12 +1,10 @@
|
||||
<table>
|
||||
<% @budgets.each do |budget| %>
|
||||
<tr id="<%= dom_id(budget) %>">
|
||||
<td><%= budget.name %></td>
|
||||
<td><%= budget.translated_phase %></td>
|
||||
<tr id="<%= dom_id(@budget) %>">
|
||||
<td><%= @budget.name %></td>
|
||||
<td><%= @budget.translated_phase %></td>
|
||||
<td align="right">
|
||||
<%= link_to t("management.budgets.print_investments"),
|
||||
print_management_budget_investments_path(budget) %>
|
||||
print_management_budget_investments_path(@budget) %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
<h2 class="inline-block"><%= t("valuation.budgets.index.title") %></h2>
|
||||
|
||||
<h3><%= page_entries_info @budgets %></h3>
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -12,25 +10,21 @@
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @budgets.each do |budget| %>
|
||||
<tr id="<%= dom_id(budget) %>" class="budget">
|
||||
<td>
|
||||
<%= budget.name %>
|
||||
</td>
|
||||
<td>
|
||||
<%= t("budgets.phase.#{budget.phase}") %>
|
||||
</td>
|
||||
<td>
|
||||
<%= @investments_with_valuation_open[budget.id] %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to t("valuation.budgets.index.evaluate"),
|
||||
valuation_budget_budget_investments_path(budget_id: budget.id),
|
||||
class: "button hollow expanded" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<tr id="<%= dom_id(@budget) %>" class="budget">
|
||||
<td>
|
||||
<%= @budget.name %>
|
||||
</td>
|
||||
<td>
|
||||
<%= t("budgets.phase.#{@budget.phase}") %>
|
||||
</td>
|
||||
<td>
|
||||
<%= @investments_with_valuation_open %>
|
||||
</td>
|
||||
<td>
|
||||
<%= link_to t("valuation.budgets.index.evaluate"),
|
||||
valuation_budget_budget_investments_path(budget_id: @budget.id),
|
||||
class: "button hollow expanded" %>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= paginate @budgets %>
|
||||
|
||||
@@ -117,8 +117,8 @@ en:
|
||||
external_url: "Link to additional documentation"
|
||||
heading_id: "Heading"
|
||||
title: "Title"
|
||||
location: "Location"
|
||||
organization_name: "If you are proposing in the name of a collective/organization, write its name"
|
||||
location: "Location (optional)"
|
||||
organization_name: "If you are proposing in the name of a collective/organization, or on behalf of more people, write its name"
|
||||
image: "Proposal descriptive image"
|
||||
image_title: "Image title"
|
||||
budget/investment/milestone:
|
||||
|
||||
@@ -104,7 +104,7 @@ en:
|
||||
unfeasibility_explanation: Unfeasibility explanation
|
||||
code_html: 'Investment project code: <strong>%{code}</strong>'
|
||||
location_html: 'Location: <strong>%{location}</strong>'
|
||||
organization_name_html: 'Organization: <strong>%{name}</strong>'
|
||||
organization_name_html: 'Proposed on behalf of: <strong>%{name}</strong>'
|
||||
share: Share
|
||||
title: Investment project
|
||||
supports: Supports
|
||||
|
||||
@@ -113,7 +113,7 @@ es:
|
||||
external_url: "Enlace a documentación adicional"
|
||||
location: "Ubicación"
|
||||
administrator_id: "Administrador"
|
||||
organization_name: "Si estás proponiendo en nombre de una organización o colectivo, escribe su nombre"
|
||||
organization_name: "Si estás proponiendo en nombre de una organización o colectivo, o en nombre de más gente, escribe su nombre"
|
||||
image: "Imagen descriptiva de la propuesta de inversión"
|
||||
image_title: "Título de la imagen"
|
||||
budget/heading:
|
||||
|
||||
@@ -59,7 +59,7 @@ es:
|
||||
tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')"
|
||||
map_location: "Ubicación en el mapa"
|
||||
map_location_instructions: "Navega por el mapa hasta la ubicación y coloca el marcador."
|
||||
map_remove_marker: "Eliminar el marcador"
|
||||
map_remove_marker: "Eliminar marcador en el mapa"
|
||||
location: "Información adicional de la ubicación"
|
||||
index:
|
||||
title: Presupuestos participativos
|
||||
@@ -104,7 +104,7 @@ es:
|
||||
unfeasibility_explanation: Informe de inviabilidad
|
||||
code_html: 'Código propuesta de gasto: <strong>%{code}</strong>'
|
||||
location_html: 'Ubicación: <strong>%{location}</strong>'
|
||||
organization_name_html: 'Organización: <strong>%{name}</strong>'
|
||||
organization_name_html: 'Propuesto en nombre de: <strong>%{name}</strong>'
|
||||
share: Compartir
|
||||
title: Proyecto de inversión
|
||||
supports: Apoyos
|
||||
|
||||
@@ -338,7 +338,7 @@ es:
|
||||
tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')"
|
||||
map_location: "Ubicación en el mapa"
|
||||
map_location_instructions: "Navega por el mapa hasta la ubicación y coloca el marcador."
|
||||
map_remove_marker: "Eliminar el marcador"
|
||||
map_remove_marker: "Eliminar marcador en el mapa"
|
||||
map_skip_checkbox: "Esta propuesta no tiene una ubicación concreta o no la conozco."
|
||||
index:
|
||||
featured_proposals: Destacadas
|
||||
|
||||
@@ -17,11 +17,11 @@ apis: &apis
|
||||
http_basic_auth: &http_basic_auth
|
||||
http_basic_auth: true
|
||||
|
||||
|
||||
development:
|
||||
http_basic_username: "dev"
|
||||
http_basic_password: "pass"
|
||||
<<: *default
|
||||
<<: *maps
|
||||
|
||||
test:
|
||||
<<: *default
|
||||
|
||||
19
spec/controllers/application_controller_spec.rb
Normal file
19
spec/controllers/application_controller_spec.rb
Normal file
@@ -0,0 +1,19 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe ApplicationController do
|
||||
|
||||
describe "#current_budget" do
|
||||
|
||||
it "returns the last budget that is not in draft phase" do
|
||||
old_budget = create(:budget, phase: "finished", created_at: 2.years.ago)
|
||||
previous_budget = create(:budget, phase: "accepting", created_at: 1.year.ago)
|
||||
current_budget = create(:budget, phase: "accepting", created_at: 1.month.ago)
|
||||
next_budget = create(:budget, phase: "drafting", created_at: 1.week.ago)
|
||||
|
||||
budget = subject.instance_eval{ current_budget }
|
||||
expect(budget).to eq(current_budget)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
@@ -259,9 +259,10 @@ feature 'Budget Investments' do
|
||||
context "Printing" do
|
||||
|
||||
scenario 'Printing budget investments' do
|
||||
16.times { create(:budget_investment, budget: @budget) }
|
||||
16.times { create(:budget_investment, budget: @budget, heading: @heading) }
|
||||
|
||||
click_link "Print Budget Investments"
|
||||
|
||||
expect(page).to have_content(@budget.name)
|
||||
within "#budget_#{@budget.id}" do
|
||||
click_link "Print Budget Investments"
|
||||
@@ -273,15 +274,17 @@ feature 'Budget Investments' do
|
||||
|
||||
scenario "Filtering budget investments by heading to be printed", :js do
|
||||
district_9 = create(:budget_heading, group: @group, name: "District Nine")
|
||||
another_heading = create(:budget_heading, group: @group)
|
||||
low_investment = create(:budget_investment, budget: @budget, title: 'Nuke district 9', heading: district_9, cached_votes_up: 1)
|
||||
mid_investment = create(:budget_investment, budget: @budget, title: 'Change district 9', heading: district_9, cached_votes_up: 10)
|
||||
top_investment = create(:budget_investment, budget: @budget, title: 'Destroy district 9', heading: district_9, cached_votes_up: 100)
|
||||
unvoted_investment = create(:budget_investment, budget: @budget, title: 'Add new districts to the city')
|
||||
unvoted_investment = create(:budget_investment, budget: @budget, heading: another_heading, title: 'Add new districts to the city')
|
||||
|
||||
user = create(:user, :level_two)
|
||||
login_managed_user(user)
|
||||
|
||||
click_link "Print Budget Investments"
|
||||
|
||||
expect(page).to have_content(@budget.name)
|
||||
within "#budget_#{@budget.id}" do
|
||||
click_link "Print Budget Investments"
|
||||
|
||||
@@ -24,18 +24,15 @@ feature 'Valuation budgets' do
|
||||
end
|
||||
|
||||
scenario 'Filters by phase' do
|
||||
budget1 = create(:budget)
|
||||
budget2 = create(:budget, :accepting)
|
||||
budget3 = create(:budget, :selecting)
|
||||
budget4 = create(:budget, :balloting)
|
||||
budget5 = create(:budget, :finished)
|
||||
budget1 = create(:budget, :finished)
|
||||
budget2 = create(:budget, :finished)
|
||||
budget3 = create(:budget, :accepting)
|
||||
|
||||
visit valuation_budgets_path
|
||||
expect(page).to have_content(budget1.name)
|
||||
expect(page).to have_content(budget2.name)
|
||||
|
||||
expect(page).to_not have_content(budget1.name)
|
||||
expect(page).to_not have_content(budget2.name)
|
||||
expect(page).to have_content(budget3.name)
|
||||
expect(page).to have_content(budget4.name)
|
||||
expect(page).not_to have_content(budget5.name)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -66,6 +66,8 @@ feature 'Valuation' do
|
||||
|
||||
scenario 'Access as a valuator is authorized' do
|
||||
create(:valuator, user: user)
|
||||
create(:budget)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
@@ -78,6 +80,8 @@ feature 'Valuation' do
|
||||
|
||||
scenario 'Access as an administrator is authorized' do
|
||||
create(:administrator, user: user)
|
||||
create(:budget)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
@@ -90,6 +94,8 @@ feature 'Valuation' do
|
||||
|
||||
scenario "Valuation access links" do
|
||||
create(:valuator, user: user)
|
||||
create(:budget)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
@@ -100,6 +106,8 @@ feature 'Valuation' do
|
||||
|
||||
scenario 'Valuation dashboard' do
|
||||
create(:valuator, user: user)
|
||||
create(:budget)
|
||||
|
||||
login_as(user)
|
||||
visit root_path
|
||||
|
||||
|
||||
@@ -118,6 +118,43 @@ describe Budget do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#current" do
|
||||
|
||||
it "returns nil if there is only one budget and it is still in drafting phase" do
|
||||
budget = create(:budget, phase: "drafting")
|
||||
|
||||
expect(Budget.current).to eq(nil)
|
||||
end
|
||||
|
||||
it "returns the budget if there is only one and not in drafting phase" do
|
||||
budget = create(:budget, phase: "accepting")
|
||||
|
||||
expect(Budget.current).to eq(budget)
|
||||
end
|
||||
|
||||
it "returns the last budget created that is not in drafting phase" do
|
||||
old_budget = create(:budget, phase: "finished", created_at: 2.years.ago)
|
||||
previous_budget = create(:budget, phase: "accepting", created_at: 1.year.ago)
|
||||
current_budget = create(:budget, phase: "accepting", created_at: 1.month.ago)
|
||||
next_budget = create(:budget, phase: "drafting", created_at: 1.week.ago)
|
||||
|
||||
expect(Budget.current).to eq(current_budget)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "#open" do
|
||||
|
||||
it "returns all budgets that are not in the finished phase" do
|
||||
phases = Budget::PHASES - ["finished"]
|
||||
phases.each do |phase|
|
||||
budget = create(:budget, phase: phase)
|
||||
expect(Budget.open).to include(budget)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "heading_price" do
|
||||
let(:group) { create(:budget_group, budget: budget) }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user