Merge pull request #2717 from consul/allow-author-notifications-to-be-moderated
Allow author notifications to be moderated
This commit is contained in:
@@ -33,6 +33,7 @@
|
||||
//= require moderator_comment
|
||||
//= require moderator_debates
|
||||
//= require moderator_proposals
|
||||
//= require moderator_proposal_notifications
|
||||
//= require prevent_double_submission
|
||||
//= require gettext
|
||||
//= require annotator
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
App.ModeratorProposalNotifications =
|
||||
|
||||
add_class_faded: (id) ->
|
||||
$("##{id}").addClass("faded")
|
||||
|
||||
hide_moderator_actions: (id) ->
|
||||
$("##{id} .js-moderator-proposal-notifications-actions:first").hide()
|
||||
@@ -1963,7 +1963,8 @@ table {
|
||||
}
|
||||
}
|
||||
|
||||
.comment-body {
|
||||
.comment-body,
|
||||
.notification-body {
|
||||
|
||||
img {
|
||||
margin-right: $line-height / 2;
|
||||
|
||||
30
app/controllers/admin/proposal_notifications_controller.rb
Normal file
30
app/controllers/admin/proposal_notifications_controller.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
class Admin::ProposalNotificationsController < Admin::BaseController
|
||||
|
||||
has_filters %w{without_confirmed_hide all with_confirmed_hide}, only: :index
|
||||
|
||||
before_action :load_proposal, only: [:confirm_hide, :restore]
|
||||
|
||||
def index
|
||||
@proposal_notifications = ProposalNotification.only_hidden.send(@current_filter).order(hidden_at: :desc)
|
||||
.page(params[:page])
|
||||
end
|
||||
|
||||
def confirm_hide
|
||||
@proposal_notification.confirm_hide
|
||||
redirect_to request.query_parameters.merge(action: :index)
|
||||
end
|
||||
|
||||
def restore
|
||||
@proposal_notification.restore
|
||||
@proposal_notification.ignore_flag
|
||||
Activity.log(current_user, :restore, @proposal_notification)
|
||||
redirect_to request.query_parameters.merge(action: :index)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def load_proposal
|
||||
@proposal_notification = ProposalNotification.with_hidden.find(params[:id])
|
||||
end
|
||||
|
||||
end
|
||||
@@ -0,0 +1,24 @@
|
||||
class Moderation::ProposalNotificationsController < Moderation::BaseController
|
||||
include ModerateActions
|
||||
|
||||
has_filters %w{pending_review all ignored}, only: :index
|
||||
has_orders %w{created_at moderated}, only: :index
|
||||
|
||||
before_action :load_resources, only: [:index, :moderate]
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
def hide
|
||||
ProposalNotification.find(params[:id]).update(moderated: true)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def resource_name
|
||||
'proposal_notification'
|
||||
end
|
||||
|
||||
def resource_model
|
||||
ProposalNotification
|
||||
end
|
||||
end
|
||||
@@ -24,6 +24,7 @@ class ProposalsController < ApplicationController
|
||||
def show
|
||||
super
|
||||
@notifications = @proposal.notifications
|
||||
@notifications = @proposal.notifications.not_moderated
|
||||
@related_contents = Kaminari.paginate_array(@proposal.relationed_contents).page(params[:page]).per(5)
|
||||
|
||||
redirect_to proposal_path(@proposal), status: :moved_permanently if request.path != proposal_path(@proposal)
|
||||
|
||||
@@ -52,6 +52,17 @@ module Abilities
|
||||
|
||||
can :block, User
|
||||
cannot :block, User, id: user.id
|
||||
|
||||
can :hide, ProposalNotification, hidden_at: nil
|
||||
cannot :hide, ProposalNotification, author_id: user.id
|
||||
|
||||
can :ignore_flag, ProposalNotification, ignored_at: nil, hidden_at: nil
|
||||
cannot :ignore_flag, ProposalNotification, author_id: user.id
|
||||
|
||||
can :moderate, ProposalNotification
|
||||
cannot :moderate, ProposalNotification, author_id: user.id
|
||||
|
||||
can :index, ProposalNotification
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -11,6 +11,18 @@ class ProposalNotification < ActiveRecord::Base
|
||||
validate :minimum_interval
|
||||
|
||||
scope :public_for_api, -> { where(proposal_id: Proposal.public_for_api.pluck(:id)) }
|
||||
scope :sort_by_created_at, -> { reorder(created_at: :desc) }
|
||||
scope :sort_by_moderated, -> { reorder(moderated: :desc) }
|
||||
|
||||
scope :moderated, -> { where(moderated: true) }
|
||||
scope :not_moderated, -> { where(moderated: false) }
|
||||
scope :pending_review, -> { moderated.where(ignored_at: nil) }
|
||||
scope :ignored, -> { moderated.where.not(ignored_at: nil) }
|
||||
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
after_create :set_author
|
||||
|
||||
def minimum_interval
|
||||
return true if proposal.try(:notifications).blank?
|
||||
@@ -25,4 +37,22 @@ class ProposalNotification < ActiveRecord::Base
|
||||
proposal
|
||||
end
|
||||
|
||||
def ignore_flag
|
||||
update(ignored_at: Time.current)
|
||||
end
|
||||
|
||||
def ignored?
|
||||
ignored_at.present?
|
||||
end
|
||||
|
||||
def after_restore
|
||||
update(moderated: false)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_author
|
||||
self.update(author_id: self.proposal.author_id) if self.proposal
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -182,12 +182,14 @@ 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)
|
||||
proposal_notification_ids = ProposalNotification.where(author_id: id).pluck(:id)
|
||||
|
||||
hide
|
||||
|
||||
Debate.hide_all debates_ids
|
||||
Comment.hide_all comments_ids
|
||||
Proposal.hide_all proposal_ids
|
||||
ProposalNotification.hide_all proposal_notification_ids
|
||||
end
|
||||
|
||||
def erase(erase_reason = nil)
|
||||
|
||||
@@ -149,6 +149,10 @@
|
||||
<%= link_to t("admin.menu.hidden_comments"), admin_comments_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "proposal_notifications" %>>
|
||||
<%= link_to t("admin.menu.hidden_proposal_notifications"), admin_proposal_notifications_path %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "hidden_users" %>>
|
||||
<%= link_to t("admin.menu.hidden_users"), admin_hidden_users_path %>
|
||||
</li>
|
||||
|
||||
49
app/views/admin/proposal_notifications/index.html.erb
Normal file
49
app/views/admin/proposal_notifications/index.html.erb
Normal file
@@ -0,0 +1,49 @@
|
||||
<h2><%= t("admin.proposal_notifications.index.title") %></h2>
|
||||
<p><%= t("admin.shared.moderated_content") %></p>
|
||||
|
||||
<%= render 'shared/filter_subnav', i18n_namespace: "admin.proposal_notifications.index" %>
|
||||
|
||||
<% if @proposal_notifications.any? %>
|
||||
<h3 class="margin"><%= page_entries_info @proposal_notifications %></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>
|
||||
<% @proposal_notifications.each do |proposal_notification| %>
|
||||
<tr id="<%= dom_id(proposal_notification) %>">
|
||||
<td class="align-top">
|
||||
<strong><%= proposal_notification.title %></strong>
|
||||
</td>
|
||||
<td>
|
||||
<div class="moderation-description">
|
||||
<%= proposal_notification.body %>
|
||||
</div>
|
||||
</td>
|
||||
<td class="align-top">
|
||||
<%= link_to t("admin.actions.restore"),
|
||||
restore_admin_proposal_notification_path(proposal_notification, request.query_parameters),
|
||||
method: :put,
|
||||
data: { confirm: t("admin.actions.confirm") },
|
||||
class: "button hollow warning" %>
|
||||
<% unless proposal_notification.confirmed_hide? %>
|
||||
<%= link_to t("admin.actions.confirm_hide"),
|
||||
confirm_hide_admin_proposal_notification_path(proposal_notification, request.query_parameters),
|
||||
method: :put,
|
||||
class: "button" %>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<%= paginate @proposal_notifications %>
|
||||
<% else %>
|
||||
<div class="callout primary margin">
|
||||
<%= t("admin.proposal_notifications.index.no_hidden_proposals") %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -11,6 +11,13 @@
|
||||
<%= t("moderation.menu.proposals") %>
|
||||
<% end %>
|
||||
</li>
|
||||
|
||||
<li <%= "class=is-active" if controller_name == "proposal_notifications" %>>
|
||||
<%= link_to moderation_proposal_notifications_path do %>
|
||||
<span class="icon-proposals"></span>
|
||||
<%= t("moderation.menu.proposal_notifications") %>
|
||||
<% end %>
|
||||
</li>
|
||||
<% end %>
|
||||
|
||||
<% if feature?(:debates) %>
|
||||
|
||||
3
app/views/moderation/proposal_notifications/hide.js.erb
Normal file
3
app/views/moderation/proposal_notifications/hide.js.erb
Normal file
@@ -0,0 +1,3 @@
|
||||
var proposal_notification_id = '<%= dom_id(@proposal_notification) %>';
|
||||
App.ModeratorProposalNotifications.add_class_faded(proposal_notification_id);
|
||||
App.ModeratorProposalNotifications.hide_moderator_actions(proposal_notification_id);
|
||||
67
app/views/moderation/proposal_notifications/index.html.erb
Normal file
67
app/views/moderation/proposal_notifications/index.html.erb
Normal file
@@ -0,0 +1,67 @@
|
||||
<h2><%= t("moderation.proposal_notifications.index.title") %></h2>
|
||||
|
||||
<%= render 'shared/filter_subnav', i18n_namespace: "moderation.proposal_notifications.index" %>
|
||||
|
||||
<h3 class="inline-block"><%= page_entries_info @proposal_notifications %></h3>
|
||||
<div class="float-right">
|
||||
<%= t("moderation.proposal_notifications.index.order") %>
|
||||
<%= render 'shared/order_selector', i18n_namespace: "moderation.proposal_notifications.index" %>
|
||||
</div>
|
||||
|
||||
<%= form_tag moderate_moderation_proposal_notifications_path(request.query_parameters), method: :put do %>
|
||||
<p class="js-check">
|
||||
<%= t('shared.check') %>:
|
||||
<%= link_to t('shared.check_all'), '#', data: {check_all: "proposal_notification_ids[]"} %>
|
||||
|
|
||||
<%= link_to t('shared.check_none'), '#', data: {check_none: "proposal_notification_ids[]"} %>
|
||||
</p>
|
||||
|
||||
<table class="clear">
|
||||
<tr>
|
||||
<th>
|
||||
<%= t("moderation.proposal_notifications.index.headers.proposal_notification") %>
|
||||
</th>
|
||||
<th>
|
||||
<%= t("moderation.proposal_notifications.index.headers.moderate") %>
|
||||
</th>
|
||||
</tr>
|
||||
<% @proposal_notifications.each do |proposal_notification| %>
|
||||
<tr id="proposal_notification_<%= proposal_notification.id %>">
|
||||
<td>
|
||||
<%= link_to proposal_notification.title, proposal_notification, target: "_blank" %>
|
||||
<br>
|
||||
<span class="date"><%= l proposal_notification.updated_at.to_date %></span>
|
||||
<br>
|
||||
<div class="moderation-description">
|
||||
<%= proposal_notification.body %>
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<%= check_box_tag "proposal_notification_ids[]", proposal_notification.id, nil, id: "#{dom_id(proposal_notification)}_check" %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
<%= submit_tag t('moderation.proposal_notifications.index.block_authors'),
|
||||
name: "block_authors",
|
||||
class: "button hollow alert",
|
||||
data: {confirm: t('moderation.proposal_notifications.index.confirm')}
|
||||
%>
|
||||
|
||||
<div class="float-right">
|
||||
<%= submit_tag t('moderation.proposal_notifications.index.hide_proposal_notifications'),
|
||||
name: "hide_proposal_notifications",
|
||||
class: "button hollow alert",
|
||||
data: {confirm: t('moderation.proposal_notifications.index.confirm')}
|
||||
%>
|
||||
<%= submit_tag t('moderation.proposal_notifications.index.ignore_flags'),
|
||||
name: "ignore_flags",
|
||||
class: "button hollow",
|
||||
data: {confirm: t('moderation.proposal_notifications.index.confirm')}
|
||||
%>
|
||||
</div>
|
||||
|
||||
<%= paginate @proposal_notifications %>
|
||||
|
||||
<% end %>
|
||||
14
app/views/proposal_notifications/_actions.html.erb
Normal file
14
app/views/proposal_notifications/_actions.html.erb
Normal file
@@ -0,0 +1,14 @@
|
||||
<div class="reply">
|
||||
<span class='js-moderation-actions'>
|
||||
<% if can? :hide, notification %>
|
||||
<%= link_to t("admin.actions.hide").capitalize, hide_moderation_proposal_notification_path(notification),
|
||||
method: :put, remote: true, data: { confirm: t('admin.actions.confirm') } %>
|
||||
<% end %>
|
||||
|
||||
<% if can? :hide, notification.author %>
|
||||
<span class="divider"> • </span>
|
||||
<%= link_to t("admin.actions.hide_author").capitalize, hide_moderation_user_path(notification.author_id),
|
||||
method: :put, data: { confirm: t('admin.actions.confirm') } %>
|
||||
<% end %>
|
||||
</span>
|
||||
</div>
|
||||
@@ -1,6 +1,6 @@
|
||||
<div class="tabs-panel" id="tab-notifications" role="tab">
|
||||
<div class="row">
|
||||
<div class="small-12 column">
|
||||
<div id="proposal_notifications" class="small-12 column notification-body">
|
||||
<% if @notifications.blank? %>
|
||||
<div class="callout primary text-center">
|
||||
<%= t('proposals.show.no_notifications') %>
|
||||
@@ -8,9 +8,15 @@
|
||||
<% end %>
|
||||
|
||||
<% @notifications.each do |notification| %>
|
||||
<div id="<%= dom_id(notification) %>">
|
||||
<h3><%= notification.title %></h3>
|
||||
<p class="more-info"><%= notification.created_at.to_date %></p>
|
||||
<p><%= notification.body %></p>
|
||||
<%= simple_format text_with_links(notification.body), {}, sanitize: false %>
|
||||
|
||||
<span class="js-flag-actions">
|
||||
<%= render 'proposal_notifications/actions', notification: notification %>
|
||||
</span>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -129,6 +129,7 @@ ignore_unused:
|
||||
- 'admin.banners.index.filters.*'
|
||||
- 'admin.debates.index.filter*'
|
||||
- 'admin.proposals.index.filter*'
|
||||
- 'admin.proposal_notifications.index.filter*'
|
||||
- 'admin.budgets.index.filter*'
|
||||
- 'admin.budget_investments.index.filter*'
|
||||
- 'admin.spending_proposals.index.filter*'
|
||||
@@ -151,6 +152,8 @@ ignore_unused:
|
||||
- 'moderation.proposals.index.order*'
|
||||
- 'moderation.debates.index.filter*'
|
||||
- 'moderation.debates.index.order*'
|
||||
- 'moderation.proposal_notifications.index.filter*'
|
||||
- 'moderation.proposal_notifications.index.order*'
|
||||
- 'valuation.spending_proposals.index.filter*'
|
||||
- 'valuation.budgets.index.filter*'
|
||||
- 'valuation.budget_investments.index.filter*'
|
||||
|
||||
@@ -103,6 +103,9 @@ en:
|
||||
poll:
|
||||
one: "Poll"
|
||||
other: "Polls"
|
||||
proposal_notification:
|
||||
one: "Proposal notification"
|
||||
other: "Proposal notifications"
|
||||
attributes:
|
||||
budget:
|
||||
name: "Name"
|
||||
|
||||
@@ -504,6 +504,7 @@ en:
|
||||
hidden_comments: Hidden comments
|
||||
hidden_debates: Hidden debates
|
||||
hidden_proposals: Hidden proposals
|
||||
hidden_proposal_notifications: Hidden proposal notifications
|
||||
hidden_users: Hidden users
|
||||
administrators: Administrators
|
||||
managers: Managers
|
||||
@@ -940,6 +941,15 @@ en:
|
||||
without_confirmed_hide: Pending
|
||||
title: Hidden proposals
|
||||
no_hidden_proposals: There is no hidden proposals.
|
||||
proposal_notifications:
|
||||
index:
|
||||
filter: Filter
|
||||
filters:
|
||||
all: All
|
||||
with_confirmed_hide: Confirmed
|
||||
without_confirmed_hide: Pending
|
||||
title: Hidden notifications
|
||||
no_hidden_proposals: There is no hidden notifications.
|
||||
settings:
|
||||
flash:
|
||||
updated: Value updated
|
||||
|
||||
@@ -47,6 +47,7 @@ en:
|
||||
flagged_comments: Comments
|
||||
flagged_debates: Debates
|
||||
proposals: Proposals
|
||||
proposal_notifications: Proposals notifications
|
||||
users: Block users
|
||||
proposals:
|
||||
index:
|
||||
@@ -67,6 +68,25 @@ en:
|
||||
created_at: Most recent
|
||||
flags: Most flagged
|
||||
title: Proposals
|
||||
proposal_notifications:
|
||||
index:
|
||||
block_authors: Block authors
|
||||
confirm: Are you sure?
|
||||
filter: Filter
|
||||
filters:
|
||||
all: All
|
||||
pending_review: Pending review
|
||||
ignored: Mark as viewed
|
||||
headers:
|
||||
moderate: Moderate
|
||||
proposal_notification: Proposal notification
|
||||
hide_proposal_notifications: Hide proposals
|
||||
ignore_flags: Mark as viewed
|
||||
order: Order by
|
||||
orders:
|
||||
created_at: Most recent
|
||||
moderated: Moderated
|
||||
title: Proposal notifications
|
||||
users:
|
||||
index:
|
||||
hidden: Blocked
|
||||
|
||||
@@ -103,6 +103,9 @@ es:
|
||||
poll:
|
||||
one: "Votación"
|
||||
other: "Votaciones"
|
||||
proposal_notification:
|
||||
one: "Notificación de propuesta"
|
||||
other: "Notificaciones de propuestas"
|
||||
attributes:
|
||||
budget:
|
||||
name: "Nombre"
|
||||
|
||||
@@ -504,6 +504,7 @@ es:
|
||||
hidden_comments: Comentarios ocultos
|
||||
hidden_debates: Debates ocultos
|
||||
hidden_proposals: Propuestas ocultas
|
||||
hidden_proposal_notifications: Notificationes de propuesta ocultas
|
||||
hidden_users: Usuarios bloqueados
|
||||
administrators: Administradores
|
||||
managers: Gestores
|
||||
@@ -940,6 +941,15 @@ es:
|
||||
without_confirmed_hide: Pendientes
|
||||
title: Propuestas ocultas
|
||||
no_hidden_proposals: No hay propuestas ocultas.
|
||||
proposal_notifications:
|
||||
index:
|
||||
filter: Filtro
|
||||
filters:
|
||||
all: Todas
|
||||
with_confirmed_hide: Confirmadas
|
||||
without_confirmed_hide: Pendientes
|
||||
title: Notificaciones ocultas
|
||||
no_hidden_proposals: No hay notificaciones ocultas.
|
||||
settings:
|
||||
flash:
|
||||
updated: Valor actualizado
|
||||
|
||||
@@ -47,6 +47,7 @@ es:
|
||||
flagged_comments: Comentarios
|
||||
flagged_debates: Debates
|
||||
proposals: Propuestas
|
||||
proposal_notifications: Notificaciones de propuestas
|
||||
users: Bloquear usuarios
|
||||
proposals:
|
||||
index:
|
||||
@@ -67,6 +68,25 @@ es:
|
||||
created_at: Más recientes
|
||||
flags: Más denunciadas
|
||||
title: Propuestas
|
||||
proposal_notifications:
|
||||
index:
|
||||
block_authors: Bloquear autores
|
||||
confirm: '¿Estás seguro?'
|
||||
filter: Filtro
|
||||
filters:
|
||||
all: Todas
|
||||
pending_review: Pendientes de revisión
|
||||
ignored: Marcadas como revisadas
|
||||
headers:
|
||||
moderate: Moderar
|
||||
proposal_notification: Notificación de propuesta
|
||||
hide_proposal_notifications: Ocultar notificaciones
|
||||
ignore_flags: Marcar como revisadas
|
||||
order: Ordenar por
|
||||
orders:
|
||||
created_at: Más recientes
|
||||
moderated: Moderadas
|
||||
title: Notificaciones de propuestas
|
||||
users:
|
||||
index:
|
||||
hidden: Bloqueado
|
||||
|
||||
@@ -38,6 +38,13 @@ namespace :admin do
|
||||
get :summary, on: :collection
|
||||
end
|
||||
|
||||
resources :proposal_notifications, only: :index do
|
||||
member do
|
||||
put :restore
|
||||
put :confirm_hide
|
||||
end
|
||||
end
|
||||
|
||||
resources :budgets do
|
||||
member do
|
||||
put :calculate_winners
|
||||
|
||||
@@ -22,4 +22,9 @@ namespace :moderation do
|
||||
put :hide, on: :member
|
||||
put :moderate, on: :collection
|
||||
end
|
||||
|
||||
resources :proposal_notifications, only: :index do
|
||||
put :hide, on: :member
|
||||
put :moderate, on: :collection
|
||||
end
|
||||
end
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
class AddModerationFlagsToProposalNotifications < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :proposal_notifications, :moderated, :boolean, default: false
|
||||
add_column :proposal_notifications, :hidden_at, :datetime
|
||||
add_column :proposal_notifications, :ignored_at, :datetime
|
||||
add_column :proposal_notifications, :confirmed_hide_at, :datetime
|
||||
end
|
||||
end
|
||||
@@ -876,6 +876,10 @@ ActiveRecord::Schema.define(version: 20180519132610) do
|
||||
t.integer "proposal_id"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.boolean "moderated", default: false
|
||||
t.datetime "hidden_at"
|
||||
t.datetime "ignored_at"
|
||||
t.datetime "confirmed_hide_at"
|
||||
end
|
||||
|
||||
create_table "proposals", force: :cascade do |t|
|
||||
|
||||
@@ -749,6 +749,23 @@ FactoryBot.define do
|
||||
sequence(:title) { |n| "Thank you for supporting my proposal #{n}" }
|
||||
sequence(:body) { |n| "Please let others know so we can make it happen #{n}" }
|
||||
proposal
|
||||
association :author, factory: :user
|
||||
|
||||
trait :moderated do
|
||||
moderated true
|
||||
end
|
||||
|
||||
trait :ignored do
|
||||
ignored_at Date.current
|
||||
end
|
||||
|
||||
trait :hidden do
|
||||
hidden_at Date.current
|
||||
end
|
||||
|
||||
trait :with_confirmed_hide do
|
||||
confirmed_hide_at Time.current
|
||||
end
|
||||
end
|
||||
|
||||
factory :direct_message do
|
||||
|
||||
95
spec/features/admin/proposal_notifications_spec.rb
Normal file
95
spec/features/admin/proposal_notifications_spec.rb
Normal file
@@ -0,0 +1,95 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Admin proposal notifications' do
|
||||
|
||||
background do
|
||||
admin = create(:administrator)
|
||||
login_as(admin.user)
|
||||
end
|
||||
|
||||
scenario 'List shows all relevant info' do
|
||||
proposal_notification = create(:proposal_notification, :hidden)
|
||||
visit admin_proposal_notifications_path
|
||||
|
||||
expect(page).to have_content(proposal_notification.title)
|
||||
expect(page).to have_content(proposal_notification.body)
|
||||
end
|
||||
|
||||
scenario 'Restore' do
|
||||
proposal_notification = create(:proposal_notification, :hidden, created_at: Date.current - 5.days)
|
||||
visit admin_proposal_notifications_path
|
||||
|
||||
click_link 'Restore'
|
||||
|
||||
expect(page).not_to have_content(proposal_notification.title)
|
||||
|
||||
expect(proposal_notification.reload).not_to be_hidden
|
||||
expect(proposal_notification).to be_ignored
|
||||
expect(proposal_notification).not_to be_moderated
|
||||
end
|
||||
|
||||
scenario 'Confirm hide' do
|
||||
proposal_notification = create(:proposal_notification, :hidden, created_at: Date.current - 5.days)
|
||||
visit admin_proposal_notifications_path
|
||||
|
||||
click_link 'Confirm moderation'
|
||||
|
||||
expect(page).not_to have_content(proposal_notification.title)
|
||||
click_link('Confirmed')
|
||||
expect(page).to have_content(proposal_notification.title)
|
||||
|
||||
expect(proposal_notification.reload).to be_confirmed_hide
|
||||
end
|
||||
|
||||
scenario "Current filter is properly highlighted" do
|
||||
visit admin_proposal_notifications_path
|
||||
expect(page).not_to have_link('Pending')
|
||||
expect(page).to have_link('All')
|
||||
expect(page).to have_link('Confirmed')
|
||||
|
||||
visit admin_proposal_notifications_path(filter: 'Pending')
|
||||
expect(page).not_to have_link('Pending')
|
||||
expect(page).to have_link('All')
|
||||
expect(page).to have_link('Confirmed')
|
||||
|
||||
visit admin_proposal_notifications_path(filter: 'all')
|
||||
expect(page).to have_link('Pending')
|
||||
expect(page).not_to have_link('All')
|
||||
expect(page).to have_link('Confirmed')
|
||||
|
||||
visit admin_proposal_notifications_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 proposals" do
|
||||
create(:proposal_notification, :hidden, title: "Unconfirmed notification")
|
||||
create(:proposal_notification, :hidden, :with_confirmed_hide, title: "Confirmed notification")
|
||||
|
||||
visit admin_proposal_notifications_path(filter: 'pending')
|
||||
expect(page).to have_content('Unconfirmed notification')
|
||||
expect(page).not_to have_content('Confirmed notification')
|
||||
|
||||
visit admin_proposal_notifications_path(filter: 'all')
|
||||
expect(page).to have_content('Unconfirmed notification')
|
||||
expect(page).to have_content('Confirmed notification')
|
||||
|
||||
visit admin_proposal_notifications_path(filter: 'with_confirmed_hide')
|
||||
expect(page).not_to have_content('Unconfirmed notification')
|
||||
expect(page).to have_content('Confirmed notification')
|
||||
end
|
||||
|
||||
scenario "Action links remember the pagination setting and the filter" do
|
||||
per_page = Kaminari.config.default_per_page
|
||||
(per_page + 2).times { create(:proposal_notification, :hidden, :with_confirmed_hide) }
|
||||
|
||||
visit admin_proposal_notifications_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
|
||||
189
spec/features/moderation/proposal_notifications_spec.rb
Normal file
189
spec/features/moderation/proposal_notifications_spec.rb
Normal file
@@ -0,0 +1,189 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Moderate proposal notifications' do
|
||||
|
||||
scenario 'Hide', :js do
|
||||
citizen = create(:user)
|
||||
proposal = create(:proposal)
|
||||
proposal_notification = create(:proposal_notification, proposal: proposal, created_at: Date.current - 4.days)
|
||||
moderator = create(:moderator)
|
||||
|
||||
login_as(moderator.user)
|
||||
visit proposal_path(proposal)
|
||||
click_link "Notifications (1)"
|
||||
|
||||
within("#proposal_notification_#{proposal_notification.id}") do
|
||||
accept_confirm { click_link 'Hide' }
|
||||
end
|
||||
|
||||
expect(page).to have_css("#proposal_notification_#{proposal.id}.faded")
|
||||
|
||||
logout
|
||||
login_as(citizen)
|
||||
visit proposal_path(proposal)
|
||||
|
||||
expect(page).to have_content "Notifications (0)"
|
||||
end
|
||||
|
||||
scenario 'Can not hide own proposal notification' do
|
||||
moderator = create(:moderator)
|
||||
proposal = create(:proposal, author: moderator.user)
|
||||
proposal_notification = create(:proposal_notification, proposal: proposal, created_at: Date.current - 4.days)
|
||||
|
||||
login_as(moderator.user)
|
||||
visit proposal_path(proposal)
|
||||
|
||||
within("#proposal_notification_#{proposal_notification.id}") do
|
||||
expect(page).not_to have_link('Hide')
|
||||
expect(page).not_to have_link('Block author')
|
||||
end
|
||||
end
|
||||
|
||||
feature '/moderation/ screen' do
|
||||
|
||||
background do
|
||||
moderator = create(:moderator)
|
||||
login_as(moderator.user)
|
||||
end
|
||||
|
||||
feature 'moderate in bulk' do
|
||||
feature "When a proposal has been selected for moderation" do
|
||||
background do
|
||||
proposal = create(:proposal)
|
||||
@proposal_notification = create(:proposal_notification, proposal: proposal, created_at: Date.current - 4.days)
|
||||
visit moderation_proposal_notifications_path
|
||||
within('.menu.simple') do
|
||||
click_link "All"
|
||||
end
|
||||
|
||||
within("#proposal_notification_#{@proposal_notification.id}") do
|
||||
check "proposal_notification_#{@proposal_notification.id}_check"
|
||||
end
|
||||
end
|
||||
|
||||
scenario 'Hide the proposal' do
|
||||
click_on "Hide proposals"
|
||||
expect(page).not_to have_css("#proposal_notification_#{@proposal_notification.id}")
|
||||
expect(@proposal_notification.reload).to be_hidden
|
||||
expect(@proposal_notification.author).not_to be_hidden
|
||||
end
|
||||
|
||||
scenario 'Block the author' do
|
||||
author = create(:user)
|
||||
@proposal_notification.update(author: author)
|
||||
click_on "Block authors"
|
||||
expect(page).not_to have_css("#proposal_notification_#{@proposal_notification.id}")
|
||||
expect(@proposal_notification.reload).to be_hidden
|
||||
expect(author.reload).to be_hidden
|
||||
end
|
||||
|
||||
scenario 'Ignore the proposal' do
|
||||
click_button "Mark as viewed"
|
||||
|
||||
expect(@proposal_notification.reload).to be_ignored
|
||||
expect(@proposal_notification.reload).not_to be_hidden
|
||||
expect(@proposal_notification.author).not_to be_hidden
|
||||
end
|
||||
end
|
||||
|
||||
scenario "select all/none", :js do
|
||||
create_list(:proposal_notification, 2)
|
||||
|
||||
visit moderation_proposal_notifications_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(:proposal, 52)
|
||||
|
||||
visit moderation_proposal_notifications_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_proposal_notifications_path
|
||||
expect(page).not_to have_link('Pending review')
|
||||
expect(page).to have_link('All')
|
||||
expect(page).to have_link('Mark as viewed')
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'all')
|
||||
within('.menu.simple') do
|
||||
expect(page).not_to have_link('All')
|
||||
expect(page).to have_link('Pending review')
|
||||
expect(page).to have_link('Mark as viewed')
|
||||
end
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'pending_review')
|
||||
within('.menu.simple') do
|
||||
expect(page).to have_link('All')
|
||||
expect(page).not_to have_link('Pending review')
|
||||
expect(page).to have_link('Mark as viewed')
|
||||
end
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'ignored')
|
||||
within('.menu.simple') do
|
||||
expect(page).to have_link('All')
|
||||
expect(page).to have_link('Pending review')
|
||||
expect(page).not_to have_link('Marked as viewed')
|
||||
end
|
||||
end
|
||||
|
||||
scenario "Filtering proposals" do
|
||||
proposal = create(:proposal)
|
||||
create(:proposal_notification, title: "Regular proposal", proposal: proposal)
|
||||
create(:proposal_notification, :moderated, title: "Pending proposal", proposal: proposal)
|
||||
create(:proposal_notification, :hidden, title: "Hidden proposal", proposal: proposal)
|
||||
create(:proposal_notification, :moderated, :ignored, title: "Ignored proposal", proposal: proposal)
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'all')
|
||||
expect(page).to have_content('Regular proposal')
|
||||
expect(page).to have_content('Pending proposal')
|
||||
expect(page).not_to have_content('Hidden proposal')
|
||||
expect(page).to have_content('Ignored proposal')
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'pending_review')
|
||||
expect(page).not_to have_content('Regular proposal')
|
||||
expect(page).to have_content('Pending proposal')
|
||||
expect(page).not_to have_content('Hidden proposal')
|
||||
expect(page).not_to have_content('Ignored proposal')
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'ignored')
|
||||
expect(page).not_to have_content('Regular proposal')
|
||||
expect(page).not_to have_content('Pending proposal')
|
||||
expect(page).not_to have_content('Hidden proposal')
|
||||
expect(page).to have_content('Ignored proposal')
|
||||
end
|
||||
|
||||
scenario "sorting proposal notifications" do
|
||||
moderated_notification = create(:proposal_notification, :moderated, title: "Moderated notification", created_at: Time.current - 1.day)
|
||||
moderated_new_notification = create(:proposal_notification, :moderated, title: "Moderated new notification", created_at: Time.current - 12.hours)
|
||||
newer_notification = create(:proposal_notification, title: "Newer notification", created_at: Time.current)
|
||||
old_moderated_notification = create(:proposal_notification, :moderated, title: "Older notification", created_at: Time.current - 2.days)
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'all', order: 'created_at')
|
||||
|
||||
expect(moderated_new_notification.title).to appear_before(moderated_notification.title)
|
||||
|
||||
visit moderation_proposal_notifications_path(filter: 'all', order: 'moderated')
|
||||
|
||||
expect(old_moderated_notification.title).to appear_before(newer_notification.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user