diff --git a/app/assets/images/admin_avatar.png b/app/assets/images/admin_avatar.png
new file mode 100644
index 000000000..28ea4a143
Binary files /dev/null and b/app/assets/images/admin_avatar.png differ
diff --git a/app/assets/images/moderator_avatar.png b/app/assets/images/moderator_avatar.png
new file mode 100644
index 000000000..1c726e57b
Binary files /dev/null and b/app/assets/images/moderator_avatar.png differ
diff --git a/app/assets/stylesheets/debates.scss b/app/assets/stylesheets/debates.scss
index dd29774a5..66ea491af 100644
--- a/app/assets/stylesheets/debates.scss
+++ b/app/assets/stylesheets/debates.scss
@@ -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;
+ }
}
}
diff --git a/app/assets/stylesheets/participacion.scss b/app/assets/stylesheets/participacion.scss
index e6aea4db2..485dbfd60 100644
--- a/app/assets/stylesheets/participacion.scss
+++ b/app/assets/stylesheets/participacion.scss
@@ -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);
diff --git a/app/assets/stylesheets/variables.scss b/app/assets/stylesheets/variables.scss
index 93107e3d2..4be7028e3 100644
--- a/app/assets/stylesheets/variables.scss
+++ b/app/assets/stylesheets/variables.scss
@@ -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
// - - - - - - - - - - - - - - - - - - - - - - - - -
diff --git a/app/controllers/comments_controller.rb b/app/controllers/comments_controller.rb
index 20df3bf2d..798196ca0 100644
--- a/app/controllers/comments_controller.rb
+++ b/app/controllers/comments_controller.rb
@@ -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
diff --git a/app/models/ability.rb b/app/models/ability.rb
index 9032038a1..a29f09a60 100644
--- a/app/models/ability.rb
+++ b/app/models/ability.rb
@@ -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
diff --git a/app/models/comment.rb b/app/models/comment.rb
index 7c18efc6b..824f1dbf0 100644
--- a/app/models/comment.rb
+++ b/app/models/comment.rb
@@ -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
diff --git a/app/views/comments/_comment.html.erb b/app/views/comments/_comment.html.erb
index 75cc9e6dd..ca7474ebd 100644
--- a/app/views/comments/_comment.html.erb
+++ b/app/views/comments/_comment.html.erb
@@ -5,50 +5,70 @@
<%= t("debates.comment.deleted") %>
<% else %>
- <% if comment.user.organization? %>
- <%= image_tag("collective_avatar.png", size: 32, class: "avatar left") %>
+ <% 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 %>
- <%= avatar_image(comment.user, size: 32, class: "left") %>
- <% end %>
- <% if comment.user.hidden? %>
-
+
+ <% if comment.user.organization? %>
+ <%= image_tag("collective_avatar.png", size: 32, class: "avatar left") %>
+ <% else %>
+ <%= avatar_image(comment.user, size: 32, class: "left") %>
+ <% end %>
+ <% if comment.user.hidden? %>
+
+ <% end %>
+
<% end %>
- <% if comment.user.official? && comment.user_id == @debate.author_id %>
+ <% if comment.as_administrator? %>
+
+ <% elsif comment.as_moderator? %>
+
+ <% elsif comment.user.official? && comment.user_id == @debate.author_id %>
<% elsif comment.user.official? %>
@@ -81,6 +101,5 @@
-
diff --git a/app/views/comments/_form.html.erb b/app/views/comments/_form.html.erb
index 5e34a9f84..b73023c7a 100644
--- a/app/views/comments/_form.html.erb
+++ b/app/views/comments/_form.html.erb
@@ -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 %>
+
+ <%= f.check_box :as_moderator, label: false %>
+ <%= f.label :as_moderator, t("comments.form.comment_as_moderator"), class: "checkbox" %>
+
+ <% end %>
+ <% if can? :comment_as_administrator, @debate %>
+
+ <%= f.check_box :as_administrator, label: false %>
+ <%= f.label :as_administrator, t("comments.form.comment_as_admin"), class: "checkbox" %>
+
+ <% end %>
<% end %>
diff --git a/config/locales/en.yml b/config/locales/en.yml
index b47d06c44..ce3339b25 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -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:
@@ -94,7 +96,9 @@ en:
recommendation_three: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore"
comments:
form:
- leave_comment: Write a comment
+ 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
diff --git a/config/locales/es.yml b/config/locales/es.yml
index 2d6b7d987..1e2cca785 100644
--- a/config/locales/es.yml
+++ b/config/locales/es.yml
@@ -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:
@@ -94,7 +96,9 @@ es:
recommendation_three: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore"
comments:
form:
- leave_comment: Deja tu comentario
+ 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
diff --git a/db/migrate/20150824111844_add_moderator_id_to_comment.rb b/db/migrate/20150824111844_add_moderator_id_to_comment.rb
new file mode 100644
index 000000000..014c3ecf3
--- /dev/null
+++ b/db/migrate/20150824111844_add_moderator_id_to_comment.rb
@@ -0,0 +1,5 @@
+class AddModeratorIdToComment < ActiveRecord::Migration
+ def change
+ add_column :comments, :moderator_id, :integer, default: nil
+ end
+end
diff --git a/db/migrate/20150824113326_add_administrator_id_to_comment.rb b/db/migrate/20150824113326_add_administrator_id_to_comment.rb
new file mode 100644
index 000000000..7be8274cb
--- /dev/null
+++ b/db/migrate/20150824113326_add_administrator_id_to_comment.rb
@@ -0,0 +1,5 @@
+class AddAdministratorIdToComment < ActiveRecord::Migration
+ def change
+ add_column :comments, :administrator_id, :integer, default: nil
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 040d21d10..12e457a1c 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -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
diff --git a/spec/features/comments_spec.rb b/spec/features/comments_spec.rb
index ce5403a56..4ed16d915 100644
--- a/spec/features/comments_spec.rb
+++ b/spec/features/comments_spec.rb
@@ -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
\ No newline at end of file
diff --git a/spec/models/ability_spec.rb b/spec/models/ability_spec.rb
index 1ff4933b0..ff3e3800c 100644
--- a/spec/models/ability_spec.rb
+++ b/spec/models/ability_spec.rb
@@ -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
diff --git a/spec/models/comment_spec.rb b/spec/models/comment_spec.rb
index 5af7afc1c..98420c000 100644
--- a/spec/models/comment_spec.rb
+++ b/spec/models/comment_spec.rb
@@ -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
<%= comment.body %>
+ <% elsif comment.as_moderator? %> +<%= comment.body %>
+ <% elsif comment.user.official? && comment.user_id == @debate.author_id %><%= comment.body %>
<% elsif comment.user.official? %><%= comment.body %>
@@ -81,6 +101,5 @@