diff --git a/plugins/comment_classification/README.md b/plugins/comment_classification/README.md new file mode 100644 index 0000000..9f8674e --- /dev/null +++ b/plugins/comment_classification/README.md @@ -0,0 +1,13 @@ +README - Comment Classification Plugin +====================================== + +This plugin creates the structure for classifying the comments. The +initial idea of this plugin is to support the management of public +consulting, but it can be used in different contexts. +For now, two kind of classification will be available: + + * Label: when creating a comment, the user identify the kind of it by +choosing the label of the comment. Example: "Suggestion", +"Disagreement"... + * Status: users with permission can include a Status for a comment. +Example: "Merged", "Unmerged" diff --git a/plugins/comment_classification/controllers/admin/comment_classification_plugin_labels_controller.rb b/plugins/comment_classification/controllers/admin/comment_classification_plugin_labels_controller.rb new file mode 100644 index 0000000..e196eef --- /dev/null +++ b/plugins/comment_classification/controllers/admin/comment_classification_plugin_labels_controller.rb @@ -0,0 +1,55 @@ +class CommentClassificationPluginLabelsController < AdminController + append_view_path File.join(File.dirname(__FILE__) + '/../../views') + + def index +# @labels = @environment.labels + @labels = CommentClassificationPlugin::Label.all + end + + def create + @label = CommentClassificationPlugin::Label.new(params[:label]) + @colors = CommentClassificationPlugin::Label::COLORS + if request.post? + begin + @label.owner = environment + @label.save! + session[:notice] = _('Label created') + redirect_to :action => 'index' + rescue + session[:notice] = _('Label could not be created') + end + end + end + + def edit +# @labels = @environment.labels.find(params[:id]) + @label = CommentClassificationPlugin::Label.find(params[:id]) + @colors = CommentClassificationPlugin::Label::COLORS + if request.post? + begin + @label.update_attributes!(params[:label]) + session[:notice] = _('Label updated') + redirect_to :action => :index + rescue + session[:notice] = _('Failed to edit label') + end + end + end + + def remove +# @label = environment.labels.find(params[:label]) + @label = CommentClassificationPlugin::Label.find(params[:id]) + if request.post? + begin + @label.destroy + session[:notice] = _('Label removed') + rescue + session[:notice] = _('Label could not be removed') + end + else + session[:notice] = _('Label could not be removed') + end + redirect_to :action => 'index' + end + +end diff --git a/plugins/comment_classification/controllers/admin/comment_classification_plugin_status_controller.rb b/plugins/comment_classification/controllers/admin/comment_classification_plugin_status_controller.rb new file mode 100644 index 0000000..af0f4a0 --- /dev/null +++ b/plugins/comment_classification/controllers/admin/comment_classification_plugin_status_controller.rb @@ -0,0 +1,53 @@ +class CommentClassificationPluginStatusController < AdminController + append_view_path File.join(File.dirname(__FILE__) + '/../../views') + + def index +# @labels = @environment.labels + @status = CommentClassificationPlugin::Status.all + end + + def create + @status = CommentClassificationPlugin::Status.new(params[:status]) + if request.post? + begin + @status.owner = environment + @status.save! + session[:notice] = _('Status created') + redirect_to :action => 'index' + rescue + session[:notice] = _('Status could not be created') + end + end + end + + def edit +# @labels = @environment.labels.find(params[:id]) + @status = CommentClassificationPlugin::Status.find(params[:id]) + if request.post? + begin + @status.update_attributes!(params[:status]) + session[:notice] = _('Status updated') + redirect_to :action => :index + rescue + session[:notice] = _('Failed to edit status') + end + end + end + + def remove +# @label = environment.labels.find(params[:label]) + @status = CommentClassificationPlugin::Status.find(params[:id]) + if request.post? + begin + @status.destroy + session[:notice] = _('Status removed') + rescue + session[:notice] = _('Status could not be removed') + end + else + session[:notice] = _('Status could not be removed') + end + redirect_to :action => 'index' + end + +end diff --git a/plugins/comment_classification/controllers/comment_classification_plugin_admin_controller.rb b/plugins/comment_classification/controllers/comment_classification_plugin_admin_controller.rb new file mode 100644 index 0000000..82f5b1d --- /dev/null +++ b/plugins/comment_classification/controllers/comment_classification_plugin_admin_controller.rb @@ -0,0 +1,7 @@ +class CommentClassificationPluginAdminController < AdminController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + + def index + end + +end diff --git a/plugins/comment_classification/controllers/comment_classification_plugin_myprofile_controller.rb b/plugins/comment_classification/controllers/comment_classification_plugin_myprofile_controller.rb new file mode 100644 index 0000000..db98137 --- /dev/null +++ b/plugins/comment_classification/controllers/comment_classification_plugin_myprofile_controller.rb @@ -0,0 +1,26 @@ +class CommentClassificationPluginMyprofileController < MyProfileController + append_view_path File.join(File.dirname(__FILE__) + '/../views') + + before_filter :organizations_only + protect 'moderate_comments', :profile + + def index + @comments = Comment.all + end + + def add_status + @comment = Comment.find(params[:id]) + @statuses = CommentClassificationPlugin::Status.enabled + @status = CommentClassificationPlugin::CommentStatusUser.new(:profile => user, :comment => @comment) + if request.post? && params[:status] + @status.update_attributes(params[:status]) + @status.save + end + end + + private + + def organizations_only + render_not_found if !profile.organization? + end +end diff --git a/plugins/comment_classification/db/migrate/20130822043033_create_comments_labels.rb b/plugins/comment_classification/db/migrate/20130822043033_create_comments_labels.rb new file mode 100644 index 0000000..8a9cb7f --- /dev/null +++ b/plugins/comment_classification/db/migrate/20130822043033_create_comments_labels.rb @@ -0,0 +1,16 @@ +class CreateCommentsLabels < ActiveRecord::Migration + def self.up + create_table :comment_classification_plugin_labels do |t| + t.string :name + t.string :color + t.boolean :enabled, :default => true + t.references :owner, :polymorphic => true + + t.timestamps + end + end + + def self.down + drop_table :comment_classification_plugin_labels + end +end diff --git a/plugins/comment_classification/db/migrate/20130822075623_create_comment_label_user.rb b/plugins/comment_classification/db/migrate/20130822075623_create_comment_label_user.rb new file mode 100644 index 0000000..bda6c2f --- /dev/null +++ b/plugins/comment_classification/db/migrate/20130822075623_create_comment_label_user.rb @@ -0,0 +1,16 @@ +class CreateCommentLabelUser < ActiveRecord::Migration + def self.up + create_table :comment_classification_plugin_comment_label_user do |t| + t.references :profile + t.references :comment + t.references :label + + t.timestamps + end + + end + + def self.down + drop_table :comment_classification_plugin_comment_label_user + end +end diff --git a/plugins/comment_classification/db/migrate/20130829130226_create_comment_status.rb b/plugins/comment_classification/db/migrate/20130829130226_create_comment_status.rb new file mode 100644 index 0000000..d18b393 --- /dev/null +++ b/plugins/comment_classification/db/migrate/20130829130226_create_comment_status.rb @@ -0,0 +1,16 @@ +class CreateCommentStatus < ActiveRecord::Migration + def self.up + create_table :comment_classification_plugin_statuses do |t| + t.string :name + t.boolean :enabled, :default => true + t.boolean :enable_reason, :default => true + t.references :owner, :polymorphic => true + t.timestamps + end + + end + + def self.down + drop_table :comment_classification_plugin_statuses + end +end diff --git a/plugins/comment_classification/db/migrate/20130829144037_create_comment_status_user.rb b/plugins/comment_classification/db/migrate/20130829144037_create_comment_status_user.rb new file mode 100644 index 0000000..3efba1c --- /dev/null +++ b/plugins/comment_classification/db/migrate/20130829144037_create_comment_status_user.rb @@ -0,0 +1,16 @@ +class CreateCommentStatusUser < ActiveRecord::Migration + def self.up + create_table :comment_classification_plugin_comment_status_user do |t| + t.references :profile + t.references :comment + t.references :status + t.text :reason + + t.timestamps + end + end + + def self.down + drop_table :comment_classification_plugin_comment_status_user + end +end diff --git a/plugins/comment_classification/features/labels.feature b/plugins/comment_classification/features/labels.feature new file mode 100644 index 0000000..f602b60 --- /dev/null +++ b/plugins/comment_classification/features/labels.feature @@ -0,0 +1,64 @@ +Feature: + As a user + I want to add label for comments + +Background: + Given the following users + | login | name | + | joaosilva | Joao Silva | + | mariasilva | Maria Silva | + And the following communities + | identifier | name | + | sample-community | Sample Community | + And the following articles + | owner | name | body | + | sample-community | Article to comment | First post | + And CommentClassificationPlugin is enabled + And "Maria Silva" is a member of "Sample Community" + And "Joao Silva" is admin of "Sample Community" + And I am logged in as "joaosilva" + + @selenium + Scenario: dont display labels if admin did not configure status + Given I am on article "Article to comment" + And I follow "Post a comment" + Then I should not see "Label" within "#page-comment-form" + + Scenario: admin configure labels + Given I am logged in as "admin_user" + And I am on the environment control panel + And I follow "Plugins" + And I follow "Configuration" + And I follow "Manage Labels" + Then I should see "no label registered yet" within "#comment-classification-labels" + When I follow "Add a new label" + And I fill in "Name" with "Question" + And I check "Enable this label" + And I press "Save" + Then I should see "Question" within "#comment-classification-labels" + + @selenium + Scenario: save label for comment + Given the following labels + | owner | name | enabled | + | environment | Addition | true | + And I go to article "Article to comment" + And I follow "Post a comment" + And I fill in "Enter your comment" with "Hey ho, let's go!" + Then I select "Addition" from "comment_label_id" + And I press "Post comment" + Then I should see "Addition" within ".comment-details" + + @selenium + Scenario: users without permission should not edit the labels + Given the following labels + | owner | name | enabled | + | environment | Addition | true | + And I go to article "Article to comment" + And I follow "Post a comment" + Then I should see "Label" within "#page-comment-form" + And I should see "Addition" within "#comment_label_id" + When I am not logged in + And I am on article "Article to comment" + And I follow "Post a comment" + Then I should not see "Label" within "#page-comment-form" diff --git a/plugins/comment_classification/features/status.feature b/plugins/comment_classification/features/status.feature new file mode 100644 index 0000000..b424928 --- /dev/null +++ b/plugins/comment_classification/features/status.feature @@ -0,0 +1,67 @@ +Feature: + As a user + I want to add status for comments + +Background: + Given the following users + | login | name | + | joaosilva | Joao Silva | + | mariasilva | Maria Silva | + And the following communities + | identifier | name | + | sample-community | Sample Community | + And the following articles + | owner | name | body | + | sample-community | Article to comment | First post | + And the following comments + | article | author | body | + | Article to comment | mariasilva | great post! | + And CommentClassificationPlugin is enabled + And "Maria Silva" is a member of "Sample Community" + And "Joao Silva" is admin of "Sample Community" + And I am logged in as "joaosilva" + + Scenario: dont display to add status if not an organization + Given the following articles + | owner | name | body | + | joaosilva | Article on a person profile | First post | + And the following comments + | article | author | body | + | Article on a person profile | mariasilva | great post! | + Given I am on article "Article on a person profile" + Then I should see "great post!" within ".comment-details" + And I should not see "Status" within ".comment-details" + + Scenario: dont display to add status if admin did not configure status + Given I am on article "Article to comment" + Then I should see "great post!" within ".comment-details" + And I should not see "Status" within ".comment-details" + + Scenario: admin configure status + Given I am logged in as "admin_user" + And I am on the environment control panel + And I follow "Plugins" + And I follow "Configuration" + And I follow "Manage Status" + Then I should see "no status registered yet" within "#comment-classification-status" + When I follow "Add a new status" + And I fill in "Name" with "Merged" + And I check "Enable this status" + And I press "Save" + Then I should see "Merged" within "#comment-classification-status" + + Scenario: save status for comment + Given the following status + | owner | name | enabled | + | environment | Merged | true | + And I go to article "Article to comment" + And I follow "Status" + Then I select "Merged" from "status_status_id" + And I press "Save" + Then I should see "added the status Merged" within "#comment-classification-status-list" + + Scenario: dont display to add status if user not allowed + Given I am logged in as "mariasilva" + When I go to article "Article to comment" + Then I should see "great post!" within ".comment-details" + And I should not see "Status" within ".comment-details" diff --git a/plugins/comment_classification/features/step_definitions/plugin_steps.rb b/plugins/comment_classification/features/step_definitions/plugin_steps.rb new file mode 100644 index 0000000..6392885 --- /dev/null +++ b/plugins/comment_classification/features/step_definitions/plugin_steps.rb @@ -0,0 +1,24 @@ +Given /^CommentClassificationPlugin is enabled$/ do + Given %{I am logged in as admin} + And %{I am on the environment control panel} + And %{I follow "Plugins"} + And %{I check "Comment Classification"} + And %{I press "Save changes"} + Environment.default.enabled_plugins.should include("CommentClassificationPlugin") +end + +Given /^the following labels$/ do |table| + table.hashes.map{|item| item.dup}.each do |item| + owner_type = item.delete('owner') + owner = owner_type == 'environment' ? Environment.default : Profile[owner_type] + CommentClassificationPlugin::Label.create!(item) + end +end + +Given /^the following status$/ do |table| + table.hashes.map{|item| item.dup}.each do |item| + owner_type = item.delete('owner') + owner = owner_type == 'environment' ? Environment.default : Profile[owner_type] + CommentClassificationPlugin::Status.create!(item) + end +end diff --git a/plugins/comment_classification/lib/comment_classification_plugin.rb b/plugins/comment_classification/lib/comment_classification_plugin.rb new file mode 100644 index 0000000..7546f3d --- /dev/null +++ b/plugins/comment_classification/lib/comment_classification_plugin.rb @@ -0,0 +1,57 @@ +require 'ext/environment' +require 'ext/comment' + +class CommentClassificationPlugin < Noosfero::Plugin + + def self.plugin_name + "Comment Classification" + end + + def self.plugin_description + _("A plugin that allow classification of comments.") + end + +#TODO Each organization can add its own status and labels +# def control_panel_buttons +# if context.profile.organization? +# { :title => _('Manage comment classification'), :icon => 'comment_classification', :url => {:controller => 'comment_classification_plugin_myprofile'} } +# end +# end + + def comment_form_extra_contents(args) + comment = args[:comment] + lambda { + render :file => 'comment/comments_labels_select.rhtml', :locals => {:comment => comment } + } + end + + def comment_extra_contents(args) + comment = args[:comment] + lambda { + render :file => 'comment/comment_extra.rhtml', :locals => {:comment => comment} + } + end + + def process_extra_comment_params(args) + comment = Comment.find args[0] + label_id = args[1][:comment_label_id] + if label_id.blank? + if !CommentClassificationPlugin::CommentLabelUser.find_by_comment_id(comment.id).nil? + CommentClassificationPlugin::CommentLabelUser.find_by_comment_id(comment.id).destroy + end + else + label = CommentClassificationPlugin::Label.find label_id + relation = CommentClassificationPlugin::CommentLabelUser.new(:profile => comment.author, :comment => comment, :label => label ) + relation.save + end + end + + def js_files + 'comment_classification.js' + end + + def stylesheet? + true + end + +end diff --git a/plugins/comment_classification/lib/comment_classification_plugin/comment_label_user.rb b/plugins/comment_classification/lib/comment_classification_plugin/comment_label_user.rb new file mode 100644 index 0000000..c25f1ba --- /dev/null +++ b/plugins/comment_classification/lib/comment_classification_plugin/comment_label_user.rb @@ -0,0 +1,11 @@ +class CommentClassificationPlugin::CommentLabelUser < Noosfero::Plugin::ActiveRecord + set_table_name :comment_classification_plugin_comment_label_user + + belongs_to :profile + belongs_to :comment + belongs_to :label, :class_name => 'CommentClassificationPlugin::Label' + + validates_presence_of :profile + validates_presence_of :comment + validates_presence_of :label +end diff --git a/plugins/comment_classification/lib/comment_classification_plugin/comment_status_user.rb b/plugins/comment_classification/lib/comment_classification_plugin/comment_status_user.rb new file mode 100644 index 0000000..af2b9f1 --- /dev/null +++ b/plugins/comment_classification/lib/comment_classification_plugin/comment_status_user.rb @@ -0,0 +1,11 @@ +class CommentClassificationPlugin::CommentStatusUser < Noosfero::Plugin::ActiveRecord + set_table_name :comment_classification_plugin_comment_status_user + + belongs_to :profile + belongs_to :comment + belongs_to :status, :class_name => 'CommentClassificationPlugin::Status' + + validates_presence_of :profile + validates_presence_of :comment + validates_presence_of :status +end diff --git a/plugins/comment_classification/lib/comment_classification_plugin/label.rb b/plugins/comment_classification/lib/comment_classification_plugin/label.rb new file mode 100644 index 0000000..27f7d32 --- /dev/null +++ b/plugins/comment_classification/lib/comment_classification_plugin/label.rb @@ -0,0 +1,10 @@ +class CommentClassificationPlugin::Label < Noosfero::Plugin::ActiveRecord + + belongs_to :owner, :polymorphic => true + + validates_presence_of :name + + named_scope :enabled, :conditions => { :enabled => true } + + COLORS = ['red', 'green', 'yellow', 'gray', 'blue'] +end diff --git a/plugins/comment_classification/lib/comment_classification_plugin/status.rb b/plugins/comment_classification/lib/comment_classification_plugin/status.rb new file mode 100644 index 0000000..f244152 --- /dev/null +++ b/plugins/comment_classification/lib/comment_classification_plugin/status.rb @@ -0,0 +1,8 @@ +class CommentClassificationPlugin::Status < Noosfero::Plugin::ActiveRecord + + belongs_to :owner, :polymorphic => true + + validates_presence_of :name + + named_scope :enabled, :conditions => { :enabled => true } +end diff --git a/plugins/comment_classification/lib/ext/comment.rb b/plugins/comment_classification/lib/ext/comment.rb new file mode 100644 index 0000000..cc07194 --- /dev/null +++ b/plugins/comment_classification/lib/ext/comment.rb @@ -0,0 +1,13 @@ +require_dependency 'comment' +require 'comment_classification_plugin.rb' +require 'comment_classification_plugin/label.rb' + +class Comment + + has_one :comment_classification_plugin_comment_label_user, :class_name => 'CommentClassificationPlugin::CommentLabelUser' + has_one :label, :through => :comment_classification_plugin_comment_label_user, :foreign_key => 'label_id' + + has_many :comment_classification_plugin_comment_status_users, :class_name => 'CommentClassificationPlugin::CommentStatusUser' + has_many :statuses, :through => :comment_classification_plugin_comment_status_users, :foreign_key => 'status_id' + +end diff --git a/plugins/comment_classification/lib/ext/environment.rb b/plugins/comment_classification/lib/ext/environment.rb new file mode 100644 index 0000000..a5f21cb --- /dev/null +++ b/plugins/comment_classification/lib/ext/environment.rb @@ -0,0 +1,8 @@ +require_dependency 'environment' + +class Environment + + has_many :labels, :as => :owner, :class_name => 'CommentClassificationPlugin::Label' + +end + diff --git a/plugins/comment_classification/public/images/comment-classification.png b/plugins/comment_classification/public/images/comment-classification.png new file mode 100644 index 0000000..954649a Binary files /dev/null and b/plugins/comment_classification/public/images/comment-classification.png differ diff --git a/plugins/comment_classification/public/style.css b/plugins/comment_classification/public/style.css new file mode 100644 index 0000000..1e426c3 --- /dev/null +++ b/plugins/comment_classification/public/style.css @@ -0,0 +1,12 @@ +.controller-profile_editor .control-panel a.control-panel-comment_classification { + background-image: url(images/comment-classification.png); +} + +#content .comment-classification-options .label-name { + font-style: italic; +} + +#content .comment-classification-options a.button { + background-color: transparent; + border: none; +} diff --git a/plugins/comment_classification/views/comment/comment_extra.rhtml b/plugins/comment_classification/views/comment/comment_extra.rhtml new file mode 100644 index 0000000..7b8dee9 --- /dev/null +++ b/plugins/comment_classification/views/comment/comment_extra.rhtml @@ -0,0 +1,17 @@ +
<%= _('Label') %> | +<%= _('Color') %> | +<%= _('Enabled') %> | +<%= _('Actions') %> | +
---|---|---|---|
<%= label.name %> | +<%= label.color %> | +<%= label.enabled %> | ++ <%= button_without_text :edit, _('Edit'), {:action => 'edit', :id => label} %> + <%= button_without_text :delete, _('Remove'), {:action => 'destroy', :id => label}, :confirm => _('Are you sure you want to remove this label?') %> + | +
<%= @comment.body %>
+ +<%= _("Reason: %s") % relation.reason %>
+ <% end %> +<%= _('Status') %> | +<%= _('Enabled') %> | +<%= _('Reason enabled?') %> | +<%= _('Actions') %> | +
---|---|---|---|
<%= st.name %> | +<%= st.enabled %> | +<%= st.enable_reason %> | ++ <%= button_without_text :edit, _('Edit'), {:action => 'edit', :id => st} %> + <%= button_without_text :delete, _('Remove'), {:action => 'destroy', :id => st}, :confirm => _('Are you sure you want to remove this status?') %> + | +
+ <%= comment.label.name %> +
+ <% end %> + + <% statuses = CommentClassificationPlugin::Status.enabled %> + <% if profile.organization? && user && user.has_permission?(:moderate_comments, profile) && !statuses.empty? %> +