Merge branch 'master' into polls

This commit is contained in:
Juanjo Bazán
2017-01-19 16:51:19 +01:00
254 changed files with 10658 additions and 871 deletions

View File

@@ -0,0 +1,17 @@
class Admin::BudgetGroupsController < Admin::BaseController
include FeatureFlags
feature_flag :budgets
def create
@budget = Budget.find params[:budget_id]
@budget.groups.create(budget_group_params)
@groups = @budget.groups.includes(:headings)
end
private
def budget_group_params
params.require(:budget_group).permit(:name)
end
end

View File

@@ -0,0 +1,18 @@
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
end
private
def budget_heading_params
params.require(:budget_heading).permit(:name, :price, :geozone_id)
end
end

View File

@@ -0,0 +1,86 @@
class Admin::BudgetInvestmentsController < Admin::BaseController
include FeatureFlags
feature_flag :budgets
has_filters(%w{valuation_open without_admin managed valuating valuation_finished
valuation_finished_feasible selected all},
only: [:index, :toggle_selection])
before_action :load_budget
before_action :load_investment, only: [:show, :edit, :update, :toggle_selection]
before_action :load_ballot, only: [:show, :index]
before_action :load_investments, only: [:index, :toggle_selection]
def index
end
def show
end
def edit
load_admins
load_valuators
load_tags
end
def update
set_valuation_tags
if @investment.update(budget_investment_params)
redirect_to admin_budget_budget_investment_path(@budget, @investment, Budget::Investment.filter_params(params)),
notice: t("flash.actions.update.budget_investment")
else
load_admins
load_valuators
load_tags
render :edit
end
end
def toggle_selection
@investment.toggle :selected
@investment.save
end
private
def load_investments
@investments = Budget::Investment.scoped_filter(params, @current_filter)
.order(cached_votes_up: :desc, created_at: :desc)
.page(params[:page])
end
def budget_investment_params
params.require(:budget_investment)
.permit(:title, :description, :external_url, :heading_id, :administrator_id, :valuation_tag_list, valuator_ids: [])
end
def load_budget
@budget = Budget.includes(:groups).find params[:budget_id]
end
def load_investment
@investment = Budget::Investment.where(budget_id: @budget.id).find params[:id]
end
def load_admins
@admins = Administrator.includes(:user).all
end
def load_valuators
@valuators = Valuator.includes(:user).all.order("description ASC").order("users.email ASC")
end
def load_tags
@tags = Budget::Investment.tags_on(:valuation).order(:name).uniq
end
def load_ballot
query = Budget::Ballot.where(user: current_user, budget: @budget)
@ballot = @budget.balloting? ? query.first_or_create : query.first_or_initialize
end
def set_valuation_tags
@investment.set_tag_list_on(:valuation, budget_investment_params[:valuation_tag_list])
params[:budget_investment] = params[:budget_investment].except(:valuation_tag_list)
end
end

View File

@@ -0,0 +1,48 @@
class Admin::BudgetsController < Admin::BaseController
include FeatureFlags
feature_flag :budgets
has_filters %w{current finished}, only: :index
load_and_authorize_resource
def index
@budgets = Budget.send(@current_filter).order(created_at: :desc).page(params[:page])
end
def show
@budget = Budget.includes(groups: :headings).find(params[:id])
end
def new
end
def edit
end
def update
if @budget.update(budget_params)
redirect_to admin_budget_path(@budget), notice: t('admin.budgets.update.notice')
else
render :edit
end
end
def create
@budget = Budget.new(budget_params)
if @budget.save
redirect_to admin_budget_path(@budget), notice: t('admin.budgets.create.notice')
else
render :new
end
end
private
def budget_params
descriptions = Budget::PHASES.map{|p| "description_#{p}"}.map(&:to_sym)
valid_attributes = [:name, :phase, :currency_symbol] + descriptions
params.require(:budget).permit(*valid_attributes)
end
end

View File

@@ -0,0 +1,78 @@
module Budgets
module Ballot
class LinesController < ApplicationController
before_action :authenticate_user!
#before_action :ensure_final_voting_allowed
before_action :load_budget
before_action :load_ballot
before_action :load_tag_cloud
before_action :load_categories
before_action :load_investments
load_and_authorize_resource :budget
load_and_authorize_resource :ballot, class: "Budget::Ballot", through: :budget
load_and_authorize_resource :line, through: :ballot, find_by: :investment_id, class: "Budget::Ballot::Line"
def create
load_investment
load_heading
unless @ballot.add_investment(@investment)
head :bad_request
end
end
def destroy
@investment = @line.investment
load_heading
@line.destroy
load_investments
#@ballot.reset_geozone
end
private
def ensure_final_voting_allowed
return head(:forbidden) unless @budget.balloting?
end
def line_params
params.permit(:investment_id, :budget_id)
end
def load_budget
@budget = Budget.find(params[:budget_id])
end
def load_ballot
@ballot = Budget::Ballot.where(user: current_user, budget: @budget).first_or_create
end
def load_investment
@investment = Budget::Investment.find(params[:investment_id])
end
def load_investments
if params[:investments_ids].present?
@investment_ids = params[:investment_ids]
@investments = Budget::Investment.where(id: params[:investments_ids])
end
end
def load_heading
@heading = @investment.heading
end
def load_tag_cloud
@tag_cloud = TagCloud.new(Budget::Investment, params[:search])
end
def load_categories
@categories = ActsAsTaggableOn::Tag.where("kind = 'category'").order(:name)
end
end
end
end

View File

@@ -0,0 +1,20 @@
module Budgets
class BallotsController < ApplicationController
before_action :authenticate_user!
load_and_authorize_resource :budget
before_action :load_ballot
def show
authorize! :show, @ballot
render template: "budgets/ballot/show"
end
private
def load_ballot
query = Budget::Ballot.where(user: current_user, budget: @budget)
@ballot = @budget.balloting? ? query.first_or_create : query.first_or_initialize
end
end
end

View File

@@ -0,0 +1,10 @@
module Budgets
class GroupsController < ApplicationController
load_and_authorize_resource :budget
load_and_authorize_resource :group, class: "Budget::Group"
def show
end
end
end

View File

@@ -0,0 +1,111 @@
module Budgets
class InvestmentsController < ApplicationController
include FeatureFlags
include CommentableActions
include FlagActions
before_action :authenticate_user!, except: [:index, :show]
load_and_authorize_resource :budget
load_and_authorize_resource :investment, through: :budget, class: "Budget::Investment"
before_action -> { flash.now[:notice] = flash[:notice].html_safe if flash[:html_safe] && flash[:notice] }
before_action :load_ballot, only: [:index, :show]
before_action :load_heading, only: [:index, :show]
before_action :set_random_seed, only: :index
before_action :load_categories, only: [:index, :new, :create]
feature_flag :budgets
has_orders %w{most_voted newest oldest}, only: :show
has_orders ->(c) { c.instance_variable_get(:@budget).investments_orders }, only: :index
invisible_captcha only: [:create, :update], honeypot: :subtitle, scope: :budget_investment
respond_to :html, :js
def index
@investments = @investments.apply_filters_and_search(@budget, params).send("sort_by_#{@current_order}").page(params[:page]).per(10).for_render
@investment_ids = @investments.pluck(:id)
load_investment_votes(@investments)
@tag_cloud = tag_cloud
end
def new
end
def show
@commentable = @investment
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
set_comment_flags(@comment_tree.comments)
load_investment_votes(@investment)
@investment_ids = [@investment.id]
end
def create
@investment.author = current_user
if @investment.save
Mailer.budget_investment_created(@investment).deliver_later
redirect_to budget_investment_path(@budget, @investment),
notice: t('flash.actions.create.budget_investment')
else
render :new
end
end
def destroy
investment.destroy
redirect_to user_path(current_user, filter: 'budget_investments'), notice: t('flash.actions.destroy.budget_investment')
end
def vote
@investment.register_selection(current_user)
load_investment_votes(@investment)
respond_to do |format|
format.html { redirect_to budget_investments_path(heading_id: @investment.heading.id) }
format.js
end
end
private
def load_investment_votes(investments)
@investment_votes = current_user ? current_user.budget_investment_votes(investments) : {}
end
def set_random_seed
if params[:order] == 'random' || params[:order].blank?
params[:random_seed] ||= rand(99)/100.0
Budget::Investment.connection.execute "select setseed(#{params[:random_seed]})"
else
params[:random_seed] = nil
end
end
def investment_params
params.require(:budget_investment).permit(:title, :description, :external_url, :heading_id, :tag_list, :organization_name, :location, :terms_of_service)
end
def load_ballot
query = Budget::Ballot.where(user: current_user, budget: @budget)
@ballot = @budget.balloting? ? query.first_or_create : query.first_or_initialize
end
def load_heading
if params[:heading_id].present?
@heading = @budget.headings.find(params[:heading_id])
@assigned_heading = @ballot.try(:heading_for_group, @heading.try(:group))
end
end
def load_categories
@categories = ActsAsTaggableOn::Tag.where("kind = 'category'").order(:name)
end
def tag_cloud
TagCloud.new(Budget::Investment, params[:search])
end
end
end

View File

@@ -0,0 +1,15 @@
class BudgetsController < ApplicationController
include FeatureFlags
feature_flag :budgets
load_and_authorize_resource
respond_to :html, :js
def show
end
def index
@budgets = @budgets.order(:created_at)
end
end

View File

@@ -3,8 +3,9 @@ module HasOrders
class_methods do
def has_orders(valid_orders, *args)
before_action(*args) do
@valid_orders = valid_orders
before_action(*args) do |c|
@valid_orders = valid_orders.respond_to?(:call) ? valid_orders.call(c) : valid_orders.dup
@valid_orders.delete('relevance') if params[:search].blank?
@current_order = @valid_orders.include?(params[:order]) ? params[:order] : @valid_orders.first
end
end

View File

@@ -0,0 +1,70 @@
class Management::Budgets::InvestmentsController < Management::BaseController
load_resource :budget
load_resource :investment, through: :budget, class: 'Budget::Investment'
before_action :only_verified_users, except: :print
before_action :load_heading, only: [:index, :show, :print]
def index
@investments = @investments.apply_filters_and_search(@budget, params).page(params[:page])
load_investment_votes(@investments)
end
def new
load_categories
end
def create
@investment.terms_of_service = "1"
@investment.author = managed_user
if @investment.save
notice= t('flash.actions.create.notice', resource_name: Budget::Investment.model_name.human, count: 1)
redirect_to management_budget_investment_path(@budget, @investment), notice: notice
else
render :new
end
end
def show
load_investment_votes(@investment)
end
def vote
@investment.register_selection(managed_user)
load_investment_votes(@investment)
respond_to do |format|
format.html { redirect_to management_budget_investments_path(heading_id: @investment.heading.id) }
format.js
end
end
def print
@investments = @investments.apply_filters_and_search(@budget, params).order(cached_votes_up: :desc).for_render.limit(15)
load_investment_votes(@investments)
end
private
def load_investment_votes(investments)
@investment_votes = managed_user ? managed_user.budget_investment_votes(investments) : {}
end
def investment_params
params.require(:budget_investment).permit(:title, :description, :external_url, :heading_id)
end
def only_verified_users
check_verified_user t("management.budget_investments.alert.unverified_user")
end
def load_heading
@heading = @budget.headings.find(params[:heading_id]) if params[:heading_id].present?
end
def load_categories
@categories = ActsAsTaggableOn::Tag.where("kind = 'category'").order(:name)
end
end

View File

@@ -0,0 +1,26 @@
class Management::BudgetsController < Management::BaseController
include FeatureFlags
include HasFilters
feature_flag :budgets
before_action :only_verified_users, except: :print_investments
def create_investments
@budgets = Budget.accepting.order(created_at: :desc).page(params[:page])
end
def support_investments
@budgets = Budget.selecting.order(created_at: :desc).page(params[:page])
end
def print_investments
@budgets = Budget.current.order(created_at: :desc).page(params[:page])
end
private
def only_verified_users
check_verified_user t("management.budget_investments.alert.unverified_user")
end
end

View File

@@ -1,8 +1,7 @@
class UsersController < ApplicationController
has_filters %w{proposals debates comments spending_proposals}, only: :show
has_filters %w{proposals debates budget_investments comments}, only: :show
load_and_authorize_resource
helper_method :authorized_for_filter?
helper_method :author?
helper_method :author_or_admin?
@@ -14,9 +13,9 @@ class UsersController < ApplicationController
def set_activity_counts
@activity_counts = HashWithIndifferentAccess.new(
proposals: Proposal.where(author_id: @user.id).count,
debates: Debate.where(author_id: @user.id).count,
comments: Comment.not_as_admin_or_moderator.where(user_id: @user.id).count,
spending_proposals: SpendingProposal.where(author_id: @user.id).count)
debates: (Setting['feature.debates'] ? Debate.where(author_id: @user.id).count : 0),
budget_investments: (Setting['feature.budgets'] ? Budget::Investment.where(author_id: @user.id).count : 0),
comments: only_active_commentables.count)
end
def load_filtered_activity
@@ -24,8 +23,8 @@ class UsersController < ApplicationController
case params[:filter]
when "proposals" then load_proposals
when "debates" then load_debates
when "budget_investments" then load_budget_investments
when "comments" then load_comments
when "spending_proposals" then load_spending_proposals if author_or_admin?
else load_available_activity
end
end
@@ -34,15 +33,15 @@ class UsersController < ApplicationController
if @activity_counts[:proposals] > 0
load_proposals
@current_filter = "proposals"
elsif @activity_counts[:debates] > 0
elsif @activity_counts[:debates] > 0
load_debates
@current_filter = "debates"
elsif @activity_counts[:budget_investments] > 0
load_budget_investments
@current_filter = "budget_investments"
elsif @activity_counts[:comments] > 0
load_comments
@current_filter = "comments"
elsif @activity_counts[:spending_proposals] > 0 && author_or_admin?
load_spending_proposals
@current_filter = "spending_proposals"
end
end
@@ -55,11 +54,11 @@ class UsersController < ApplicationController
end
def load_comments
@comments = Comment.not_as_admin_or_moderator.where(user_id: @user.id).includes(:commentable).order(created_at: :desc).page(params[:page])
@comments = only_active_commentables.includes(:commentable).order(created_at: :desc).page(params[:page])
end
def load_spending_proposals
@spending_proposals = SpendingProposal.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
def load_budget_investments
@budget_investments = Budget::Investment.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
end
def valid_access?
@@ -78,7 +77,19 @@ class UsersController < ApplicationController
@authorized_current_user ||= current_user && (current_user == @user || current_user.moderator? || current_user.administrator?)
end
def authorized_for_filter?(filter)
filter == "spending_proposals" ? author_or_admin? : true
def all_user_comments
Comment.not_as_admin_or_moderator.where(user_id: @user.id)
end
def only_active_commentables
disabled_commentables = []
disabled_commentables << "Debate" unless Setting['feature.debates']
disabled_commentables << "Budget::Investment" unless Setting['feature.budgets']
if disabled_commentables.present?
all_user_comments.where("commentable_type NOT IN (?)", disabled_commentables)
else
all_user_comments
end
end
end

View File

@@ -0,0 +1,84 @@
class Valuation::BudgetInvestmentsController < Valuation::BaseController
include FeatureFlags
feature_flag :budgets
before_action :restrict_access_to_assigned_items, only: [:show, :edit, :valuate]
before_action :load_budget
before_action :load_investment, only: [:show, :edit, :valuate]
has_filters %w{valuating valuation_finished}, only: :index
load_and_authorize_resource :investment, class: "Budget::Investment"
def index
@heading_filters = heading_filters
if current_user.valuator? && @budget.present?
@investments = @budget.investments.scoped_filter(params_for_current_valuator, @current_filter).order(cached_votes_up: :desc).page(params[:page])
else
@investments = Budget::Investment.none.page(params[:page])
end
end
def valuate
if valid_price_params? && @investment.update(valuation_params)
if @investment.unfeasible_email_pending?
@investment.send_unfeasible_email
end
redirect_to valuation_budget_budget_investment_path(@budget, @investment), notice: t('valuation.budget_investments.notice.valuate')
else
render action: :edit
end
end
private
def load_budget
@budget = Budget.find(params[:budget_id])
end
def load_investment
@investment = @budget.investments.find params[:id]
end
def heading_filters
investments = @budget.investments.by_valuator(current_user.valuator.try(:id)).valuation_open.select(:heading_id).all.to_a
[ { name: t('valuation.budget_investments.index.headings_filter_all'),
id: nil,
pending_count: investments.size
}
] + Budget::Heading.where(id: investments.map(&:heading_id).uniq).order(name: :asc).collect do |h|
{ name: h.name,
id: h.id,
pending_count: investments.count{|x| x.heading_id == h.id}
}
end
end
def params_for_current_valuator
Budget::Investment.filter_params(params).merge({valuator_id: current_user.valuator.id, budget_id: @budget.id})
end
def valuation_params
params.require(:budget_investment).permit(:price, :price_first_year, :price_explanation, :feasibility, :unfeasibility_explanation, :duration, :valuation_finished, :internal_comments)
end
def restrict_access_to_assigned_items
raise ActionController::RoutingError.new('Not Found') unless current_user.administrator? || Budget::ValuatorAssignment.exists?(investment_id: params[:id], valuator_id: current_user.valuator.id)
end
def valid_price_params?
if /\D/.match params[:budget_investment][:price]
@investment.errors.add(:price, I18n.t('budgets.investments.wrong_price_format'))
end
if /\D/.match params[:budget_investment][:price_first_year]
@investment.errors.add(:price_first_year, I18n.t('budgets.investments.wrong_price_format'))
end
@investment.errors.empty?
end
end

View File

@@ -0,0 +1,17 @@
class Valuation::BudgetsController < Valuation::BaseController
include FeatureFlags
feature_flag :budgets
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
.by_valuator(current_user.valuator.try(:id))
.valuation_open
.count
end
end
end