Merge pull request #2778 from wairbut-m2c/backport/investments-moderation
Allow budget investments to be moderated
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
//= require moderator_comment
|
//= require moderator_comment
|
||||||
//= require moderator_debates
|
//= require moderator_debates
|
||||||
//= require moderator_proposals
|
//= require moderator_proposals
|
||||||
|
//= require moderator_budget_investments
|
||||||
//= require moderator_proposal_notifications
|
//= require moderator_proposal_notifications
|
||||||
//= require prevent_double_submission
|
//= require prevent_double_submission
|
||||||
//= require gettext
|
//= require gettext
|
||||||
|
|||||||
@@ -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()
|
||||||
@@ -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
|
||||||
@@ -3,18 +3,32 @@ module FlagActions
|
|||||||
|
|
||||||
def flag
|
def flag
|
||||||
Flag.flag(current_user, flaggable)
|
Flag.flag(current_user, flaggable)
|
||||||
|
|
||||||
|
if controller_name == 'investments'
|
||||||
|
respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
|
||||||
|
else
|
||||||
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
|
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def unflag
|
def unflag
|
||||||
Flag.unflag(current_user, flaggable)
|
Flag.unflag(current_user, flaggable)
|
||||||
|
|
||||||
|
if controller_name == 'investments'
|
||||||
|
respond_with flaggable, template: "budgets/#{controller_name}/_refresh_flag_actions"
|
||||||
|
else
|
||||||
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
|
respond_with flaggable, template: "#{controller_name}/_refresh_flag_actions"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def flaggable
|
def flaggable
|
||||||
|
if resource_model.to_s == 'Budget::Investment'
|
||||||
|
instance_variable_get("@investment")
|
||||||
|
else
|
||||||
instance_variable_get("@#{resource_model.to_s.downcase}")
|
instance_variable_get("@#{resource_model.to_s.downcase}")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
@@ -3,8 +3,12 @@ module Polymorphic
|
|||||||
private
|
private
|
||||||
|
|
||||||
def resource
|
def resource
|
||||||
|
if resource_model.to_s == 'Budget::Investment'
|
||||||
|
@resource ||= instance_variable_get("@investment")
|
||||||
|
else
|
||||||
@resource ||= instance_variable_get("@#{resource_name}")
|
@resource ||= instance_variable_get("@#{resource_name}")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def resource_name
|
def resource_name
|
||||||
@resource_name ||= resource_model.to_s.downcase
|
@resource_name ||= resource_model.to_s.downcase
|
||||||
|
|||||||
24
app/controllers/moderation/budgets/investments_controller.rb
Normal file
24
app/controllers/moderation/budgets/investments_controller.rb
Normal file
@@ -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
|
||||||
@@ -14,6 +14,7 @@ class StatsController < ApplicationController
|
|||||||
@debate_votes = daily_cache('debate_votes') { Vote.where(votable_type: 'Debate').count }
|
@debate_votes = daily_cache('debate_votes') { Vote.where(votable_type: 'Debate').count }
|
||||||
@proposal_votes = daily_cache('proposal_votes') { Vote.where(votable_type: 'Proposal').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 }
|
@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 }
|
@votes = daily_cache('votes') { Vote.count }
|
||||||
|
|
||||||
@verified_users = daily_cache('verified_users') { User.with_hidden.level_two_or_three_verified.count }
|
@verified_users = daily_cache('verified_users') { User.with_hidden.level_two_or_three_verified.count }
|
||||||
|
|||||||
@@ -1,19 +1,31 @@
|
|||||||
module AdminHelper
|
module AdminHelper
|
||||||
|
|
||||||
def side_menu
|
def side_menu
|
||||||
|
if namespace == 'moderation/budgets'
|
||||||
|
render "/moderation/menu"
|
||||||
|
else
|
||||||
render "/#{namespace}/menu"
|
render "/#{namespace}/menu"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def namespaced_root_path
|
def namespaced_root_path
|
||||||
|
if namespace == 'moderation/budgets'
|
||||||
|
"/moderation"
|
||||||
|
else
|
||||||
"/#{namespace}"
|
"/#{namespace}"
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def namespaced_header_title
|
def namespaced_header_title
|
||||||
|
if namespace == 'moderation/budgets'
|
||||||
|
t("moderation.header.title")
|
||||||
|
else
|
||||||
t("#{namespace}.header.title")
|
t("#{namespace}.header.title")
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def menu_moderated_content?
|
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
|
end
|
||||||
|
|
||||||
def menu_budget?
|
def menu_budget?
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ module Abilities
|
|||||||
can :restore, Legislation::Proposal
|
can :restore, Legislation::Proposal
|
||||||
cannot :restore, Legislation::Proposal, hidden_at: nil
|
cannot :restore, Legislation::Proposal, hidden_at: nil
|
||||||
|
|
||||||
|
can :restore, Budget::Investment
|
||||||
|
cannot :restore, Budget::Investment, hidden_at: nil
|
||||||
|
|
||||||
can :restore, User
|
can :restore, User
|
||||||
cannot :restore, User, hidden_at: nil
|
cannot :restore, User, hidden_at: nil
|
||||||
|
|
||||||
@@ -32,6 +35,9 @@ module Abilities
|
|||||||
can :confirm_hide, Legislation::Proposal
|
can :confirm_hide, Legislation::Proposal
|
||||||
cannot :confirm_hide, Legislation::Proposal, hidden_at: nil
|
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
|
can :confirm_hide, User
|
||||||
cannot :confirm_hide, User, hidden_at: nil
|
cannot :confirm_hide, User, hidden_at: nil
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,9 @@ module Abilities
|
|||||||
can [:flag, :unflag], Legislation::Proposal
|
can [:flag, :unflag], Legislation::Proposal
|
||||||
cannot [:flag, :unflag], Legislation::Proposal, author_id: user.id
|
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 [:create, :destroy], Follow
|
||||||
|
|
||||||
can [:destroy], Document, documentable: { author_id: user.id }
|
can [:destroy], Document, documentable: { author_id: user.id }
|
||||||
|
|||||||
@@ -63,6 +63,15 @@ module Abilities
|
|||||||
cannot :moderate, ProposalNotification, author_id: user.id
|
cannot :moderate, ProposalNotification, author_id: user.id
|
||||||
|
|
||||||
can :index, ProposalNotification
|
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
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -23,6 +23,7 @@ class Budget
|
|||||||
include Relationable
|
include Relationable
|
||||||
include Notifiable
|
include Notifiable
|
||||||
include Filterable
|
include Filterable
|
||||||
|
include Flaggable
|
||||||
|
|
||||||
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
|
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
|
||||||
belongs_to :heading
|
belongs_to :heading
|
||||||
@@ -81,6 +82,8 @@ class Budget
|
|||||||
scope :winners, -> { selected.compatible.where(winner: true) }
|
scope :winners, -> { selected.compatible.where(winner: true) }
|
||||||
scope :unselected, -> { not_unfeasible.where(selected: false) }
|
scope :unselected, -> { not_unfeasible.where(selected: false) }
|
||||||
scope :last_week, -> { where("created_at >= ?", 7.days.ago)}
|
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_budget, ->(budget) { where(budget: budget) }
|
||||||
scope :by_group, ->(group_id) { where(group_id: group_id) }
|
scope :by_group, ->(group_id) { where(group_id: group_id) }
|
||||||
|
|||||||
@@ -182,6 +182,7 @@ class User < ActiveRecord::Base
|
|||||||
debates_ids = Debate.where(author_id: id).pluck(:id)
|
debates_ids = Debate.where(author_id: id).pluck(:id)
|
||||||
comments_ids = Comment.where(user_id: id).pluck(:id)
|
comments_ids = Comment.where(user_id: id).pluck(:id)
|
||||||
proposal_ids = Proposal.where(author_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)
|
proposal_notification_ids = ProposalNotification.where(author_id: id).pluck(:id)
|
||||||
|
|
||||||
hide
|
hide
|
||||||
@@ -189,6 +190,7 @@ class User < ActiveRecord::Base
|
|||||||
Debate.hide_all debates_ids
|
Debate.hide_all debates_ids
|
||||||
Comment.hide_all comments_ids
|
Comment.hide_all comments_ids
|
||||||
Proposal.hide_all proposal_ids
|
Proposal.hide_all proposal_ids
|
||||||
|
Budget::Investment.hide_all investment_ids
|
||||||
ProposalNotification.hide_all proposal_notification_ids
|
ProposalNotification.hide_all proposal_notification_ids
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -151,6 +151,12 @@
|
|||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if feature?(:budgets) %>
|
||||||
|
<li <%= "class=is-active" if controller_name == "hidden_budget_investments" %>>
|
||||||
|
<%= link_to t("admin.menu.hidden_budget_investments"), admin_hidden_budget_investments_path %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<li <%= "class=is-active" if controller_name == "comments" %>>
|
<li <%= "class=is-active" if controller_name == "comments" %>>
|
||||||
<%= link_to t("admin.menu.hidden_comments"), admin_comments_path %>
|
<%= link_to t("admin.menu.hidden_comments"), admin_comments_path %>
|
||||||
</li>
|
</li>
|
||||||
|
|||||||
49
app/views/admin/hidden_budget_investments/index.html.erb
Normal file
49
app/views/admin/hidden_budget_investments/index.html.erb
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
<h2><%= t("admin.hidden_budget_investments.index.title") %></h2>
|
||||||
|
<p><%= t("admin.shared.moderated_content") %></p>
|
||||||
|
|
||||||
|
<%= render 'shared/filter_subnav', i18n_namespace: "admin.hidden_budget_investments.index" %>
|
||||||
|
|
||||||
|
<% if @investments.any? %>
|
||||||
|
<h3 class="margin"><%= page_entries_info @investments %></h3>
|
||||||
|
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<th scope="col"><%= t("admin.shared.title") %></th>
|
||||||
|
<th scope="col" class="small-6"><%= t("admin.shared.description") %></th>
|
||||||
|
<th scope="col" class="small-4"><%= t("admin.shared.actions") %></th>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<% @investments.each do |investment| %>
|
||||||
|
<tr id="<%= dom_id(investment) %>">
|
||||||
|
<td class="align-top">
|
||||||
|
<strong><%= investment.title %></strong>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="moderation-description">
|
||||||
|
<%= investment.description %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="align-top">
|
||||||
|
<%= 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 %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= paginate @investments %>
|
||||||
|
<% else %>
|
||||||
|
<div class="callout primary margin">
|
||||||
|
<%= t("admin.hidden_budget_investments.index.no_hidden_budget_investments") %>
|
||||||
|
</div>
|
||||||
|
<% end %>
|
||||||
10
app/views/budgets/investments/_actions.html.erb
Normal file
10
app/views/budgets/investments/_actions.html.erb
Normal file
@@ -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 %>
|
||||||
25
app/views/budgets/investments/_flag_actions.html.erb
Normal file
25
app/views/budgets/investments/_flag_actions.html.erb
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<span class="flag-content">
|
||||||
|
<% if show_flag_action? investment %>
|
||||||
|
<a id="flag-expand-investment-<%= investment.id %>" data-toggle="flag-drop-investment-<%= investment.id %>" title="<%= t('shared.flag') %>">
|
||||||
|
<span class="icon-flag flag-disable"></span>
|
||||||
|
</a>
|
||||||
|
<span class="dropdown-pane" id="flag-drop-investment-<%= investment.id %>" data-dropdown data-auto-focus="true">
|
||||||
|
<%= link_to t('shared.flag'), flag_budget_investment_path(investment.budget, investment.id),
|
||||||
|
method: :put,
|
||||||
|
remote: true,
|
||||||
|
id: "flag-investment-#{ investment.id }" %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
|
<% if show_unflag_action? investment %>
|
||||||
|
<a id="unflag-expand-investment-<%= investment.id %>" data-toggle="unflag-drop-investment-<%= investment.id %>" title="<%= t('shared.unflag') %>">
|
||||||
|
<span class="icon-flag flag-active"></span>
|
||||||
|
</a>
|
||||||
|
<span class="dropdown-pane" id="unflag-drop-investment-<%= investment.id %>" data-dropdown data-auto-focus="true">
|
||||||
|
<%= link_to t('shared.unflag'), unflag_budget_investment_path(investment.budget, investment.id),
|
||||||
|
method: :put,
|
||||||
|
remote: true,
|
||||||
|
id: "unflag-investment-#{ investment.id }" %>
|
||||||
|
</span>
|
||||||
|
<% end %>
|
||||||
|
</span>
|
||||||
@@ -7,7 +7,12 @@
|
|||||||
og_image_url: (investment.image.present? ? investment.image_url(:thumb) : nil) %>
|
og_image_url: (investment.image.present? ? investment.image_url(:thumb) : nil) %>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<section class="budget-investment-show" id="<%= dom_id(investment) %>">
|
<% cache [locale_and_user_status(investment),
|
||||||
|
investment,
|
||||||
|
investment.author,
|
||||||
|
Flag.flagged?(current_user, investment),
|
||||||
|
@investment_votes] do %>
|
||||||
|
<section class="budget-investment-show" id="<%= dom_id(investment) %>">
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="small-12 medium-9 column">
|
<div class="small-12 medium-9 column">
|
||||||
@@ -21,6 +26,10 @@
|
|||||||
<%= l investment.created_at.to_date %>
|
<%= l investment.created_at.to_date %>
|
||||||
<span class="bullet"> • </span>
|
<span class="bullet"> • </span>
|
||||||
<%= investment.heading.name %>
|
<%= investment.heading.name %>
|
||||||
|
<span class="bullet"> • </span>
|
||||||
|
<span class="js-flag-actions">
|
||||||
|
<%= render 'budgets/investments/flag_actions', investment: @investment %>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
@@ -76,6 +85,10 @@
|
|||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<%= render 'relationable/related_content', relationable: @investment %>
|
<%= render 'relationable/related_content', relationable: @investment %>
|
||||||
|
|
||||||
|
<div class="js-moderator-investment-actions margin">
|
||||||
|
<%= render "budgets/investments/actions", investment: @investment %>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<aside class="small-12 medium-3 column">
|
<aside class="small-12 medium-3 column">
|
||||||
@@ -130,13 +143,6 @@
|
|||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% else %>
|
<% else %>
|
||||||
<div class="float-right">
|
|
||||||
<span class="label-budget-investment float-left">
|
|
||||||
<%= t("budgets.investments.show.title") %>
|
|
||||||
</span>
|
|
||||||
<span class="icon-budget"></span>
|
|
||||||
</div>
|
|
||||||
<br>
|
|
||||||
<% if investment.unfeasible? %>
|
<% if investment.unfeasible? %>
|
||||||
<div class="callout warning">
|
<div class="callout warning">
|
||||||
<%= t("budgets.investments.show.project_unfeasible_html") %>
|
<%= t("budgets.investments.show.project_unfeasible_html") %>
|
||||||
@@ -153,6 +159,14 @@
|
|||||||
<div class="callout warning">
|
<div class="callout warning">
|
||||||
<%= t("budgets.investments.show.project_not_selected_html") %>
|
<%= t("budgets.investments.show.project_not_selected_html") %>
|
||||||
</div>
|
</div>
|
||||||
|
<% else %>
|
||||||
|
<br>
|
||||||
|
<div class="float-right">
|
||||||
|
<span class="label-budget-investment float-left">
|
||||||
|
<%= t("budgets.investments.show.title") %>
|
||||||
|
</span>
|
||||||
|
<span class="icon-budget"></span>
|
||||||
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
<% if investment.should_show_price? %>
|
<% if investment.should_show_price? %>
|
||||||
<div class="sidebar-divider"></div>
|
<div class="sidebar-divider"></div>
|
||||||
@@ -183,4 +197,5 @@
|
|||||||
|
|
||||||
</aside>
|
</aside>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
<% end %>
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
App.Flaggable.update("<%= dom_id(@investment) %>", "<%= j render("budgets/investments/flag_actions", investment: @investment) %>")
|
||||||
@@ -29,6 +29,15 @@
|
|||||||
</li>
|
</li>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<% if feature?(:budgets) %>
|
||||||
|
<li <%= "class=is-active" if controller_name == "investments" %>>
|
||||||
|
<%= link_to moderation_budget_investments_path do %>
|
||||||
|
<span class="icon-budget"></span>
|
||||||
|
<%= t("moderation.menu.flagged_investments") %>
|
||||||
|
<% end %>
|
||||||
|
</li>
|
||||||
|
<% end %>
|
||||||
|
|
||||||
<li <%= "class=is-active" if controller_name == "comments" %>>
|
<li <%= "class=is-active" if controller_name == "comments" %>>
|
||||||
<%= link_to moderation_comments_path do %>
|
<%= link_to moderation_comments_path do %>
|
||||||
<span class="icon-comments"></span>
|
<span class="icon-comments"></span>
|
||||||
|
|||||||
3
app/views/moderation/budgets/investments/hide.js.erb
Normal file
3
app/views/moderation/budgets/investments/hide.js.erb
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
var investment_id = '<%= dom_id(@investment) %>'
|
||||||
|
App.ModeratorBudgetInvestments.add_class_faded(investment_id)
|
||||||
|
App.ModeratorBudgetInvestments.hide_moderator_actions(investment_id)
|
||||||
73
app/views/moderation/budgets/investments/index.html.erb
Normal file
73
app/views/moderation/budgets/investments/index.html.erb
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
<h2><%= t("moderation.budget_investments.index.title") %></h2>
|
||||||
|
|
||||||
|
<%= render "shared/filter_subnav", i18n_namespace: "moderation.budget_investments.index" %>
|
||||||
|
|
||||||
|
<h3 class="inline-block"><%= page_entries_info @budget_investments %></h3>
|
||||||
|
<div class="float-right">
|
||||||
|
<%= t("moderation.budget_investments.index.order") %>
|
||||||
|
<%= render "shared/order_selector", i18n_namespace: "moderation.budget_investments.index" %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= form_tag moderate_moderation_budget_investments_path(request.query_parameters), method: :put do %>
|
||||||
|
<p class="float-left js-check">
|
||||||
|
<%= t("shared.check") %>:
|
||||||
|
<%= link_to t("shared.check_all"), "#", data: { check_all: "budget_investment_ids[]" } %>
|
||||||
|
|
|
||||||
|
<%= link_to t("shared.check_none"), "#", data: { check_none: "budget_investment_ids[]" } %>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<table class="clear">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th><%= t("moderation.budget_investments.index.headers.budget_investment") %></th>
|
||||||
|
<th><%= t("moderation.budget_investments.index.headers.moderate") %></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
|
||||||
|
<tbody>
|
||||||
|
<% @budget_investments.each do |investment| %>
|
||||||
|
<tr id="investment_<%= investment.id %>">
|
||||||
|
<td>
|
||||||
|
<%= link_to investment.title, admin_budget_budget_investment_path(
|
||||||
|
budget_id: investment.budget_id,
|
||||||
|
id: investment.id
|
||||||
|
), target: "_blank" %>
|
||||||
|
<br>
|
||||||
|
<span class="date"><%= l investment.updated_at.to_date %></span>
|
||||||
|
<span class="bullet"> • </span>
|
||||||
|
<%= investment.flags_count %><span class="icon-flag flag-disable"></span>
|
||||||
|
<span class="bullet"> • </span>
|
||||||
|
<%= investment.author.username %>
|
||||||
|
<br>
|
||||||
|
<div class="moderation-description">
|
||||||
|
<%= investment.description %>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="text-center">
|
||||||
|
<%= check_box_tag "budget_investment_ids[]", investment.id, nil, id: "#{dom_id(investment)}_check" %>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<%= submit_tag t("moderation.budget_investments.index.block_authors"),
|
||||||
|
name: "block_authors",
|
||||||
|
class: "button hollow alert",
|
||||||
|
data: { confirm: t("moderation.budget_investments.index.confirm") } %>
|
||||||
|
|
||||||
|
<div class="float-right">
|
||||||
|
<%= submit_tag t("moderation.budget_investments.index.hide_budget_investments"),
|
||||||
|
name: "hide_budget_investments",
|
||||||
|
class: "button hollow alert",
|
||||||
|
data: { confirm: t("moderation.budget_investments.index.confirm") } %>
|
||||||
|
|
||||||
|
<%= submit_tag t("moderation.budget_investments.index.ignore_flags"),
|
||||||
|
name: "ignore_flags",
|
||||||
|
class: "button hollow",
|
||||||
|
data: { confirm: t("moderation.budget_investments.index.confirm") } %>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<%= paginate @budget_investments %>
|
||||||
|
|
||||||
|
<% end %>
|
||||||
@@ -135,6 +135,7 @@ ignore_unused:
|
|||||||
- 'admin.spending_proposals.index.filter*'
|
- 'admin.spending_proposals.index.filter*'
|
||||||
- 'admin.organizations.index.filter*'
|
- 'admin.organizations.index.filter*'
|
||||||
- 'admin.hidden_users.index.filter*'
|
- 'admin.hidden_users.index.filter*'
|
||||||
|
- 'admin.hidden_budget_investments.index.filter*'
|
||||||
- 'admin.activity.show.filter*'
|
- 'admin.activity.show.filter*'
|
||||||
- 'admin.legislation.processes.index.filter*'
|
- 'admin.legislation.processes.index.filter*'
|
||||||
- 'admin.legislation.processes.*.submit_button'
|
- 'admin.legislation.processes.*.submit_button'
|
||||||
@@ -152,6 +153,8 @@ ignore_unused:
|
|||||||
- 'moderation.proposals.index.order*'
|
- 'moderation.proposals.index.order*'
|
||||||
- 'moderation.debates.index.filter*'
|
- 'moderation.debates.index.filter*'
|
||||||
- 'moderation.debates.index.order*'
|
- 'moderation.debates.index.order*'
|
||||||
|
- 'moderation.budget_investments.index.filter*'
|
||||||
|
- 'moderation.budget_investments.index.order*'
|
||||||
- 'moderation.proposal_notifications.index.filter*'
|
- 'moderation.proposal_notifications.index.filter*'
|
||||||
- 'moderation.proposal_notifications.index.order*'
|
- 'moderation.proposal_notifications.index.order*'
|
||||||
- 'valuation.spending_proposals.index.filter*'
|
- 'valuation.spending_proposals.index.filter*'
|
||||||
|
|||||||
@@ -345,6 +345,15 @@ en:
|
|||||||
hidden_at: 'Hidden at:'
|
hidden_at: 'Hidden at:'
|
||||||
registered_at: 'Registered at:'
|
registered_at: 'Registered at:'
|
||||||
title: Activity of user (%{user})
|
title: Activity of user (%{user})
|
||||||
|
hidden_budget_investments:
|
||||||
|
index:
|
||||||
|
filter: Filter
|
||||||
|
filters:
|
||||||
|
all: All
|
||||||
|
with_confirmed_hide: Confirmed
|
||||||
|
without_confirmed_hide: Pending
|
||||||
|
title: Hidden budgets investments
|
||||||
|
no_hidden_budget_investments: There are no hidden budget investments
|
||||||
legislation:
|
legislation:
|
||||||
processes:
|
processes:
|
||||||
create:
|
create:
|
||||||
@@ -514,6 +523,7 @@ en:
|
|||||||
hidden_comments: Hidden comments
|
hidden_comments: Hidden comments
|
||||||
hidden_debates: Hidden debates
|
hidden_debates: Hidden debates
|
||||||
hidden_proposals: Hidden proposals
|
hidden_proposals: Hidden proposals
|
||||||
|
hidden_budget_investments: Hidden budget investments
|
||||||
hidden_proposal_notifications: Hidden proposal notifications
|
hidden_proposal_notifications: Hidden proposal notifications
|
||||||
hidden_users: Hidden users
|
hidden_users: Hidden users
|
||||||
administrators: Administrators
|
administrators: Administrators
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ en:
|
|||||||
menu:
|
menu:
|
||||||
flagged_comments: Comments
|
flagged_comments: Comments
|
||||||
flagged_debates: Debates
|
flagged_debates: Debates
|
||||||
|
flagged_investments: Budget investments
|
||||||
proposals: Proposals
|
proposals: Proposals
|
||||||
proposal_notifications: Proposals notifications
|
proposal_notifications: Proposals notifications
|
||||||
users: Block users
|
users: Block users
|
||||||
@@ -68,6 +69,25 @@ en:
|
|||||||
created_at: Most recent
|
created_at: Most recent
|
||||||
flags: Most flagged
|
flags: Most flagged
|
||||||
title: Proposals
|
title: Proposals
|
||||||
|
budget_investments:
|
||||||
|
index:
|
||||||
|
block_authors: Block authors
|
||||||
|
confirm: Are you sure?
|
||||||
|
filter: Filter
|
||||||
|
filters:
|
||||||
|
all: All
|
||||||
|
pending_flag_review: Pending
|
||||||
|
with_ignored_flag: Marked as viewed
|
||||||
|
headers:
|
||||||
|
moderate: Moderate
|
||||||
|
budget_investment: Budget investment
|
||||||
|
hide_budget_investments: Hide budget investments
|
||||||
|
ignore_flags: Mark as viewed
|
||||||
|
order: Order by
|
||||||
|
orders:
|
||||||
|
created_at: Most recent
|
||||||
|
flags: Most flagged
|
||||||
|
title: Budget investments
|
||||||
proposal_notifications:
|
proposal_notifications:
|
||||||
index:
|
index:
|
||||||
block_authors: Block authors
|
block_authors: Block authors
|
||||||
|
|||||||
@@ -346,6 +346,15 @@ es:
|
|||||||
hidden_at: 'Bloqueado:'
|
hidden_at: 'Bloqueado:'
|
||||||
registered_at: 'Fecha de alta:'
|
registered_at: 'Fecha de alta:'
|
||||||
title: Actividad del usuario (%{user})
|
title: Actividad del usuario (%{user})
|
||||||
|
hidden_budget_investments:
|
||||||
|
index:
|
||||||
|
filter: Filtro
|
||||||
|
filters:
|
||||||
|
all: Todos
|
||||||
|
with_confirmed_hide: Confirmados
|
||||||
|
without_confirmed_hide: Pendientes
|
||||||
|
title: Proyectos de gasto ocultos
|
||||||
|
no_hidden_budget_investments: No hay proyectos de gasto ocultos
|
||||||
legislation:
|
legislation:
|
||||||
processes:
|
processes:
|
||||||
create:
|
create:
|
||||||
@@ -515,6 +524,7 @@ es:
|
|||||||
hidden_comments: Comentarios ocultos
|
hidden_comments: Comentarios ocultos
|
||||||
hidden_debates: Debates ocultos
|
hidden_debates: Debates ocultos
|
||||||
hidden_proposals: Propuestas ocultas
|
hidden_proposals: Propuestas ocultas
|
||||||
|
hidden_budget_investments: Proyectos de gasto ocultos
|
||||||
hidden_proposal_notifications: Notificationes de propuesta ocultas
|
hidden_proposal_notifications: Notificationes de propuesta ocultas
|
||||||
hidden_users: Usuarios bloqueados
|
hidden_users: Usuarios bloqueados
|
||||||
administrators: Administradores
|
administrators: Administradores
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ es:
|
|||||||
menu:
|
menu:
|
||||||
flagged_comments: Comentarios
|
flagged_comments: Comentarios
|
||||||
flagged_debates: Debates
|
flagged_debates: Debates
|
||||||
|
flagged_investments: Proyectos de gasto
|
||||||
proposals: Propuestas
|
proposals: Propuestas
|
||||||
proposal_notifications: Notificaciones de propuestas
|
proposal_notifications: Notificaciones de propuestas
|
||||||
users: Bloquear usuarios
|
users: Bloquear usuarios
|
||||||
@@ -68,6 +69,25 @@ es:
|
|||||||
created_at: Más recientes
|
created_at: Más recientes
|
||||||
flags: Más denunciadas
|
flags: Más denunciadas
|
||||||
title: Propuestas
|
title: Propuestas
|
||||||
|
budget_investments:
|
||||||
|
index:
|
||||||
|
block_authors: Bloquear autores
|
||||||
|
confirm: '¿Estás seguro?'
|
||||||
|
filter: Filtro
|
||||||
|
filters:
|
||||||
|
all: Todos
|
||||||
|
pending_flag_review: Pendientes de revisión
|
||||||
|
with_ignored_flag: Marcadas como revisadas
|
||||||
|
headers:
|
||||||
|
moderate: Moderar
|
||||||
|
budget_investment: Proyecto de gasto
|
||||||
|
hide_budget_investments: Ocultar proyectos de gasto
|
||||||
|
ignore_flags: Marcar como revisadas
|
||||||
|
order: Ordenar por
|
||||||
|
orders:
|
||||||
|
created_at: Más recientes
|
||||||
|
flags: Más denunciadas
|
||||||
|
title: Proyectos de gasto
|
||||||
proposal_notifications:
|
proposal_notifications:
|
||||||
index:
|
index:
|
||||||
block_authors: Bloquear autores
|
block_authors: Bloquear autores
|
||||||
|
|||||||
@@ -15,6 +15,13 @@ namespace :admin do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :hidden_budget_investments, only: :index do
|
||||||
|
member do
|
||||||
|
put :restore
|
||||||
|
put :confirm_hide
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
resources :debates, only: :index do
|
resources :debates, only: :index do
|
||||||
member do
|
member do
|
||||||
put :restore
|
put :restore
|
||||||
@@ -78,6 +85,7 @@ namespace :admin do
|
|||||||
end
|
end
|
||||||
|
|
||||||
resources :tags, only: [:index, :create, :update, :destroy]
|
resources :tags, only: [:index, :create, :update, :destroy]
|
||||||
|
|
||||||
resources :officials, only: [:index, :edit, :update, :destroy] do
|
resources :officials, only: [:index, :edit, :update, :destroy] do
|
||||||
get :search, on: :collection
|
get :search, on: :collection
|
||||||
end
|
end
|
||||||
@@ -93,6 +101,7 @@ namespace :admin do
|
|||||||
get :search, on: :collection
|
get :search, on: :collection
|
||||||
get :summary, on: :collection
|
get :summary, on: :collection
|
||||||
end
|
end
|
||||||
|
|
||||||
resources :valuator_groups
|
resources :valuator_groups
|
||||||
|
|
||||||
resources :managers, only: [:index, :create, :destroy] do
|
resources :managers, only: [:index, :create, :destroy] do
|
||||||
|
|||||||
@@ -1,7 +1,12 @@
|
|||||||
resources :budgets, only: [:show, :index] do
|
resources :budgets, only: [:show, :index] do
|
||||||
resources :groups, controller: "budgets/groups", only: [:show]
|
resources :groups, controller: "budgets/groups", only: [:show]
|
||||||
resources :investments, controller: "budgets/investments", only: [:index, :new, :create, :show, :destroy] do
|
resources :investments, controller: "budgets/investments", only: [:index, :new, :create, :show, :destroy] do
|
||||||
member { post :vote }
|
member do
|
||||||
|
post :vote
|
||||||
|
put :flag
|
||||||
|
put :unflag
|
||||||
|
end
|
||||||
|
|
||||||
collection { get :suggest }
|
collection { get :suggest }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -27,4 +27,9 @@ namespace :moderation do
|
|||||||
put :hide, on: :member
|
put :hide, on: :member
|
||||||
put :moderate, on: :collection
|
put :moderate, on: :collection
|
||||||
end
|
end
|
||||||
|
|
||||||
|
resources :budget_investments, only: :index, controller: 'budgets/investments' do
|
||||||
|
put :hide, on: :member
|
||||||
|
put :moderate, on: :collection
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
class AddModerationAttrsToInvestments < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
change_table :budget_investments do |t|
|
||||||
|
t.datetime :confirmed_hide_at
|
||||||
|
t.datetime :ignored_flag_at
|
||||||
|
t.integer :flags_count, default: 0
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -207,6 +207,9 @@ ActiveRecord::Schema.define(version: 20180711224810) do
|
|||||||
t.integer "community_id"
|
t.integer "community_id"
|
||||||
t.boolean "visible_to_valuators", default: false
|
t.boolean "visible_to_valuators", default: false
|
||||||
t.integer "valuator_group_assignments_count", default: 0
|
t.integer "valuator_group_assignments_count", default: 0
|
||||||
|
t.datetime "confirmed_hide_at"
|
||||||
|
t.datetime "ignored_flag_at"
|
||||||
|
t.integer "flags_count", default: 0
|
||||||
end
|
end
|
||||||
|
|
||||||
add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree
|
add_index "budget_investments", ["administrator_id"], name: "index_budget_investments_on_administrator_id", using: :btree
|
||||||
|
|||||||
@@ -362,6 +362,24 @@ FactoryBot.define do
|
|||||||
feasibility "feasible"
|
feasibility "feasible"
|
||||||
valuation_finished true
|
valuation_finished true
|
||||||
end
|
end
|
||||||
|
|
||||||
|
trait :hidden do
|
||||||
|
hidden_at Time.current
|
||||||
|
end
|
||||||
|
|
||||||
|
trait :with_ignored_flag do
|
||||||
|
ignored_flag_at Time.current
|
||||||
|
end
|
||||||
|
|
||||||
|
trait :flagged do
|
||||||
|
after :create do |investment|
|
||||||
|
Flag.flag(create(:user), investment)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
trait :with_confirmed_hide do
|
||||||
|
confirmed_hide_at Time.current
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
factory :budget_phase, class: 'Budget::Phase' do
|
factory :budget_phase, class: 'Budget::Phase' do
|
||||||
|
|||||||
108
spec/features/admin/hidden_budget_investments_spec.rb
Normal file
108
spec/features/admin/hidden_budget_investments_spec.rb
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
feature 'Admin hidden budget investments' do
|
||||||
|
|
||||||
|
let(:budget) { create(:budget) }
|
||||||
|
let(:group) { create(:budget_group, name: 'Music', budget: budget) }
|
||||||
|
let(:heading) { create(:budget_heading, name: 'Black metal', price: 666666, group: group) }
|
||||||
|
|
||||||
|
background do
|
||||||
|
admin = create(:administrator)
|
||||||
|
login_as(admin.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Disabled with a feature flag' do
|
||||||
|
Setting['feature.budgets'] = nil
|
||||||
|
|
||||||
|
expect{ visit admin_hidden_budget_investments_path }.to raise_exception(FeatureFlags::FeatureDisabled)
|
||||||
|
|
||||||
|
Setting['feature.budgets'] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'List shows all relevant info' do
|
||||||
|
investment = create(:budget_investment, :hidden, heading: heading)
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path
|
||||||
|
|
||||||
|
expect(page).to have_content(investment.title)
|
||||||
|
expect(page).to have_content(investment.description)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Restore' do
|
||||||
|
investment = create(:budget_investment, :hidden, heading: heading)
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path
|
||||||
|
|
||||||
|
click_link 'Restore'
|
||||||
|
|
||||||
|
expect(page).not_to have_content(investment.title)
|
||||||
|
|
||||||
|
investment.reload
|
||||||
|
|
||||||
|
expect(investment).to be_ignored_flag
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Confirm hide' do
|
||||||
|
investment = create(:budget_investment, :hidden, heading: heading)
|
||||||
|
visit admin_hidden_budget_investments_path
|
||||||
|
|
||||||
|
click_link('Pending')
|
||||||
|
expect(page).to have_content(investment.title)
|
||||||
|
|
||||||
|
click_link 'Confirm moderation'
|
||||||
|
|
||||||
|
expect(page).not_to have_content(investment.title)
|
||||||
|
|
||||||
|
click_link('Confirmed')
|
||||||
|
expect(page).to have_content(investment.title)
|
||||||
|
|
||||||
|
expect(investment.reload).to be_confirmed_hide
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Current filter is properly highlighted" do
|
||||||
|
visit admin_hidden_budget_investments_path
|
||||||
|
expect(page).not_to have_link('All')
|
||||||
|
expect(page).to have_link('Pending')
|
||||||
|
expect(page).to have_link('Confirmed')
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path(filter: 'without_confirmed_hide')
|
||||||
|
expect(page).to have_link('All')
|
||||||
|
expect(page).to have_link('Confirmed')
|
||||||
|
expect(page).not_to have_link('Pending')
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path(filter: 'with_confirmed_hide')
|
||||||
|
expect(page).to have_link('All')
|
||||||
|
expect(page).to have_link('Pending')
|
||||||
|
expect(page).not_to have_link('Confirmed')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Filtering investments' do
|
||||||
|
create(:budget_investment, :hidden, heading: heading, title: 'Unconfirmed investment')
|
||||||
|
create(:budget_investment, :hidden, :with_confirmed_hide, heading: heading, title: 'Confirmed investment')
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path(filter: 'without_confirmed_hide')
|
||||||
|
expect(page).to have_content('Unconfirmed investment')
|
||||||
|
expect(page).not_to have_content('Confirmed investment')
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path(filter: 'all')
|
||||||
|
expect(page).to have_content('Unconfirmed investment')
|
||||||
|
expect(page).to have_content('Confirmed investment')
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path(filter: 'with_confirmed_hide')
|
||||||
|
expect(page).not_to have_content('Unconfirmed investment')
|
||||||
|
expect(page).to have_content('Confirmed investment')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Action links remember the pagination setting and the filter" do
|
||||||
|
per_page = Kaminari.config.default_per_page
|
||||||
|
(per_page + 2).times { create(:budget_investment, :hidden, :with_confirmed_hide, heading: heading) }
|
||||||
|
|
||||||
|
visit admin_hidden_budget_investments_path(filter: 'with_confirmed_hide', page: 2)
|
||||||
|
|
||||||
|
click_on('Restore', match: :first, exact: true)
|
||||||
|
|
||||||
|
expect(current_url).to include('filter=with_confirmed_hide')
|
||||||
|
expect(current_url).to include('page=2')
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
@@ -1617,4 +1617,69 @@ feature 'Budget Investments' do
|
|||||||
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
scenario 'Flagging an investment as innapropriate', :js do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment, heading: heading)
|
||||||
|
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget, investment)
|
||||||
|
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
find("#flag-expand-investment-#{investment.id}").click
|
||||||
|
find("#flag-investment-#{investment.id}").click
|
||||||
|
|
||||||
|
expect(page).to have_css("#unflag-expand-investment-#{investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(Flag.flagged?(user, investment)).to be
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Unflagging an investment', :js do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment, heading: heading)
|
||||||
|
Flag.flag(user, investment)
|
||||||
|
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget, investment)
|
||||||
|
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
find("#unflag-expand-investment-#{investment.id}").click
|
||||||
|
find("#unflag-investment-#{investment.id}").click
|
||||||
|
|
||||||
|
expect(page).to have_css("#flag-expand-investment-#{investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(Flag.flagged?(user, investment)).not_to be
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Flagging an investment updates the DOM properly', :js do
|
||||||
|
user = create(:user)
|
||||||
|
investment = create(:budget_investment, heading: heading)
|
||||||
|
|
||||||
|
login_as(user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget, investment)
|
||||||
|
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
find("#flag-expand-investment-#{investment.id}").click
|
||||||
|
find("#flag-investment-#{investment.id}").click
|
||||||
|
|
||||||
|
expect(page).to have_css("#unflag-expand-investment-#{investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(Flag.flagged?(user, investment)).to be
|
||||||
|
|
||||||
|
within "#budget_investment_#{investment.id}" do
|
||||||
|
find("#unflag-expand-investment-#{investment.id}").click
|
||||||
|
find("#unflag-investment-#{investment.id}").click
|
||||||
|
|
||||||
|
expect(page).to have_css("#flag-expand-investment-#{investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(Flag.flagged?(user, investment)).not_to be
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|||||||
246
spec/features/moderation/budget_investments_spec.rb
Normal file
246
spec/features/moderation/budget_investments_spec.rb
Normal file
@@ -0,0 +1,246 @@
|
|||||||
|
require 'rails_helper'
|
||||||
|
|
||||||
|
feature 'Moderate budget investments' do
|
||||||
|
|
||||||
|
let(:budget) { create(:budget) }
|
||||||
|
let(:group) { create(:budget_group, name: 'Culture', budget: budget) }
|
||||||
|
let(:heading) { create(:budget_heading, name: 'More libraries', price: 666666, group: group) }
|
||||||
|
|
||||||
|
background do
|
||||||
|
@mod = create(:moderator)
|
||||||
|
@investment = create(:budget_investment, heading: heading, author: create(:user))
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Disabled with a feature flag' do
|
||||||
|
Setting['feature.budgets'] = nil
|
||||||
|
login_as(@mod.user)
|
||||||
|
|
||||||
|
expect{ visit moderation_budget_investments_path }.to raise_exception(FeatureFlags::FeatureDisabled)
|
||||||
|
|
||||||
|
Setting['feature.budgets'] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Hiding an investment', :js do
|
||||||
|
login_as(@mod.user)
|
||||||
|
visit budget_investment_path(budget, @investment)
|
||||||
|
|
||||||
|
accept_confirm { click_link 'Hide' }
|
||||||
|
|
||||||
|
expect(page).to have_css('.faded', count: 2)
|
||||||
|
|
||||||
|
visit budget_investments_path(budget.id, heading_id: heading.id)
|
||||||
|
|
||||||
|
expect(page).not_to have_content(@investment.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario "Hiding an investment's author", :js do
|
||||||
|
login_as(@mod.user)
|
||||||
|
visit budget_investment_path(budget, @investment)
|
||||||
|
|
||||||
|
accept_confirm { click_link 'Hide author' }
|
||||||
|
|
||||||
|
expect(page).to have_current_path(debates_path)
|
||||||
|
|
||||||
|
visit budget_investments_path(budget.id, heading_id: heading.id)
|
||||||
|
|
||||||
|
expect(page).not_to have_content(@investment.title)
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Can not hide own investment' do
|
||||||
|
@investment.update(author: @mod.user)
|
||||||
|
login_as(@mod.user)
|
||||||
|
|
||||||
|
visit budget_investment_path(budget, @investment)
|
||||||
|
|
||||||
|
within "#budget_investment_#{@investment.id}" do
|
||||||
|
expect(page).not_to have_link('Hide')
|
||||||
|
expect(page).not_to have_link('Hide author')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
feature '/moderation/ screen' do
|
||||||
|
|
||||||
|
background do
|
||||||
|
login_as(@mod.user)
|
||||||
|
end
|
||||||
|
|
||||||
|
feature 'moderate in bulk' do
|
||||||
|
feature 'When an investment has been selected for moderation' do
|
||||||
|
|
||||||
|
background do
|
||||||
|
visit moderation_budget_investments_path
|
||||||
|
|
||||||
|
within('.menu.simple') do
|
||||||
|
click_link 'All'
|
||||||
|
end
|
||||||
|
|
||||||
|
within("#investment_#{@investment.id}") do
|
||||||
|
check "budget_investment_#{@investment.id}_check"
|
||||||
|
end
|
||||||
|
|
||||||
|
expect(page).not_to have_css("investment#{@investment.id}")
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Hide the investment' do
|
||||||
|
click_button 'Hide budget investments'
|
||||||
|
expect(page).not_to have_css("investment_#{@investment.id}")
|
||||||
|
|
||||||
|
@investment.reload
|
||||||
|
|
||||||
|
expect(@investment.author).not_to be_hidden
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Block the author' do
|
||||||
|
click_button 'Block authors'
|
||||||
|
expect(page).not_to have_css("investment_#{@investment.id}")
|
||||||
|
|
||||||
|
@investment.reload
|
||||||
|
|
||||||
|
expect(@investment.author).to be_hidden
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Ignore the investment' do
|
||||||
|
click_button 'Mark as viewed'
|
||||||
|
expect(page).not_to have_css("investment_#{@investment.id}")
|
||||||
|
|
||||||
|
@investment.reload
|
||||||
|
|
||||||
|
expect(@investment).to be_ignored_flag
|
||||||
|
expect(@investment).not_to be_hidden
|
||||||
|
expect(@investment.author).not_to be_hidden
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'select all/none', :js do
|
||||||
|
create_list(:budget_investment, 2, heading: heading, author: create(:user))
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path
|
||||||
|
|
||||||
|
within('.js-check') { click_on 'All' }
|
||||||
|
|
||||||
|
expect(all('input[type=checkbox]')).to all(be_checked)
|
||||||
|
|
||||||
|
within('.js-check') { click_on 'None' }
|
||||||
|
|
||||||
|
all('input[type=checkbox]').each do |checkbox|
|
||||||
|
expect(checkbox).not_to be_checked
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'remembering page, filter and order' do
|
||||||
|
create_list(:budget_investment, 52, heading: heading, author: create(:user))
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'all', page: '2', order: 'created_at')
|
||||||
|
|
||||||
|
click_button 'Mark as viewed'
|
||||||
|
|
||||||
|
expect(page).to have_selector('.js-order-selector[data-order="created_at"]')
|
||||||
|
|
||||||
|
expect(current_url).to include('filter=all')
|
||||||
|
expect(current_url).to include('page=2')
|
||||||
|
expect(current_url).to include('order=created_at')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Current filter is properly highlighted' do
|
||||||
|
visit moderation_budget_investments_path
|
||||||
|
|
||||||
|
expect(page).not_to have_link('Pending')
|
||||||
|
expect(page).to have_link('All')
|
||||||
|
expect(page).to have_link('Marked as viewed')
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'all')
|
||||||
|
|
||||||
|
within('.menu.simple') do
|
||||||
|
expect(page).not_to have_link('All')
|
||||||
|
expect(page).to have_link('Pending')
|
||||||
|
expect(page).to have_link('Marked as viewed')
|
||||||
|
end
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'pending_flag_review')
|
||||||
|
|
||||||
|
within('.menu.simple') do
|
||||||
|
expect(page).to have_link('All')
|
||||||
|
expect(page).not_to have_link('Pending')
|
||||||
|
expect(page).to have_link('Marked as viewed')
|
||||||
|
end
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'with_ignored_flag')
|
||||||
|
|
||||||
|
within('.menu.simple') do
|
||||||
|
expect(page).to have_link('All')
|
||||||
|
expect(page).to have_link('Pending')
|
||||||
|
expect(page).not_to have_link('Marked as viewed')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'Filtering investments' do
|
||||||
|
create(:budget_investment, heading: heading, title: 'Books investment')
|
||||||
|
create(:budget_investment, :flagged, heading: heading, title: 'Non-selected investment')
|
||||||
|
create(:budget_investment, :hidden, heading: heading, title: 'Hidden investment')
|
||||||
|
create(:budget_investment, :flagged, :with_ignored_flag, heading: heading, title: 'Ignored investment')
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'all')
|
||||||
|
|
||||||
|
expect(page).to have_content('Books investment')
|
||||||
|
expect(page).to have_content('Non-selected investment')
|
||||||
|
expect(page).not_to have_content('Hidden investment')
|
||||||
|
expect(page).to have_content('Ignored investment')
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'pending_flag_review')
|
||||||
|
|
||||||
|
expect(page).not_to have_content('Books investment')
|
||||||
|
expect(page).to have_content('Non-selected investment')
|
||||||
|
expect(page).not_to have_content('Hidden investment')
|
||||||
|
expect(page).not_to have_content('Ignored investment')
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'with_ignored_flag')
|
||||||
|
|
||||||
|
expect(page).not_to have_content('Books investment')
|
||||||
|
expect(page).not_to have_content('Non-selected investment')
|
||||||
|
expect(page).not_to have_content('Hidden investment')
|
||||||
|
expect(page).to have_content('Ignored investment')
|
||||||
|
end
|
||||||
|
|
||||||
|
scenario 'sorting investments' do
|
||||||
|
flagged_investment = create(:budget_investment,
|
||||||
|
heading: heading,
|
||||||
|
title: 'Flagged investment',
|
||||||
|
created_at: Time.current - 1.day,
|
||||||
|
flags_count: 5
|
||||||
|
)
|
||||||
|
|
||||||
|
flagged_new_investment = create(:budget_investment,
|
||||||
|
heading: heading,
|
||||||
|
title: 'Flagged new investment',
|
||||||
|
created_at: Time.current - 12.hours,
|
||||||
|
flags_count: 3
|
||||||
|
)
|
||||||
|
|
||||||
|
latest_investment = create(:budget_investment,
|
||||||
|
heading: heading,
|
||||||
|
title: 'Latest investment',
|
||||||
|
created_at: Time.current
|
||||||
|
)
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(order: 'created_at')
|
||||||
|
|
||||||
|
expect(flagged_new_investment.title).to appear_before(flagged_investment.title)
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(order: 'flags')
|
||||||
|
|
||||||
|
expect(flagged_investment.title).to appear_before(flagged_new_investment.title)
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'all', order: 'created_at')
|
||||||
|
|
||||||
|
expect(latest_investment.title).to appear_before(flagged_new_investment.title)
|
||||||
|
expect(flagged_new_investment.title).to appear_before(flagged_investment.title)
|
||||||
|
|
||||||
|
visit moderation_budget_investments_path(filter: 'all', order: 'flags')
|
||||||
|
|
||||||
|
expect(flagged_investment.title).to appear_before(flagged_new_investment.title)
|
||||||
|
expect(flagged_new_investment.title).to appear_before(latest_investment.title)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
Reference in New Issue
Block a user