diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 44258bc7a..0d5b962c1 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -33,6 +33,7 @@
//= require moderator_comment
//= require moderator_debates
//= require moderator_proposals
+//= require moderator_budget_investments
//= require moderator_proposal_notifications
//= require prevent_double_submission
//= require gettext
diff --git a/app/assets/javascripts/moderator_budget_investments.js.coffee b/app/assets/javascripts/moderator_budget_investments.js.coffee
new file mode 100644
index 000000000..612a058a4
--- /dev/null
+++ b/app/assets/javascripts/moderator_budget_investments.js.coffee
@@ -0,0 +1,8 @@
+App.ModeratorBudgetInvestments =
+
+ add_class_faded: (id) ->
+ $("##{id}").addClass("faded")
+ $("#comments").addClass("faded")
+
+ hide_moderator_actions: (id) ->
+ $("##{id} .js-moderator-investment-actions:first").hide()
diff --git a/app/controllers/admin/hidden_budget_investments_controller.rb b/app/controllers/admin/hidden_budget_investments_controller.rb
new file mode 100644
index 000000000..439f3c722
--- /dev/null
+++ b/app/controllers/admin/hidden_budget_investments_controller.rb
@@ -0,0 +1,34 @@
+class Admin::HiddenBudgetInvestmentsController < Admin::BaseController
+ include FeatureFlags
+
+ has_filters %w{all with_confirmed_hide without_confirmed_hide}, only: :index
+
+ feature_flag :budgets
+
+ before_action :load_investment, only: [:confirm_hide, :restore]
+
+ def index
+ @investments = Budget::Investment.only_hidden.send(@current_filter)
+ .order(hidden_at: :desc)
+ .page(params[:page])
+ end
+
+ def confirm_hide
+ @investment.confirm_hide
+ redirect_to request.query_parameters.merge(action: :index)
+ end
+
+ def restore
+ @investment.restore
+ @investment.ignore_flag
+ Activity.log(current_user, :restore, @investment)
+ redirect_to request.query_parameters.merge(action: :index)
+ end
+
+ private
+
+ def load_investment
+ @investment = Budget::Investment.with_hidden.find(params[:id])
+ end
+
+end
diff --git a/app/controllers/concerns/flag_actions.rb b/app/controllers/concerns/flag_actions.rb
index 3f5d0b2c7..da637407a 100644
--- a/app/controllers/concerns/flag_actions.rb
+++ b/app/controllers/concerns/flag_actions.rb
@@ -3,18 +3,32 @@ module FlagActions
def flag
Flag.flag(current_user, flaggable)
- respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
+
+ if controller_name == 'investments'
+ respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
+ else
+ respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
+ end
end
def unflag
Flag.unflag(current_user, flaggable)
- respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
+
+ if controller_name == 'investments'
+ respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
+ else
+ respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
+ end
end
private
def flaggable
- instance_variable_get("@#{resource_model.to_s.downcase}")
+ if resource_model.to_s == 'Budget::Investment'
+ instance_variable_get("@investment")
+ else
+ instance_variable_get("@#{resource_model.to_s.downcase}")
+ end
end
-end
\ No newline at end of file
+end
diff --git a/app/controllers/concerns/polymorphic.rb b/app/controllers/concerns/polymorphic.rb
index 8fd4ab312..0e25b4231 100644
--- a/app/controllers/concerns/polymorphic.rb
+++ b/app/controllers/concerns/polymorphic.rb
@@ -3,7 +3,11 @@ module Polymorphic
private
def resource
- @resource ||= instance_variable_get("@#{resource_name}")
+ if resource_model.to_s == 'Budget::Investment'
+ @resource ||= instance_variable_get("@investment")
+ else
+ @resource ||= instance_variable_get("@#{resource_name}")
+ end
end
def resource_name
diff --git a/app/controllers/moderation/budgets/investments_controller.rb b/app/controllers/moderation/budgets/investments_controller.rb
new file mode 100644
index 000000000..7f33058e8
--- /dev/null
+++ b/app/controllers/moderation/budgets/investments_controller.rb
@@ -0,0 +1,24 @@
+class Moderation::Budgets::InvestmentsController < Moderation::BaseController
+ include FeatureFlags
+ include ModerateActions
+
+ has_filters %w{pending_flag_review all with_ignored_flag}, only: :index
+ has_orders %w{flags created_at}, only: :index
+
+ feature_flag :budgets
+
+ before_action :load_resources, only: [:index, :moderate]
+
+ load_and_authorize_resource class: 'Budget::Investment'
+
+ private
+
+ def resource_name
+ 'budget_investment'
+ end
+
+ def resource_model
+ Budget::Investment
+ end
+
+end
diff --git a/app/controllers/stats_controller.rb b/app/controllers/stats_controller.rb
index 7130e661d..7bb872257 100644
--- a/app/controllers/stats_controller.rb
+++ b/app/controllers/stats_controller.rb
@@ -14,6 +14,7 @@ class StatsController < ApplicationController
@debate_votes = daily_cache('debate_votes') { Vote.where(votable_type: 'Debate').count }
@proposal_votes = daily_cache('proposal_votes') { Vote.where(votable_type: 'Proposal').count }
@comment_votes = daily_cache('comment_votes') { Vote.where(votable_type: 'Comment').count }
+ @investment_votes = daily_cache('budget_investment_votes') { Vote.where(votable_type: 'Budget::Investment').count }
@votes = daily_cache('votes') { Vote.count }
@verified_users = daily_cache('verified_users') { User.with_hidden.level_two_or_three_verified.count }
diff --git a/app/helpers/admin_helper.rb b/app/helpers/admin_helper.rb
index 2c1a32c70..8a32e5630 100644
--- a/app/helpers/admin_helper.rb
+++ b/app/helpers/admin_helper.rb
@@ -1,19 +1,31 @@
module AdminHelper
def side_menu
- render "/#{namespace}/menu"
+ if namespace == 'moderation/budgets'
+ render "/moderation/menu"
+ else
+ render "/#{namespace}/menu"
+ end
end
def namespaced_root_path
- "/#{namespace}"
+ if namespace == 'moderation/budgets'
+ "/moderation"
+ else
+ "/#{namespace}"
+ end
end
def namespaced_header_title
- t("#{namespace}.header.title")
+ if namespace == 'moderation/budgets'
+ t("moderation.header.title")
+ else
+ t("#{namespace}.header.title")
+ end
end
def menu_moderated_content?
- ["proposals", "debates", "comments", "hidden_users", "activity"].include?(controller_name) && controller.class.parent != Admin::Legislation
+ ["proposals", "debates", "comments", "hidden_users", "activity", "hidden_budget_investments"].include?(controller_name) && controller.class.parent != Admin::Legislation
end
def menu_budget?
diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb
index e8bb005d4..40e951326 100644
--- a/app/models/abilities/administrator.rb
+++ b/app/models/abilities/administrator.rb
@@ -17,6 +17,9 @@ module Abilities
can :restore, Legislation::Proposal
cannot :restore, Legislation::Proposal, hidden_at: nil
+ can :restore, Budget::Investment
+ cannot :restore, Budget::Investment, hidden_at: nil
+
can :restore, User
cannot :restore, User, hidden_at: nil
@@ -32,6 +35,9 @@ module Abilities
can :confirm_hide, Legislation::Proposal
cannot :confirm_hide, Legislation::Proposal, hidden_at: nil
+ can :confirm_hide, Budget::Investment
+ cannot :confirm_hide, Budget::Investment, hidden_at: nil
+
can :confirm_hide, User
cannot :confirm_hide, User, hidden_at: nil
diff --git a/app/models/abilities/common.rb b/app/models/abilities/common.rb
index d8d716ec2..7c84089b4 100644
--- a/app/models/abilities/common.rb
+++ b/app/models/abilities/common.rb
@@ -46,6 +46,9 @@ module Abilities
can [:flag, :unflag], Legislation::Proposal
cannot [:flag, :unflag], Legislation::Proposal, author_id: user.id
+ can [:flag, :unflag], Budget::Investment
+ cannot [:flag, :unflag], Budget::Investment, author_id: user.id
+
can [:create, :destroy], Follow
can [:destroy], Document, documentable: { author_id: user.id }
diff --git a/app/models/abilities/moderation.rb b/app/models/abilities/moderation.rb
index 801e752ed..86f44f25e 100644
--- a/app/models/abilities/moderation.rb
+++ b/app/models/abilities/moderation.rb
@@ -63,6 +63,15 @@ module Abilities
cannot :moderate, ProposalNotification, author_id: user.id
can :index, ProposalNotification
+
+ can :hide, Budget::Investment, hidden_at: nil
+ cannot :hide, Budget::Investment, author_id: user.id
+
+ can :ignore_flag, Budget::Investment, ignored_flag_at: nil, hidden_at: nil
+ cannot :ignore_flag, Budget::Investment, author_id: user.id
+
+ can :moderate, Budget::Investment
+ cannot :moderate, Budget::Investment, author_id: user.id
end
end
end
diff --git a/app/models/budget/investment.rb b/app/models/budget/investment.rb
index d69a0d64a..e531612a8 100644
--- a/app/models/budget/investment.rb
+++ b/app/models/budget/investment.rb
@@ -23,6 +23,7 @@ class Budget
include Relationable
include Notifiable
include Filterable
+ include Flaggable
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
belongs_to :heading
@@ -81,6 +82,8 @@ class Budget
scope :winners, -> { selected.compatible.where(winner: true) }
scope :unselected, -> { not_unfeasible.where(selected: false) }
scope :last_week, -> { where("created_at >= ?", 7.days.ago)}
+ scope :sort_by_flags, -> { order(flags_count: :desc, updated_at: :desc) }
+ scope :sort_by_created_at, -> { reorder(created_at: :desc) }
scope :by_budget, ->(budget) { where(budget: budget) }
scope :by_group, ->(group_id) { where(group_id: group_id) }
diff --git a/app/models/user.rb b/app/models/user.rb
index 67fe5d104..4b999207d 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -182,6 +182,7 @@ class User < ActiveRecord::Base
debates_ids = Debate.where(author_id: id).pluck(:id)
comments_ids = Comment.where(user_id: id).pluck(:id)
proposal_ids = Proposal.where(author_id: id).pluck(:id)
+ investment_ids = Budget::Investment.where(author_id: id).pluck(:id)
proposal_notification_ids = ProposalNotification.where(author_id: id).pluck(:id)
hide
@@ -189,6 +190,7 @@ class User < ActiveRecord::Base
Debate.hide_all debates_ids
Comment.hide_all comments_ids
Proposal.hide_all proposal_ids
+ Budget::Investment.hide_all investment_ids
ProposalNotification.hide_all proposal_notification_ids
end
diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb
index 78ce6b351..8385b8742 100644
--- a/app/views/admin/_menu.html.erb
+++ b/app/views/admin/_menu.html.erb
@@ -151,6 +151,12 @@
<% end %>
+ <% if feature?(:budgets) %>
+
>
+ <%= link_to t("admin.menu.hidden_budget_investments"), admin_hidden_budget_investments_path %>
+
+ <% end %>
+
>
<%= link_to t("admin.menu.hidden_comments"), admin_comments_path %>
diff --git a/app/views/admin/hidden_budget_investments/index.html.erb b/app/views/admin/hidden_budget_investments/index.html.erb
new file mode 100644
index 000000000..68f5f6ce6
--- /dev/null
+++ b/app/views/admin/hidden_budget_investments/index.html.erb
@@ -0,0 +1,49 @@
+<%= t("admin.hidden_budget_investments.index.title") %>
+<%= t("admin.shared.moderated_content") %>
+
+<%= render 'shared/filter_subnav', i18n_namespace: "admin.hidden_budget_investments.index" %>
+
+<% if @investments.any? %>
+ <%= page_entries_info @investments %>
+
+
+
+ | <%= t("admin.shared.title") %> |
+ <%= t("admin.shared.description") %> |
+ <%= t("admin.shared.actions") %> |
+
+
+ <% @investments.each do |investment| %>
+
+ |
+ <%= investment.title %>
+ |
+
+
+ <%= investment.description %>
+
+ |
+
+ <%= link_to t("admin.actions.restore"),
+ restore_admin_hidden_budget_investment_path(investment, request.query_parameters),
+ method: :put,
+ data: { confirm: t("admin.actions.confirm") },
+ class: "button hollow warning" %>
+ <% unless investment.confirmed_hide? %>
+ <%= link_to t("admin.actions.confirm_hide"),
+ confirm_hide_admin_hidden_budget_investment_path(investment, request.query_parameters),
+ method: :put,
+ class: "button" %>
+ <% end %>
+ |
+
+ <% end %>
+
+
+
+ <%= paginate @investments %>
+<% else %>
+
+ <%= t("admin.hidden_budget_investments.index.no_hidden_budget_investments") %>
+
+<% end %>
diff --git a/app/views/budgets/investments/_actions.html.erb b/app/views/budgets/investments/_actions.html.erb
new file mode 100644
index 000000000..a464d7495
--- /dev/null
+++ b/app/views/budgets/investments/_actions.html.erb
@@ -0,0 +1,10 @@
+<% if can? :hide, investment %>
+ <%= link_to t("admin.actions.hide").capitalize, hide_moderation_budget_investment_path(investment),
+ method: :put, remote: true, data: { confirm: t("admin.actions.confirm") } %>
+<% end %>
+
+<% if can? :hide, investment.author %>
+ |
+ <%= link_to t("admin.actions.hide_author").capitalize, hide_moderation_user_path(investment.author_id),
+ method: :put, data: { confirm: t("admin.actions.confirm") } %>
+<% end %>
diff --git a/app/views/budgets/investments/_flag_actions.html.erb b/app/views/budgets/investments/_flag_actions.html.erb
new file mode 100644
index 000000000..8627dfe94
--- /dev/null
+++ b/app/views/budgets/investments/_flag_actions.html.erb
@@ -0,0 +1,25 @@
+
+ <% if show_flag_action? investment %>
+
+
+
+
+ <%= link_to t('shared.flag'), flag_budget_investment_path(investment.budget, investment.id),
+ method: :put,
+ remote: true,
+ id: "flag-investment-#{ investment.id }" %>
+
+ <% end %>
+
+ <% if show_unflag_action? investment %>
+
+
+
+
+ <%= link_to t('shared.unflag'), unflag_budget_investment_path(investment.budget, investment.id),
+ method: :put,
+ remote: true,
+ id: "unflag-investment-#{ investment.id }" %>
+
+ <% end %>
+
diff --git a/app/views/budgets/investments/_investment_show.html.erb b/app/views/budgets/investments/_investment_show.html.erb
index acca21a80..2f3528653 100644
--- a/app/views/budgets/investments/_investment_show.html.erb
+++ b/app/views/budgets/investments/_investment_show.html.erb
@@ -7,180 +7,195 @@
og_image_url: (investment.image.present? ? investment.image_url(:thumb) : nil) %>
<% end %>
-
+<% cache [locale_and_user_status(investment),
+ investment,
+ investment.author,
+ Flag.flagged?(current_user, investment),
+ @investment_votes] do %>
+
-
-
- <%= back_link_to budget_investments_path(investment.budget, heading_id: investment.heading) %>
+
+
+ <%= back_link_to budget_investments_path(investment.budget, heading_id: investment.heading) %>
-
<%= investment.title %>
-
- <%= render '/shared/author_info', resource: investment %>
+
<%= investment.title %>
+
+ <%= render '/shared/author_info', resource: investment %>
- •
- <%= l investment.created_at.to_date %>
- •
- <%= investment.heading.name %>
+ •
+ <%= l investment.created_at.to_date %>
+ •
+ <%= investment.heading.name %>
+ •
+
+ <%= render 'budgets/investments/flag_actions', investment: @investment %>
+
+
+
+
+
+ <%= render_image(investment.image, :large, true) if investment.image.present? %>
+
+
+ <%= t("budgets.investments.show.code_html", code: investment.id) %>
+
+
+ <%= safe_html_with_links investment.description.html_safe %>
+
+ <% if feature?(:map) && map_location_available?(@investment.map_location) %>
+
+ <%= render_map(@investment.map_location, "budget_investment", false, nil) %>
+
+ <% end %>
+
+ <% if investment.location.present? %>
+
+ <%= t("budgets.investments.show.location_html", location: investment.location) %>
+
+ <% end %>
+
+ <% if investment.organization_name.present? %>
+
+ <%= t("budgets.investments.show.organization_name_html", name: investment.organization_name) %>
+
+ <% end %>
+
+ <% if feature?(:allow_attached_documents) %>
+ <%= render 'documents/documents',
+ documents: investment.documents,
+ max_documents_allowed: Budget::Investment.max_documents_allowed %>
+ <% end %>
+
+ <%= render 'shared/tags', taggable: investment %>
+
+ <% if investment.external_url.present? %>
+
+ <%= text_with_links investment.external_url %>
+
+ <% end %>
+
+ <% if investment.should_show_unfeasibility_explanation? %>
+
<%= t('budgets.investments.show.unfeasibility_explanation') %>
+
<%= investment.unfeasibility_explanation %>
+ <% end %>
+
+ <% if investment.should_show_price_explanation? %>
+
<%= t('budgets.investments.show.price_explanation') %>
+
<%= investment.price_explanation %>
+ <% end %>
+
+ <%= render 'relationable/related_content', relationable: @investment %>
+
+
+ <%= render "budgets/investments/actions", investment: @investment %>
+
-
+
-
-