Merge pull request #234 from AyuntamientoMadrid/moderator_comments

Moderator/Administrator comments
This commit is contained in:
Raimond Garcia
2015-08-24 19:05:51 +02:00
18 changed files with 290 additions and 43 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -249,6 +249,7 @@
.panel {
border: 0;
border-radius: 0;
margin-bottom: 0;
min-height: rem-calc(192);
padding: 0 rem-calc(12) rem-calc(2) rem-calc(12);
@@ -567,6 +568,15 @@
background: $comment-author;
padding: rem-calc(6) rem-calc(12);
}
&.is-admin {
background: $comment-admin;
padding: rem-calc(6) rem-calc(12);
}
&.is-moderator {
@extend .is-admin;
}
}
}

View File

@@ -548,19 +548,19 @@ form {
line-height: $line-height;
}
input[type]:not([type=submit]):not([type=file]) {
input[type]:not([type=submit]):not([type=file]):not([type=checkbox]) {
background: $input-bg;
height: rem-calc(48);
margin-bottom: rem-calc(16);
}
input[type="checkbox"] {
height: rem-calc(24) !important;
margin: 0 !important;
input[type="checkbox"] + label,
input[type="radio"] + label {
margin-right: 0;
}
input[type=file] {
margin: rem-calc(12) 0;
margin: rem-calc(12) 0 rem-calc(12) rem-calc(6);
}
.note {
@@ -579,8 +579,7 @@ form {
font-size: rem-calc(14);
font-weight: normal;
line-height: $line-height;
margin: 0 0 0 rem-calc(6);
vertical-align: top;
vertical-align: middle;
}
.captcha {
@@ -591,6 +590,10 @@ form {
margin-bottom: 0 !important;
}
}
.button.margin-top {
margin-top: rem-calc(24);
}
}
// 09. Alerts
@@ -689,11 +692,15 @@ form {
}
}
img.initialjs-avatar, img.avatar {
img.admin-avatar, img.moderator-avatar {
border-radius: rem-calc(1000);
position: relative;
}
img.initialjs-avatar {
@extend .moderator-avatar;
}
.author-deleted {
background-color: rgba(255,255,255,.5);
color: rgba(0,0,0,.4);

View File

@@ -77,8 +77,9 @@ $author: #008CCF;
$association: #C0392B;
$comment-author: rgba(45,144,248,.15);
$comment-official: rgba(70,219,145,.3);
$comment-level-5: rgba(255,241,204,1);
$comment-admin: rgba(45,144,248,.15);
$comment-official: rgba(70,219,145,.3);
// 06. Responsive
// - - - - - - - - - - - - - - - - - - - - - - - - -

View File

@@ -35,11 +35,20 @@ class CommentsController < ApplicationController
private
def comment_params
params.require(:comment).permit(:commentable_type, :commentable_id, :body)
params.require(:comment).permit(:commentable_type, :commentable_id, :body, :as_moderator, :as_administrator)
end
def build_comment
@comment = Comment.build(debate, current_user, comment_params[:body])
check_for_special_comments
end
def check_for_special_comments
if administrator_comment?
@comment.administrator_id = current_user.administrator.id
elsif moderator_comment?
@comment.moderator_id = current_user.moderator.id
end
end
def debate
@@ -62,4 +71,12 @@ class CommentsController < ApplicationController
reply? && parent.author.email_on_comment_reply?
end
def administrator_comment?
["1", true].include?(comment_params[:as_administrator]) && can?(:comment_as_administrator, Debate)
end
def moderator_comment?
["1", true].include?(comment_params[:as_moderator]) && can?(:comment_as_moderator, Debate)
end
end

View File

@@ -66,10 +66,15 @@ class Ability
cannot :hide, User, id: user.id
end
if user.moderator?
can :comment_as_moderator, [Debate, Comment]
end
if user.administrator?
can :restore, Comment
can :restore, Debate
can :restore, User
can :comment_as_administrator, [Debate, Comment]
end
end
end

View File

@@ -1,10 +1,11 @@
class Comment < ActiveRecord::Base
include ActsAsParanoidAliases
acts_as_nested_set scope: [:commentable_id, :commentable_type], counter_cache: :children_count
acts_as_paranoid column: :hidden_at
acts_as_votable
attr_accessor :as_moderator, :as_administrator
validates :body, presence: true
validates :user, presence: true
@@ -59,6 +60,14 @@ class Comment < ActiveRecord::Base
reviewed_at.present?
end
def as_administrator?
administrator_id.present?
end
def as_moderator?
moderator_id.present?
end
def mark_as_reviewed
update(reviewed_at: Time.now)
end

View File

@@ -5,6 +5,12 @@
<%= t("debates.comment.deleted") %>
<% else %>
<% if comment.as_administrator? %>
<%= image_tag("admin_avatar.png", size: 32, class: "admin-avatar left") %>
<% elsif comment.as_moderator? %>
<%= image_tag("moderator_avatar.png", size: 32, class: "moderator-avatar left") %>
<% else %>
<% if comment.user.organization? %>
<%= image_tag("collective_avatar.png", size: 32, class: "avatar left") %>
<% else %>
@@ -14,9 +20,17 @@
<i class="icon-deleted user-deleted"></i>
<% end %>
<% end %>
<div class="comment-body">
<div class="comment-info">
<% if comment.as_administrator? %>
<span class="user-name"><%= t("debates.comment.admin") %> #<%= comment.administrator_id%></span>
<% elsif comment.as_moderator? %>
<span class="user-name"><%= t("debates.comment.moderator") %> #<%= comment.moderator_id%></span>
<% else %>
<% if comment.user.hidden? %>
<span class="user-name"><%= t("debates.comment.user_deleted") %></span>
<% else %>
@@ -40,15 +54,21 @@
<%= t("debates.comment.author") %>
</span>
<% end %>
<% end %>
&nbsp;&bullet;&nbsp;<%= time_ago_in_words(comment.created_at) %>
<span class="right js-flag-as-inappropiate-actions">
<%= render 'comments/flag_as_inappropiate_actions', comment: comment %>
</span>
</div>
<% if comment.user.official? && comment.user_id == @debate.author_id %>
<% if comment.as_administrator? %>
<p class="comment-user is-admin"><%= comment.body %></p>
<% elsif comment.as_moderator? %>
<p class="comment-user is-moderator"><%= comment.body %></p>
<% elsif comment.user.official? && comment.user_id == @debate.author_id %>
<p class="comment-user level-<%= comment.user.official_level %> is-author"><%= comment.body %></p>
<% elsif comment.user.official? %>
<p class="comment-user level-<%= comment.user.official_level %>"><%= comment.body %></p>
@@ -81,6 +101,5 @@
<div class="comment-children">
<%= render comment.children.with_hidden.reorder('id DESC, lft') %>
</div>
</div>
</div>

View File

@@ -4,6 +4,19 @@
<%= f.hidden_field :commentable_type, value: parent.class %>
<%= f.hidden_field :commentable_id, value: parent.id %>
<%= f.submit comment_button_text(parent), class: "button radius small" %>
<%= f.submit comment_button_text(parent), class: "button radius small inline-block" %>
<% if can? :comment_as_moderator, @debate %>
<div class="right">
<%= f.check_box :as_moderator, label: false %>
<%= f.label :as_moderator, t("comments.form.comment_as_moderator"), class: "checkbox" %>
</div>
<% end %>
<% if can? :comment_as_administrator, @debate %>
<div class="right">
<%= f.check_box :as_administrator, label: false %>
<%= f.label :as_administrator, t("comments.form.comment_as_admin"), class: "checkbox" %>
</div>
<% end %>
<% end %>
</div>

View File

@@ -49,6 +49,8 @@ en:
other: "%{count} votes"
comment:
author: Debate's author
moderator: Moderator
admin: Administrator
deleted: This comment has been deleted
user_deleted: Deleted user
responses:
@@ -95,6 +97,8 @@ en:
comments:
form:
leave_comment: Write a comment
comment_as_moderator: Comment as moderator
comment_as_admin: Comment as administrator
comments_helper:
comment_link: Comment
comment_button: Publish comment

View File

@@ -49,6 +49,8 @@ es:
other: "%{count} votos"
comment:
author: Autor del debate
moderator: Moderador
admin: Administrador
deleted: Este comentario ha sido eliminado
user_deleted: Usuario eliminado
responses:
@@ -95,6 +97,8 @@ es:
comments:
form:
leave_comment: Deja tu comentario
comment_as_moderator: Comentar como moderador
comment_as_admin: Comentar como administrador
comments_helper:
comment_link: Comentar
comment_button: Publicar comentario

View File

@@ -0,0 +1,5 @@
class AddModeratorIdToComment < ActiveRecord::Migration
def change
add_column :comments, :moderator_id, :integer, default: nil
end
end

View File

@@ -0,0 +1,5 @@
class AddAdministratorIdToComment < ActiveRecord::Migration
def change
add_column :comments, :administrator_id, :integer, default: nil
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20150821180155) do
ActiveRecord::Schema.define(version: 20150824113326) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -52,6 +52,8 @@ ActiveRecord::Schema.define(version: 20150821180155) do
t.datetime "flagged_as_inappropiate_at"
t.integer "inappropiate_flags_count", default: 0
t.datetime "reviewed_at"
t.integer "moderator_id"
t.integer "administrator_id"
end
add_index "comments", ["commentable_id", "commentable_type"], name: "index_comments_on_commentable_id_and_commentable_type", using: :btree

View File

@@ -168,4 +168,122 @@ feature 'Comments' do
expect(InappropiateFlag.flagged?(user, comment)).to_not be
end
feature "Moderators" do
scenario "can create comment as a moderator", :js do
moderator = create(:moderator)
debate = create(:debate)
login_as(moderator.user)
visit debate_path(debate)
fill_in "comment_body", with: "I am moderating!"
check "comment_as_moderator"
click_button "Publish comment"
within "#comments" do
expect(page).to have_content "I am moderating!"
expect(page).to have_content "Moderator ##{moderator.id}"
expect(page).to have_css "p.is-moderator"
expect(page).to have_css "img.moderator-avatar"
end
end
scenario "can create reply as a moderator", :js do
citizen = create(:user, username: "Ana")
manuela = create(:user, username: "Manuela")
moderator = create(:moderator, user: manuela)
debate = create(:debate)
comment = create(:comment, commentable: debate, user: citizen)
login_as(manuela)
visit debate_path(debate)
click_link "Reply"
within "#js-comment-form-comment_#{comment.id}" do
fill_in "comment_body", with: "I am moderating!"
check "comment_as_moderator"
click_button 'Publish reply'
end
within "#comment_#{comment.id}" do
expect(page).to have_content "I am moderating!"
expect(page).to have_content "Moderator ##{moderator.id}"
expect(page).to have_css "p.is-moderator"
expect(page).to have_css "img.moderator-avatar"
end
expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true)
end
scenario "can not comment as an administrator" do
moderator = create(:moderator)
debate = create(:debate)
login_as(moderator.user)
visit debate_path(debate)
expect(page).to_not have_content "Comment as administrator"
end
end
feature "Administrators" do
scenario "can create comment as an administrator", :js do
admin = create(:administrator)
debate = create(:debate)
login_as(admin.user)
visit debate_path(debate)
fill_in "comment_body", with: "I am your Admin!"
check "comment_as_administrator"
click_button "Publish comment"
within "#comments" do
expect(page).to have_content "I am your Admin!"
expect(page).to have_content "Administrator ##{admin.id}"
expect(page).to have_css "p.is-admin"
expect(page).to have_css "img.admin-avatar"
end
end
scenario "can create reply as an administrator", :js do
citizen = create(:user, username: "Ana")
manuela = create(:user, username: "Manuela")
admin = create(:administrator, user: manuela)
debate = create(:debate)
comment = create(:comment, commentable: debate, user: citizen)
login_as(manuela)
visit debate_path(debate)
click_link "Reply"
within "#js-comment-form-comment_#{comment.id}" do
fill_in "comment_body", with: "Top of the world!"
check "comment_as_administrator"
click_button 'Publish reply'
end
within "#comment_#{comment.id}" do
expect(page).to have_content "Top of the world!"
expect(page).to have_content "Administrator ##{admin.id}"
expect(page).to have_css "p.is-admin"
expect(page).to have_css "img.admin-avatar"
end
expect(page).to_not have_selector("#js-comment-form-comment_#{comment.id}", visible: true)
end
scenario "can not comment as a moderator" do
admin = create(:administrator)
debate = create(:debate)
login_as(admin.user)
visit debate_path(debate)
expect(page).to_not have_content "Comment as moderator"
end
end
end

View File

@@ -22,13 +22,15 @@ describe Ability do
it { should be_able_to(:show, debate) }
it { should be_able_to(:vote, debate) }
it { should be_able_to(:show, user) }
it { should be_able_to(:edit, user) }
it { should be_able_to(:create, Comment) }
it { should be_able_to(:vote, Comment) }
it { should_not be_able_to(:comment_as_administrator, debate) }
it { should_not be_able_to(:comment_as_moderator, debate) }
describe 'flagging content as inappropiate' do
it { should be_able_to(:flag_as_inappropiate, debate) }
it { should_not be_able_to(:undo_flag_as_inappropiate, debate) }
@@ -158,6 +160,9 @@ describe Ability do
it { should_not be_able_to(:restore, comment) }
it { should_not be_able_to(:restore, debate) }
it { should_not be_able_to(:restore, other_user) }
it { should be_able_to(:comment_as_moderator, debate) }
it { should_not be_able_to(:comment_as_administrator, debate) }
end
end
@@ -173,5 +178,8 @@ describe Ability do
it { should be_able_to(:restore, comment) }
it { should be_able_to(:restore, debate) }
it { should be_able_to(:restore, other_user) }
it { should be_able_to(:comment_as_administrator, debate) }
it { should_not be_able_to(:comment_as_moderator, debate) }
end
end

View File

@@ -38,4 +38,24 @@ describe Comment do
expect { new_comment.destroy }.to change { comment.children_count }.from(1).to(0)
end
end
describe "#as_administrator?" do
it "should be true if comment has administrator_id, false otherway" do
expect(comment).not_to be_as_administrator
comment.administrator_id = 33
expect(comment).to be_as_administrator
end
end
describe "#as_moderator?" do
it "should be true if comment has moderator_id, false otherway" do
expect(comment).not_to be_as_moderator
comment.moderator_id = 21
expect(comment).to be_as_moderator
end
end
end