Commit 29249040654c0a8948afeb1748ddd3f3e6819042

Authored by Daniela Feitosa
1 parent 873f1d46

Add Organization Ratings Plugin

A plugin that allow users to rate a organization and comment about it.

Signed-off-by: Alexandre Torres <alexandrekry@gmail.com>
Signed-off-by: Andre Bernardes <andrebsguedes@gmail.com>
Signed-off-by: Brenddon Gontijo <brenddongontijo@msn.com>
Signed-off-by: DylanGuedes <djmgguedes@gmail.com>
Signed-off-by: Fabio Teixeira <fabio1079@gmail.com>
Signed-off-by: Filipe Ribeiro <firibeiro77@live.com>
Signed-off-by: Gabriela Navarro <navarro1703@gmail.com
Signed-off-by: Hebert Douglas <hebertdougl@gmail.com>
Signed-off-by: Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
Signed-off-by: Omar Junior <omarroinuj@gmail.com>
Signed-off-by: Pedro de Lyra <pedrodelyra@gmail.com>
Signed-off-by: Simião Carvalho <simiaosimis@gmail.com>
Signed-off-by: Tallys Martins <tallysmartins@gmail.com>
Showing 43 changed files with 1598 additions and 2 deletions   Show diff stats
lib/noosfero/plugin.rb
... ... @@ -241,6 +241,16 @@ class Noosfero::Plugin
241 241 nil
242 242 end
243 243  
  244 + # -> Customize the way comments are counted for Profiles and Environment
  245 + # considering more than just articles comments
  246 + # Used on statistic block
  247 + # Ex: a plugin may want that Communities receive comments themselves
  248 + # as evaluations
  249 + # returns = the number of comments to be sum on the statistics
  250 + def more_comments_count owner
  251 + nil
  252 + end
  253 +
244 254 # -> Adds tabs to the profile
245 255 # returns = { :title => title, :id => id, :content => content, :start => start }
246 256 # title = name that will be displayed.
... ...
plugins/organization_ratings/controllers/organization_ratings_plugin_admin_controller.rb 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +class OrganizationRatingsPluginAdminController < PluginAdminController
  2 +
  3 + include RatingsHelper
  4 + helper :ratings
  5 + append_view_path File.join(File.dirname(__FILE__) + '/../views')
  6 +
  7 + def index
  8 + end
  9 +
  10 + def update
  11 + if env_organization_ratings_config.update_attributes(params[:organization_ratings_config])
  12 + session[:notice] = _('Configuration updated successfully.')
  13 + else
  14 + session[:notice] = _('Configuration could not be saved.')
  15 + end
  16 + render :action => 'index'
  17 + end
  18 +
  19 +end
0 20 \ No newline at end of file
... ...
plugins/organization_ratings/controllers/organization_ratings_plugin_profile_controller.rb 0 → 100644
... ... @@ -0,0 +1,76 @@
  1 +class OrganizationRatingsPluginProfileController < ProfileController
  2 + include RatingsHelper
  3 + helper :ratings
  4 +
  5 + def new_rating
  6 + @rating_available = user_can_rate_now?
  7 + @users_ratings = get_ratings(profile.id).paginate(
  8 + :per_page => env_organization_ratings_config.per_page,
  9 + :page => params[:npage]
  10 + )
  11 + if request.post?
  12 + if @rating_available
  13 + create_new_rate
  14 + else
  15 + session[:notice] = _("You can not vote on this %s") % profile.class.name
  16 + end
  17 + end
  18 + end
  19 +
  20 + private
  21 +
  22 + def user_can_rate_now?
  23 + return false unless user
  24 + ratings = OrganizationRating.where(
  25 + :organization_id => profile.id,
  26 + :person_id => user.id
  27 + )
  28 +
  29 + return false if (!ratings.empty? && env_organization_ratings_config.vote_once)
  30 +
  31 + if ratings.empty?
  32 + true
  33 + else
  34 + elapsed_time_since_last_rating = Time.zone.now - ratings.last.created_at
  35 + elapsed_time_since_last_rating > env_organization_ratings_config.cooldown.hours
  36 + end
  37 + end
  38 +
  39 + def create_new_rate
  40 + rating = OrganizationRating.new(params[:organization_rating])
  41 + rating.person = current_user.person
  42 + rating.organization = profile
  43 + rating.value = params[:organization_rating_value] if params[:organization_rating_value]
  44 +
  45 + if rating.save
  46 + create_rating_comment(rating)
  47 + session[:notice] = _("%s successfully rated!") % profile.name
  48 + else
  49 + session[:notice] = _("Sorry, there were problems rating this profile.")
  50 + end
  51 +
  52 + redirect_to :controller => 'profile', :action => 'index'
  53 + end
  54 +
  55 + def create_rating_comment(rating)
  56 + if params[:comments]
  57 + comment_task = CreateOrganizationRatingComment.create!(
  58 + params[:comments].merge(
  59 + :requestor => rating.person,
  60 + :organization_rating_id => rating.id,
  61 + :target => rating.organization
  62 + )
  63 + )
  64 + comment_task.finish if can_perform?(params)
  65 + end
  66 + end
  67 +
  68 + def can_perform? (params)
  69 + (params[:comments][:body].blank? ||
  70 + !env_organization_ratings_config.are_moderated)
  71 + end
  72 +
  73 + def permission
  74 + :manage_memberships
  75 + end
  76 +end
... ...
plugins/organization_ratings/db/migrate/20150830225546_create_organization_ratings.rb 0 → 100644
... ... @@ -0,0 +1,12 @@
  1 +class CreateOrganizationRatings < ActiveRecord::Migration
  2 + def change
  3 + create_table :organization_ratings do |t|
  4 + t.belongs_to :organization
  5 + t.belongs_to :person
  6 + t.belongs_to :comment
  7 + t.integer :value
  8 +
  9 + t.timestamps
  10 + end
  11 + end
  12 +end
... ...
plugins/organization_ratings/db/migrate/20150830225733_create_organization_ratings_config.rb 0 → 100644
... ... @@ -0,0 +1,14 @@
  1 +class CreateOrganizationRatingsConfig < ActiveRecord::Migration
  2 +
  3 + def change
  4 + create_table :organization_ratings_configs do |t|
  5 + t.belongs_to :environment
  6 + t.integer :cooldown, :integer, :default => 24
  7 + t.integer :default_rating, :integer, :default => 1
  8 + t.string :order, :string, :default => "recent"
  9 + t.integer :per_page, :integer, :default => 10
  10 + t.boolean :vote_once, :boolean, :default => false
  11 + t.boolean :are_moderated, :boolean, :default => true
  12 + end
  13 + end
  14 +end
... ...
plugins/organization_ratings/db/migrate/20150830230047_add_comments_count_to_profile.rb 0 → 100644
... ... @@ -0,0 +1,11 @@
  1 +class AddCommentsCountToProfile < ActiveRecord::Migration
  2 + def self.up
  3 + change_table :profiles do |t|
  4 + t.integer :comments_count
  5 + end
  6 + end
  7 +
  8 + def self.down
  9 + remove_column :profiles, :comments_count
  10 + end
  11 +end
0 12 \ No newline at end of file
... ...
plugins/organization_ratings/features/rate_community.feature 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +Feature: rate_community
  2 + As a user
  3 + I want to be able rate a community
  4 + So that users can see my feedback about that community
  5 +
  6 + Background:
  7 + Given plugin "OrganizationRatings" is enabled on environment
  8 + Given the following user
  9 + | login | name |
  10 + | joaosilva | Joao Silva |
  11 + And the following community
  12 + | identifier | name |
  13 + | mycommunity | My Community |
  14 + And the following blocks
  15 + | owner | type |
  16 + | mycommunity | AverageRatingBlock |
  17 + | mycommunity | OrganizationRatingsBlock |
  18 + And the environment domain is "localhost"
  19 + And I am logged in as "joaosilva"
  20 +
  21 + @selenium
  22 + Scenario: display rate button inside average block
  23 + Given I am on mycommunity's homepage
  24 + Then I should see "Rate this Community" within ".average-rating-block"
  25 + And I should see "Be the first to rate" within ".average-rating-block"
  26 +
  27 + @selenium
  28 + Scenario: display rate button inside communities ratings block
  29 + Given I am on mycommunity's homepage
  30 + Then I should see "Rate Community" within ".make-report-block"
... ...
plugins/organization_ratings/lib/average_rating_block.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +class AverageRatingBlock < Block
  2 + include RatingsHelper
  3 +
  4 + def self.description
  5 + _('Organization Average Rating')
  6 + end
  7 +
  8 + def help
  9 + _('This block displays the organization average rating.')
  10 + end
  11 +
  12 + def content(args = {})
  13 + profile_identifier = self.owner.identifier
  14 + average_rating = OrganizationRating.average_rating self.owner.id
  15 +
  16 + proc do
  17 + render(
  18 + :file => 'blocks/display_organization_average_rating',
  19 + :locals => {
  20 + :profile_identifier => profile_identifier,
  21 + :average_rating => average_rating
  22 + }
  23 + )
  24 + end
  25 + end
  26 +
  27 + def cacheable?
  28 + false
  29 + end
  30 +end
... ...
plugins/organization_ratings/lib/create_organization_rating_comment.rb 0 → 100644
... ... @@ -0,0 +1,131 @@
  1 +class CreateOrganizationRatingComment < Task
  2 + include Rails.application.routes.url_helpers
  3 +
  4 + validates_presence_of :requestor_id, :organization_rating_id, :target_id
  5 +
  6 + settings_items :organization_rating_id, :type => Integer, :default => nil
  7 + settings_items :organization_rating_comment_id, :type => Integer, :default => nil
  8 +
  9 + attr_accessible :organization_rating_id, :body, :requestor
  10 + attr_accessible :reject_explanation, :target
  11 +
  12 + before_save :update_comment_body
  13 +
  14 + DATA_FIELDS = ['body']
  15 + DATA_FIELDS.each do |field|
  16 + settings_items field.to_sym
  17 + end
  18 +
  19 + def update_comment_body
  20 + if self.organization_rating_comment_id.nil?
  21 + create_comment
  22 + else
  23 + comment = Comment.find_by_id(self.organization_rating_comment_id)
  24 + comment.body = get_comment_message
  25 + comment.save
  26 + end
  27 + end
  28 +
  29 + def create_comment
  30 + if (self.body && !self.body.blank?)
  31 + comment_body = _("Comment waiting for approval")
  32 + comment = Comment.create!(:source => self.target, :body => comment_body, :author => self.requestor)
  33 +
  34 +
  35 + self.organization_rating_comment_id = comment.id
  36 + link_comment_with_its_rating(comment)
  37 + end
  38 + end
  39 +
  40 + def link_comment_with_its_rating(user_comment)
  41 + rating = OrganizationRating.find(self.organization_rating_id)
  42 + rating.comment = user_comment
  43 + rating.save
  44 + end
  45 +
  46 + def get_comment_message
  47 + if self.status == Status::CANCELLED
  48 + _("Comment rejected")
  49 + elsif self.status == Status::FINISHED
  50 + self.body
  51 + else
  52 + _("No comment")
  53 + end
  54 + end
  55 +
  56 + def accept_details
  57 + true
  58 + end
  59 +
  60 + def title
  61 + _("New Comment")
  62 + end
  63 +
  64 + def information
  65 + message = _("<a href=%{requestor_url}>%{requestor}</a> wants to create a comment in this %{target_class}") %
  66 + {:requestor_url => url_for(self.requestor.url), :requestor => self.requestor.name, :target_class => self.target.class.name.downcase}
  67 +
  68 + {:message => message}
  69 + end
  70 +
  71 + def reject_details
  72 + true
  73 + end
  74 +
  75 + def icon
  76 + {:type => :profile_image, :profile => requestor, :url => requestor.url}
  77 + end
  78 +
  79 + # tells if this request was rejected
  80 + def rejected?
  81 + self.status == Task::Status::CANCELLED
  82 + end
  83 +
  84 + # tells if this request was appoved
  85 + def approved?
  86 + self.status == Task::Status::FINISHED
  87 + end
  88 +
  89 + def target_notification_description
  90 + _("%{requestor} wants to create a comment in this \"%{target}\"") %
  91 + {:requestor => self.requestor.name, :target => self.target.class.name.downcase }
  92 + end
  93 +
  94 + def target_notification_message
  95 + _("User \"%{user}\" just requested to create a comment in the %{target_class}
  96 + \"%{target_name}\".
  97 + You have to approve or reject it through the \"Pending Validations\"
  98 + section in your control panel.\n") %
  99 + { :user => self.requestor.name, :target_class => self.target.class.name.downcase, :target_name => self.target.name }
  100 + end
  101 +
  102 + def task_created_message
  103 + _("Your request for commenting at %{target} was
  104 + just sent. Environment administrator will receive it and will approve or
  105 + reject your request according to his methods and criteria.
  106 + You will be notified as soon as environment administrator has a position
  107 + about your request.") %
  108 + { :target => self.target.name }
  109 + end
  110 +
  111 + def task_cancelled_message
  112 + _("Your request for commenting at %{target} was
  113 + not approved by the environment administrator. The following explanation
  114 + was given: \n\n%{explanation}") %
  115 + { :target => self.target.name,
  116 + :explanation => self.reject_explanation }
  117 + end
  118 +
  119 + def task_finished_message
  120 + _('Your request for commenting was approved.
  121 + You can access %{url} to see your comment.') %
  122 + { :url => ratings_url }
  123 + end
  124 +
  125 + private
  126 +
  127 + def ratings_url
  128 + url = url_for(self.target.public_profile_url) + "/plugin/organization_ratings/new_rating"
  129 + end
  130 +
  131 +end
... ...
plugins/organization_ratings/lib/ext/comments.rb 0 → 100644
... ... @@ -0,0 +1,6 @@
  1 +require_dependency "comment"
  2 +
  3 +Comment.class_eval do
  4 +
  5 + has_one :organization_rating
  6 +end
... ...
plugins/organization_ratings/lib/ext/environment.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require_dependency "environment"
  2 +
  3 +class Environment
  4 + has_one :organization_ratings_config
  5 +end
... ...
plugins/organization_ratings/lib/ext/organization.rb 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +require_dependency 'organization'
  2 +
  3 +Organization.class_eval do
  4 + has_many :organization_ratings
  5 +
  6 + has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
  7 +end
... ...
plugins/organization_ratings/lib/ext/person.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +require_dependency 'person'
  2 +
  3 +Person.class_eval do
  4 + has_many :organization_ratings
  5 +end
... ...
plugins/organization_ratings/lib/organization_rating.rb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +class OrganizationRating < ActiveRecord::Base
  2 + belongs_to :person
  3 + belongs_to :organization
  4 + belongs_to :comment
  5 +
  6 + attr_accessible :value, :person, :organization, :comment
  7 +
  8 + validates :value,
  9 + :presence => true, :inclusion => {
  10 + in: 1..5, message: _("must be between 1 and 5")
  11 + }
  12 +
  13 + validates :organization_id, :person_id,
  14 + :presence => true
  15 +
  16 +
  17 + def self.average_rating organization_id
  18 + average = OrganizationRating.where(organization_id: organization_id).average(:value)
  19 +
  20 + if average
  21 + (average - average.truncate) >= 0.5 ? average.ceil : average.floor
  22 + end
  23 + end
  24 +
  25 +end
... ...
plugins/organization_ratings/lib/organization_ratings_block.rb 0 → 100644
... ... @@ -0,0 +1,30 @@
  1 +class OrganizationRatingsBlock < Block
  2 + include RatingsHelper
  3 +
  4 + def self.description
  5 + _('Organization Ratings')
  6 + end
  7 +
  8 + def help
  9 + _('This block displays the community ratings.')
  10 + end
  11 +
  12 + def content(args = {})
  13 + block = self
  14 +
  15 + proc do
  16 + render(
  17 + :file => 'blocks/organization_ratings_block',
  18 + :locals => {:block => block}
  19 + )
  20 + end
  21 + end
  22 +
  23 + def limit_number_of_ratings
  24 + env_organization_ratings_config.per_page
  25 + end
  26 +
  27 + def cacheable?
  28 + false
  29 + end
  30 +end
... ...
plugins/organization_ratings/lib/organization_ratings_config.rb 0 → 100644
... ... @@ -0,0 +1,53 @@
  1 +class OrganizationRatingsConfig < ActiveRecord::Base
  2 +
  3 + belongs_to :environment
  4 +
  5 + attr_accessible :cooldown, :default_rating, :order, :per_page
  6 + attr_accessible :vote_once, :are_moderated, :environment_id
  7 +
  8 + ORDER_OPTIONS = {recent: _('More Recent'), best: _('Best Ratings')}
  9 +
  10 + MINIMUM_RATING = 1
  11 + MAX_COOLDOWN = 1000
  12 +
  13 + validates :default_rating,
  14 + :presence => true, :numericality => {
  15 + greater_than_or_equal_to: MINIMUM_RATING,
  16 + less_than_or_equal_to: 5
  17 + }
  18 +
  19 + validates :cooldown,
  20 + :presence => true, :numericality => {
  21 + greater_than_or_equal_to: 0,
  22 + less_than_or_equal_to: MAX_COOLDOWN
  23 + }
  24 +
  25 + validates :per_page,
  26 + :presence => true, :numericality => {
  27 + :greater_than_or_equal_to => 5,
  28 + :less_than_or_equal_to => 20
  29 + }
  30 +
  31 +
  32 + def order_options
  33 + ORDER_OPTIONS
  34 + end
  35 +
  36 + def minimum_ratings
  37 + MINIMUM_RATING
  38 + end
  39 +
  40 + def max_cooldown
  41 + MAX_COOLDOWN
  42 + end
  43 +
  44 + class << self
  45 + def instance
  46 + environment = Environment.default
  47 + environment.organization_ratings_config || create(environment_id: environment.id)
  48 + end
  49 +
  50 + private :new
  51 + end
  52 +
  53 +end
... ...
plugins/organization_ratings/lib/organization_ratings_plugin.rb 0 → 100644
... ... @@ -0,0 +1,73 @@
  1 +class OrganizationRatingsPlugin < Noosfero::Plugin
  2 + include Noosfero::Plugin::HotSpot
  3 +
  4 + def self.plugin_name
  5 + "Organization Ratings"
  6 + end
  7 +
  8 + def self.plugin_description
  9 + _("A plugin that allows you to rate a organization and comment about it.")
  10 + end
  11 +
  12 + module Hotspots
  13 + def organization_ratings_plugin_comments_extra_fields
  14 + nil
  15 + end
  16 +
  17 + def organization_ratings_title
  18 + nil
  19 + end
  20 +
  21 + def organization_ratings_plugin_star_message
  22 + nil
  23 + end
  24 +
  25 + def organization_ratings_plugin_extra_fields_show_data user_rating
  26 + nil
  27 + end
  28 + end
  29 +
  30 + # Plugin Hotspot to display the average rating
  31 + def display_organization_average_rating organization
  32 + unless organization.nil?
  33 + average_rating = OrganizationRating.average_rating organization.id
  34 +
  35 + Proc::new {
  36 + render :file => 'blocks/display_organization_average_rating',
  37 + :locals => {
  38 + :profile_identifier => organization.identifier,
  39 + :average_rating => average_rating
  40 + }
  41 + }
  42 + end
  43 + end
  44 +
  45 + def more_comments_count owner
  46 + if owner.kind_of?(Environment) then
  47 + owner.profiles.sum(:comments_count)
  48 + elsif owner.kind_of?(Profile) then
  49 + owner.comments_count
  50 + else
  51 + 0
  52 + end
  53 + end
  54 +
  55 + def self.extra_blocks
  56 + {
  57 + OrganizationRatingsBlock => {:type => [Enterprise, Community], :position => ['1']},
  58 + AverageRatingBlock => {:type => [Enterprise, Community]}
  59 + }
  60 + end
  61 +
  62 + def stylesheet?
  63 + true
  64 + end
  65 +
  66 + def js_files
  67 + %w(
  68 + public/rate.js
  69 + public/comunities_rating_management.js
  70 + )
  71 + end
  72 +
  73 +end
... ...
plugins/organization_ratings/lib/ratings_helper.rb 0 → 100644
... ... @@ -0,0 +1,15 @@
  1 +module RatingsHelper
  2 +
  3 + def env_organization_ratings_config
  4 + OrganizationRatingsConfig.instance
  5 + end
  6 +
  7 + def get_ratings (profile_id)
  8 + order_options = env_organization_ratings_config.order_options
  9 + if env_organization_ratings_config.order.downcase == order_options[:recent]
  10 + ratings = OrganizationRating.where(organization_id: profile_id).order("value DESC")
  11 + else
  12 + ratings = OrganizationRating.where(organization_id: profile_id).order("created_at DESC")
  13 + end
  14 + end
  15 +end
0 16 \ No newline at end of file
... ...
plugins/organization_ratings/public/images/small-star-negative.png 0 → 100644

529 Bytes

plugins/organization_ratings/public/images/small-star-positive.png 0 → 100644

509 Bytes

plugins/organization_ratings/public/images/star-negative-medium.png 0 → 100644

642 Bytes

plugins/organization_ratings/public/images/star-negative.png 0 → 100644

642 Bytes

plugins/organization_ratings/public/images/star-positive-medium.png 0 → 100644

637 Bytes

plugins/organization_ratings/public/images/star-positive.png 0 → 100644

637 Bytes

plugins/organization_ratings/public/images/user-not-logged.png 0 → 100644

2.48 KB

plugins/organization_ratings/public/organization_rating_management.js 0 → 100644
... ... @@ -0,0 +1,35 @@
  1 +(function($) {
  2 + "use strict";
  3 +
  4 + var VoteOnce = {
  5 + init: function() {
  6 + this.cacheDom();
  7 + this.setEvents();
  8 + },
  9 +
  10 +
  11 + cacheDom: function() {
  12 + this.$vote_once_checkbox = $("#environment_organization_ratings_vote_once");
  13 + this.$hours_timer_input = $("#environment_organization_ratings_cooldown");
  14 + },
  15 +
  16 +
  17 + setEvents: function() {
  18 + this.$vote_once_checkbox.on("click", this.verifyHoursTimerDisable.bind(this));
  19 + },
  20 +
  21 +
  22 + verifyHoursTimerDisable: function() {
  23 + if (this.$vote_once_checkbox.is(":checked")) {
  24 + this.$hours_timer_input.attr("disabled", "disabled");
  25 + } else {
  26 + this.$hours_timer_input.removeAttr("disabled");
  27 + }
  28 + }
  29 + }
  30 +
  31 +
  32 + $(document).ready(function() {
  33 + VoteOnce.init();
  34 + });
  35 +}) (jQuery);
... ...
plugins/organization_ratings/public/rate.js 0 → 100644
... ... @@ -0,0 +1,122 @@
  1 +;(function($, undefined) {
  2 + "use strict";
  3 +
  4 + /*
  5 + * All global data that are used in the stars feature.
  6 + */
  7 + var DATA = {
  8 + selected_rate: 0, // The actual selected star when the user click on a star
  9 + maximum_stars: 5, // (const) The maximum number of allowed stars
  10 + minimum_stars: 1, // (const) The minimum number of allowed stars
  11 + DATA_RATE_ATTRIBUTE: "data-star-rate", // (const) The data attribute with the star rate
  12 + NOT_SELECTED_VALUE: 0 // (const) The value when there is no selected rate
  13 + }
  14 +
  15 +
  16 + /*
  17 + * Prepare the global data that are variable.
  18 + * If the user already rated the organization, set the selected_rate as the rated value
  19 + */
  20 + function set_global_data() {
  21 + var selected_rate = parseInt($("#selected-star-rate").val());
  22 + var minimum_stars = parseInt($("#minimum_stars").val());
  23 + DATA.selected_rate = selected_rate;
  24 + DATA.minimum_stars = minimum_stars;
  25 + }
  26 +
  27 +
  28 + /*
  29 + * Given a start rate, an end rate and the elements, it makes a regex that filter
  30 + * the elements by the given range and returns it.
  31 + */
  32 + function star_filter(start, end, elements) {
  33 + var test_regex = undefined;
  34 +
  35 + // Verify if it is a valid range and makes its range regex: /[start-end]/
  36 + if (end >= start) {
  37 + test_regex = new RegExp("["+(start)+"-"+(end)+"]");
  38 + } else {
  39 + // If the range is invalid, make a regex that will return no element
  40 + test_regex = new RegExp("[]");
  41 + }
  42 +
  43 + // Filter the elements that are in the given range
  44 + var result = elements.filter(function(i, element) {
  45 + var rate = parseInt(element.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  46 +
  47 + return test_regex.test(rate);
  48 + });
  49 +
  50 + return result;
  51 + }
  52 +
  53 +
  54 + /*
  55 + * Show or hide the stars depending on the mouse position and the limit rate.
  56 + * Given the mouseover rate, the limit rate and the css classes to be swapped,
  57 + *
  58 + * It verify if the user already selected a star rate:
  59 + * If true:
  60 + * It swap the css classes from the selected star up to the given limit rate
  61 + * If false:
  62 + * It swap the css classes from the minimum rate up to the mouseover rate
  63 + */
  64 + function change_stars_class(rate_mouseover, limit_rate, remove_class, add_class) {
  65 + var previous_stars = undefined;
  66 +
  67 + // The default not selected rate value is 0 and minimum is 1.
  68 + if (DATA.selected_rate >= DATA.minimum_stars) {
  69 + previous_stars = star_filter(DATA.selected_rate+1, limit_rate, $("."+remove_class));
  70 + } else {
  71 + previous_stars = star_filter(DATA.minimum_stars, rate_mouseover, $("."+remove_class));
  72 + }
  73 +
  74 + previous_stars.switchClass(remove_class, add_class);
  75 + }
  76 +
  77 +
  78 + /*
  79 + * Sets the stars mouse events.
  80 + */
  81 + function set_star_hover_actions() {
  82 + $(".star-negative, .star-positive")
  83 + .on("mouseover", function() { // On mouse over, show the current rate star
  84 + var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  85 +
  86 + change_stars_class(rate_mouseover, rate_mouseover, "star-negative", "star-positive");
  87 + })
  88 +
  89 + .on("mouseout", function() { // On mouse out, hide the stars
  90 + var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  91 +
  92 + change_stars_class(rate_mouseover, DATA.maximum_stars, "star-positive", "star-negative");
  93 + })
  94 +
  95 + .on("click", function() { // On mouse click, set the selected star rate
  96 + var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
  97 +
  98 + // If the new rate is different from actual, update it
  99 + if (rate_mouseover !== DATA.selected_rate && rate_mouseover > DATA.minimum_stars) {
  100 + DATA.selected_rate = rate_mouseover;
  101 + } else { // or else, uncheck it
  102 + DATA.selected_rate = DATA.minimum_stars;
  103 + }
  104 +
  105 + // Mark the selected_rate
  106 + $("#selected-star-rate").val(DATA.selected_rate);
  107 +
  108 + var star_notice = $(".star-notice");
  109 + star_notice.find("span").html(DATA.selected_rate);
  110 + star_notice.removeClass("star-hide");
  111 + });
  112 + }
  113 +
  114 +
  115 + /*
  116 + * When the page DOM is ready, set all the stars events
  117 + */
  118 + $(document).ready(function() {
  119 + set_global_data();
  120 + set_star_hover_actions();
  121 + });
  122 +}) (jQuery);
... ...
plugins/organization_ratings/style.css 0 → 100644
... ... @@ -0,0 +1,200 @@
  1 +.star-container {
  2 + width: 100%;
  3 + height: 20px;
  4 +}
  5 +
  6 +.star-negative, .star-positive {
  7 + width: 20px;
  8 + height: 20px;
  9 + background-repeat: no-repeat;
  10 + margin-right: 2px;
  11 + position: relative;
  12 + float: left;
  13 + cursor: pointer;
  14 +}
  15 +
  16 +.star-negative {
  17 + background-image: url('public/images/star-negative.png');
  18 +}
  19 +
  20 +.star-positive {
  21 + background-image: url('public/images/star-positive.png');
  22 +}
  23 +
  24 +.small-star-negative, .small-star-positive {
  25 + background-repeat: no-repeat;
  26 + float: left;
  27 + height: 15px;
  28 + margin-right: 2px;
  29 + position: relative;
  30 + width: 15px;
  31 +}
  32 +
  33 +.small-star-negative {
  34 + background-image: url('public/images/small-star-negative.png');
  35 +}
  36 +
  37 +.small-star-positive {
  38 + background-image: url('public/images/small-star-positive.png');
  39 +}
  40 +
  41 +.medium-star-negative, .medium-star-positive {
  42 + background-repeat: no-repeat;
  43 + float: left;
  44 + height: 20px;
  45 + margin-right: 2px;
  46 + position: relative;
  47 + width: 20px;
  48 +}
  49 +
  50 +.medium-star-positive {
  51 + background-image: url('public/images/star-positive-medium.png');
  52 +}
  53 +
  54 +.medium-star-negative {
  55 + background-image: url('public/images/star-negative-medium.png');
  56 +}
  57 +
  58 +.star-hide {
  59 + display: none;
  60 +}
  61 +
  62 +.organization-average-rating-container {
  63 + border-top: 1px dotted #D3D6DE;
  64 + margin-top: 20px;
  65 + padding-top: 10px;
  66 +}
  67 +
  68 +.organization-average-rating-container .star-rate-text {
  69 + float: left;
  70 + margin-right: 10px;
  71 + padding-top: 5px;
  72 +}
  73 +
  74 +.organization-average-rating-container .rating-invitation {
  75 + font-size: 14px;
  76 + float: left;
  77 + margin-right: 10px;
  78 + padding-top: 3px;
  79 +}
  80 +
  81 +.organization-average-rating-container .star-container {
  82 + float: left;
  83 + width: 120px;
  84 +}
  85 +
  86 +.organization-average-rating-container .rate-this-organization {
  87 + border-left: 1px dotted #D3D6DE;
  88 + float: left;
  89 + padding: 4px 0px 2px 10px;
  90 +}
  91 +
  92 +.star-rate-data {
  93 + width: 100%;
  94 + padding-top: 20px;
  95 + position: relative;
  96 + overflow: auto;
  97 +}
  98 +
  99 +.star-profile-information, .star-rate-form {
  100 + display: table-cell;
  101 + vertical-align: top;
  102 + width: 362px;
  103 +}
  104 +
  105 +.star-profile-information {
  106 + width: 134px;
  107 +}
  108 +
  109 +.star-rate-form {
  110 + display: table-cell;
  111 + vertical-align: top;
  112 +}
  113 +
  114 +.star-profile-image, .star-profile-name {
  115 + text-align: center;
  116 +}
  117 +
  118 +.star-profile-name {
  119 + word-break: break-word;
  120 + margin: auto;
  121 + margin-top: 5px;
  122 + width: 66px;
  123 +}
  124 +
  125 +.star-rate-data .star-rate-form .star-comment-container .formfield textarea {
  126 + width: 361px;
  127 +}
  128 +
  129 +/************* Users ratings list ****************/
  130 +
  131 +.ratings-list .user-rating-block,
  132 +.ratings-list .make-report-block {
  133 + border-top: 1px solid #D3D6DE;
  134 + margin-top: 25px;
  135 + padding-top: 20px;
  136 +}
  137 +
  138 +.ratings-list .make-report-block {
  139 + padding-bottom: 25px;
  140 +}
  141 +
  142 +.ratings-list .see-more{
  143 + border-top: 1px solid #D3D6DE;
  144 +}
  145 +.ratings-list .user-rating-block .user-testimony-container {
  146 + display: table-cell;
  147 + padding-left: 20px;
  148 +}
  149 +
  150 +.ratings-list .make-report-block .make-report-container {
  151 + display: table-cell;
  152 +}
  153 +
  154 +.ratings-list .user-rating-block .user-testimony-container .star-container {
  155 + display: table-cell;
  156 +}
  157 +
  158 +.ratings-list .user-rating-block .user-testimony-container .testimony-rate-date {
  159 + display: table-cell;
  160 + max-width: 95px;
  161 + min-width: 95px;
  162 + padding-right: 160px;
  163 + white-space: nowrap;
  164 +}
  165 +
  166 +.ratings-list .user-rating-block .user-testimony-container .user-testimony {
  167 + margin-top: 10px;
  168 + word-break: break-word;
  169 +}
  170 +
  171 +.ratings-list .make-report-block .make-report-container .make-report-message {
  172 + font-size: 14px;
  173 + font-style: italic;
  174 + word-break: break-word;
  175 +}
  176 +
  177 +.ratings-list .make-report-block .make-report-container .button-bar {
  178 + overflow: auto;
  179 + padding-top: 15px;
  180 +}
  181 +
  182 +.ratings-list .user-rating-block .star-profile-information {
  183 + border-right: 1px dotted #D3D6DE;
  184 +}
  185 +
  186 +.ratings-list .icon-arrow-right-p {
  187 + background: url(/designs/themes/base/imgs/arrow-right-p.png) 100% 50% no-repeat;
  188 + display: block;
  189 + float: right;
  190 + margin-top: 20px;
  191 + padding-right: 15px;
  192 +}
  193 +
  194 +.task_information .comment {
  195 + padding-left: 60px;
  196 +}
  197 +
  198 +.average-rating-block {
  199 + height: 55px;
  200 +}
... ...
plugins/organization_ratings/test/functional/organization_ratings_plugin_admin_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,49 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +require File.expand_path(File.dirname(__FILE__)) + '/../../controllers/organization_ratings_plugin_admin_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class OrganizationRatingsPluginAdminController; def rescue_action(e) raise e end; end
  6 +
  7 +class OrganizationRatingsPluginAdminControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = OrganizationRatingsPluginAdminController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 +
  14 + @environment = Environment.default
  15 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  16 + @environment.save
  17 +
  18 + @community = Community.create(:name => "TestCommunity")
  19 +
  20 + login_as(create_admin_user(@environment))
  21 + end
  22 +
  23 + test "should update organization rating plugin configuration" do
  24 + post :update, :organization_ratings_config => { :default_rating => 5,
  25 + :cooldown => 12,
  26 + :order => "recent",
  27 + :per_page => 10,
  28 + :vote_once => true }
  29 +
  30 + assert :success
  31 + @environment.reload
  32 + assert_equal 5, @environment.organization_ratings_config.default_rating
  33 + assert_equal "Configuration updated successfully.", session[:notice]
  34 + end
  35 +
  36 + test "should not update organization rating plugin configuration with negative cooldown time" do
  37 + post :update, :organization_ratings_config => { :default_rating => 5,
  38 + :cooldown => -50,
  39 + :order => "recent",
  40 + :per_page => 10,
  41 + :vote_once => true }
  42 +
  43 + assert :success
  44 + @environment.reload
  45 + assert_equal 24, @environment.organization_ratings_config.cooldown
  46 + assert_equal "Configuration could not be saved.", session[:notice]
  47 + end
  48 +end
  49 +
... ...
plugins/organization_ratings/test/functional/organization_ratings_plugin_profile_controller_test.rb 0 → 100644
... ... @@ -0,0 +1,104 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +require File.expand_path(File.dirname(__FILE__)) + '/../../controllers/organization_ratings_plugin_profile_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class OrganizationRatingsPluginProfileController; def rescue_action(e) raise e end; end
  6 +
  7 +class OrganizationRatingsPluginProfileControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = OrganizationRatingsPluginProfileController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 +
  14 + @environment = Environment.default
  15 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  16 + @environment.save
  17 +
  18 + @person = create_user('testuser').person
  19 + @community = Community.create(:name => "TestCommunity")
  20 + @enterprise = fast_create(Enterprise)
  21 + @config = OrganizationRatingsConfig.instance
  22 + login_as(@person.identifier)
  23 + @controller.stubs(:logged_in?).returns(true)
  24 + @controller.stubs(:current_user).returns(@person.user)
  25 + end
  26 +
  27 + test "should add new comment to community" do
  28 + post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test"}, :organization_rating_value => 4
  29 + assert_equal "#{@community.name} successfully rated!", session[:notice]
  30 + end
  31 +
  32 + test "Create community_rating without comment body" do
  33 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => 2
  34 +
  35 + assert_equal "#{@community.name} successfully rated!", session[:notice]
  36 + end
  37 +
  38 + test "Do not create community_rating without a rate value" do
  39 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => nil
  40 +
  41 + assert_equal "Sorry, there were problems rating this profile.", session[:notice]
  42 + end
  43 +
  44 + test "do not create two ratings on Community when vote once config is true" do
  45 + post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test"}, :organization_rating_value => 3
  46 +
  47 + assert_equal "#{@community.name} successfully rated!", session[:notice]
  48 +
  49 + @environment.organization_ratings_config.vote_once = true
  50 + @environment.save
  51 +
  52 + post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test 2"}, :organization_rating_value => 3
  53 + assert_equal "You can not vote on this Community", session[:notice]
  54 + end
  55 +
  56 + test "do not create two ratings on Enterprise when vote once config is true" do
  57 + post :new_rating, profile: @enterprise.identifier, :comments => {:body => "This is a test"}, :organization_rating_value => 3
  58 +
  59 + assert_equal "#{@enterprise.name} successfully rated!", session[:notice]
  60 +
  61 + @environment.organization_ratings_config.vote_once = true
  62 + @environment.save
  63 +
  64 + post :new_rating, profile: @enterprise.identifier, :comments => {:body => "This is a test 2"}, :organization_rating_value => 3
  65 + assert_equal "You can not vote on this Enterprise", session[:notice]
  66 + end
  67 +
  68 + test "should count organization ratings on statistic block when block owner = Environment" do
  69 + block = StatisticsBlock.new
  70 + enterprise = fast_create(Enterprise)
  71 + post :new_rating, profile: enterprise.identifier, :comments => {:body => "body board"}, :organization_rating_value => 1
  72 + enterprise.reload
  73 + @environment.reload
  74 + block.expects(:owner).at_least_once.returns(@environment)
  75 + assert_equal 1, block.comments
  76 + end
  77 +
  78 +
  79 + test "should count organization ratings on statistic block when block owner = Profile" do
  80 + @config.cooldown = 0
  81 + @config.save
  82 +
  83 + block = StatisticsBlock.new
  84 +
  85 + post :new_rating, profile: @community.identifier, :comments => {:body => "body board"}, :organization_rating_value => 1
  86 + post :new_rating, profile: @community.identifier, :comments => {:body => "body surf"}, :organization_rating_value => 5
  87 +
  88 + block.expects(:owner).at_least_once.returns(@community)
  89 + @community.reload
  90 + assert_equal 2, block.comments
  91 + end
  92 +
  93 + test "Display unavailable rating message for users that must wait the rating cooldown time" do
  94 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => 3
  95 + assert_not_match(/The administrators set the minimum time of/, @response.body)
  96 + valid_rating = OrganizationRating.last
  97 +
  98 + post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :organization_rating_value => 3
  99 + assert_match(/The administrators set the minimum time of/, @response.body)
  100 + new_rating = OrganizationRating.last
  101 +
  102 + assert_equal valid_rating.id, new_rating.id
  103 + end
  104 +end
... ...
plugins/organization_ratings/test/unit/organization_rating_config_test.rb 0 → 100644
... ... @@ -0,0 +1,43 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +
  3 +class OrganizationRatingConfigTest < ActiveSupport::TestCase
  4 +
  5 + def setup
  6 + @environment = Environment.default
  7 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  8 + @environment.save
  9 + @organization_ratings_config = OrganizationRatingsConfig.instance
  10 + end
  11 +
  12 + test "Community ratings config default rating validation" do
  13 + @organization_ratings_config.default_rating = 0
  14 + @organization_ratings_config.save
  15 +
  16 + assert_equal false, @organization_ratings_config.valid?
  17 + assert_equal "must be greater than or equal to 1", @organization_ratings_config.errors[:default_rating].first
  18 +
  19 + @organization_ratings_config.default_rating = 6
  20 + assert_equal false, @organization_ratings_config.valid?
  21 +
  22 + assert_equal "must be less than or equal to 5", @organization_ratings_config.errors[:default_rating].first
  23 + end
  24 +
  25 + test "Communities ratings config cooldown validation" do
  26 + @organization_ratings_config.cooldown = -1
  27 + assert_equal false, @organization_ratings_config.valid?
  28 +
  29 + assert_equal "must be greater than or equal to 0", @organization_ratings_config.errors[:cooldown].first
  30 + end
  31 +
  32 + # test "communities ratings per page validation" do
  33 + # environment = Environment.new :communities_ratings_per_page => 4
  34 + # environment.valid?
  35 +
  36 + # assert_equal "must be greater than or equal to 5", environment.errors[:communities_ratings_per_page].first
  37 +
  38 + # environment.communities_ratings_per_page = 21
  39 + # environment.valid?
  40 +
  41 + # assert_equal "must be less than or equal to 20", environment.errors[:communities_ratings_per_page].first
  42 + # end
  43 +end
... ...
plugins/organization_ratings/test/unit/organization_rating_test.rb 0 → 100644
... ... @@ -0,0 +1,154 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +
  3 +class OrganizationRatingTest < ActiveSupport::TestCase
  4 + test "The value must be between 1 and 5" do
  5 + organization_rating1 = OrganizationRating.new :value => -1
  6 + organization_rating2 = OrganizationRating.new :value => 6
  7 +
  8 + assert_equal false, organization_rating1.valid?
  9 + assert_equal false, organization_rating2.valid?
  10 +
  11 + assert_equal true, organization_rating1.errors[:value].include?("must be between 1 and 5")
  12 + assert_equal true, organization_rating2.errors[:value].include?("must be between 1 and 5")
  13 +
  14 + organization_rating1.value = 1
  15 + organization_rating1.valid?
  16 +
  17 + organization_rating2.value = 5
  18 + organization_rating2.valid?
  19 +
  20 + assert_equal false, organization_rating1.errors[:value].include?("must be between 1 and 5")
  21 + assert_equal false, organization_rating2.errors[:value].include?("must be between 1 and 5")
  22 + end
  23 +
  24 + test "Create task for create a rating comment" do
  25 + person = create_user('molly').person
  26 + person.email = "person@email.com"
  27 + person.save!
  28 +
  29 + community = fast_create(Community)
  30 + community.add_admin(person)
  31 +
  32 + organization_rating = OrganizationRating.create!(
  33 + :value => 3,
  34 + :person => person,
  35 + :organization => community
  36 + )
  37 +
  38 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  39 + :requestor => person,
  40 + :organization_rating_id => organization_rating.id,
  41 + :target => community
  42 + )
  43 +
  44 + assert community.tasks.include?(create_organization_rating_comment)
  45 + end
  46 +
  47 + test "Check comment message when Task status = ACTIVE" do
  48 + person = create_user('molly').person
  49 + person.email = "person@email.com"
  50 + person.save!
  51 +
  52 + community = fast_create(Community)
  53 + community.add_admin(person)
  54 +
  55 +
  56 + organization_rating = OrganizationRating.create!(
  57 + :value => 3,
  58 + :person => person,
  59 + :organization => community
  60 + )
  61 +
  62 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  63 + :requestor => person,
  64 + :organization_rating_id => organization_rating.id,
  65 + :target => community,
  66 + :body => "sample comment"
  67 + )
  68 + assert_equal 1, create_organization_rating_comment.status
  69 + message = "Comment waiting for approval"
  70 + comment = Comment.find_by_id(create_organization_rating_comment.organization_rating_comment_id)
  71 + assert_equal message, comment.body
  72 + end
  73 +
  74 + test "Check comment message when Task status = CANCELLED" do
  75 + person = create_user('molly').person
  76 + person.email = "person@email.com"
  77 + person.save!
  78 +
  79 + community = fast_create(Community)
  80 + community.add_admin(person)
  81 +
  82 +
  83 + organization_rating = OrganizationRating.create!(
  84 + :value => 3,
  85 + :person => person,
  86 + :organization => community
  87 + )
  88 +
  89 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  90 + :requestor => person,
  91 + :organization_rating_id => organization_rating.id,
  92 + :target => community,
  93 + :body => "sample comment"
  94 + )
  95 + create_organization_rating_comment.cancel
  96 + assert_equal 2, create_organization_rating_comment.status
  97 + message = "Comment rejected"
  98 + comment = Comment.find_by_id(create_organization_rating_comment.organization_rating_comment_id)
  99 + assert_equal message, comment.body
  100 + end
  101 +
  102 + test "Check comment message when Task status = FINISHED" do
  103 + person = create_user('molly').person
  104 + person.email = "person@email.com"
  105 + person.save!
  106 +
  107 + community = fast_create(Community)
  108 + community.add_admin(person)
  109 +
  110 + comment = Comment.create!(source: community,
  111 + body: "regular comment",
  112 + author: person)
  113 +
  114 + organization_rating = OrganizationRating.create!(
  115 + :value => 3,
  116 + :person => person,
  117 + :organization => community,
  118 + :comment => comment
  119 + )
  120 +
  121 + create_organization_rating_comment = CreateOrganizationRatingComment.create!(
  122 + :body => comment.body,
  123 + :requestor => organization_rating.person,
  124 + :organization_rating_id => organization_rating.id,
  125 + :target => organization_rating.organization,
  126 + :body => "sample comment"
  127 + )
  128 +
  129 + create_organization_rating_comment.finish
  130 + assert_equal 3, create_organization_rating_comment.status
  131 + message = "sample comment"
  132 + comment = Comment.find_by_id(create_organization_rating_comment.organization_rating_comment_id)
  133 + assert_equal message, comment.body
  134 + end
  135 +
  136 +
  137 + test "Should calculate community's rating average" do
  138 + community = fast_create Community
  139 + p1 = fast_create Person, :name=>"Person 1"
  140 + p2 = fast_create Person, :name=>"Person 2"
  141 + p3 = fast_create Person, :name=>"Person 3"
  142 +
  143 + OrganizationRating.create! :value => 2, :organization => community, :person => p1
  144 + OrganizationRating.create! :value => 3, :organization => community, :person => p2
  145 + OrganizationRating.create! :value => 5, :organization => community, :person => p3
  146 +
  147 + assert_equal 3, OrganizationRating.average_rating(community)
  148 +
  149 + p4 = fast_create Person, :name=>"Person 4"
  150 + OrganizationRating.create! :value => 4, :organization => community, :person => p4
  151 +
  152 + assert_equal 4, OrganizationRating.average_rating(community)
  153 + end
  154 +end
... ...
plugins/organization_ratings/test/unit/ratings_helper_test.rb 0 → 100644
... ... @@ -0,0 +1,63 @@
  1 +require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
  2 +require 'ratings_helper'
  3 +
  4 +class RatingsHelperTest < ActiveSupport::TestCase
  5 + include RatingsHelper
  6 +
  7 + def setup
  8 +
  9 + @environment = Environment.default
  10 + @environment.enabled_plugins = ['OrganizationRatingsPlugin']
  11 + @environment.save
  12 + @person = create_user('testuser').person
  13 + @community = Community.create(:name => "TestCommunity")
  14 + @organization_ratings_config = OrganizationRatingsConfig.instance
  15 + end
  16 +
  17 + should "get the ratings of a community ordered by most recent ratings" do
  18 + ratings_array = []
  19 +
  20 + first_rating = OrganizationRating.new
  21 + first_rating.organization = @community
  22 + first_rating.person = @person
  23 + first_rating.value = 3
  24 + first_rating.save
  25 +
  26 + most_recent_rating = OrganizationRating.new
  27 + most_recent_rating.organization = @community
  28 + most_recent_rating.person = @person
  29 + most_recent_rating.value = 5
  30 + sleep 2
  31 + most_recent_rating.save
  32 +
  33 + ratings_array << most_recent_rating
  34 + ratings_array << first_rating
  35 +
  36 + assert_equal @organization_ratings_config.order, "recent"
  37 + assert_equal ratings_array, get_ratings(@community.id)
  38 + end
  39 +
  40 + should "get the ratings of a community ordered by best ratings" do
  41 + ratings_array = []
  42 + @organization_ratings_config = "best"
  43 + @environment.save
  44 +
  45 + first_rating = OrganizationRating.new
  46 + first_rating.organization = @community
  47 + first_rating.person = @person
  48 + first_rating.value = 3
  49 + first_rating.save
  50 +
  51 + second_rating = OrganizationRating.new
  52 + second_rating.organization = @community
  53 + second_rating.person = @person
  54 + second_rating.value = 5
  55 + sleep 2
  56 + second_rating.save
  57 +
  58 + ratings_array << second_rating
  59 + ratings_array << first_rating
  60 +
  61 + assert_equal ratings_array, get_ratings(@community.id)
  62 + end
  63 +end
... ...
plugins/organization_ratings/views/blocks/display_organization_average_rating.html.erb 0 → 100644
... ... @@ -0,0 +1,25 @@
  1 +<div class="organization-average-rating-container">
  2 + <% if average_rating %>
  3 + <div class="star-rate-text">
  4 + <%= _("Rating: ") %>
  5 + </div>
  6 +
  7 + <div class="star-container">
  8 + <% (1..5).each do |star_number| %>
  9 + <% if star_number <= average_rating %>
  10 + <div class="medium-star-positive"></div>
  11 + <% else %>
  12 + <div class="medium-star-negative"></div>
  13 + <% end %>
  14 + <% end %>
  15 + </div>
  16 + <% else %>
  17 + <div class="rating-invitation">
  18 + <%= _("Be the first to rate!") %>
  19 + </div>
  20 + <% end %>
  21 +
  22 + <div class="rate-this-organization">
  23 + <%= link_to _("Rate this %s" % profile.class.name), url_for(:controller => "organization_ratings_plugin_profile", :action => "new_rating", :profile=>profile_identifier) %>
  24 + </div>
  25 +</div>
0 26 \ No newline at end of file
... ...
plugins/organization_ratings/views/blocks/organization_ratings_block.html.erb 0 → 100644
... ... @@ -0,0 +1,21 @@
  1 +<div class="ratings-title">
  2 + <%= block_title(block.title) %>
  3 + <% if block.get_ratings(block.owner.id).empty? %>
  4 + <div class="ratings-list">
  5 + <%= render :partial => 'shared/make_report_block' %>
  6 + </div>
  7 + <% else %>
  8 + <div class="ratings-list">
  9 + <% block.get_ratings(block.owner.id).each_with_index do |r, index| %>
  10 + <% break if index >= block.limit_number_of_ratings %>
  11 + <%= render :partial => "shared/user_rating_container", :locals => {:user_rate => r} %>
  12 + <% end %>
  13 +
  14 + <%= render :partial => 'shared/make_report_block' %>
  15 +
  16 + <div class="see-more">
  17 + <%= link_to _('See more'), url_for(:controller => 'organization_ratings_plugin_profile', :action => 'new_rating'), :class => 'icon-arrow-right-p' %>
  18 + </div>
  19 + </div>
  20 + <% end %>
  21 +</div>
... ...
plugins/organization_ratings/views/organization_ratings_plugin_admin/index.html.erb 0 → 100644
... ... @@ -0,0 +1,54 @@
  1 +<% config = env_organization_ratings_config %>
  2 +
  3 +<h1><%= _("Organization Rating Management") %> </h1>
  4 +
  5 +<%= labelled_form_for(:organization_ratings_config, :url => {:action => 'update'}) do |f| %>
  6 + <%= labelled_fields_for(:organization_ratings_config, config) do |c| %>
  7 + <table>
  8 + <tr>
  9 + <th><%= c_('Configuration') %></th>
  10 + <th><%= _('Value') %></th>
  11 + </tr>
  12 + <tr>
  13 + <td><%= _('Default amount of stars marked on evaluations') %></td>
  14 + <td><%= c.select :default_rating, (config.minimum_ratings)..5 %></td>
  15 + </tr>
  16 + <tr>
  17 + <td><%= _('Can rate an organization only once') %></td>
  18 + <td><%= c.check_box :vote_once %></td>
  19 + </tr>
  20 + <tr>
  21 + <td><%= _('The comments are moderated') %></td>
  22 + <td><%= c.check_box :are_moderated %></td>
  23 + </tr>
  24 + <tr>
  25 + <td>
  26 + <%= _('Time in hours between evaluations from the same user.') %>
  27 + <span class="hint" title=" <%= _('To disable cooldown use zero (0) value.') %> ">(?)</span>
  28 + </td>
  29 + <% hours_options = {size: 2} %>
  30 + <% hours_options[:disabled] = "disabled" if config.vote_once %>
  31 + <td><%= c.text_field :cooldown, hours_options %>
  32 + </td>
  33 + </tr>
  34 + <tr>
  35 + <td><%= _('Order ratings by') %></td>
  36 + <% order_options = [] %>
  37 + <% config.order_options.select{|k,v| order_options << v } %>
  38 + <td><%= c.select :order, order_options %></td>
  39 + </tr>
  40 + <tr>
  41 + <td><%= _('Ratings per page') %></td>
  42 + <td>
  43 + <%= c.select :per_page, 5..20 %>
  44 + </td>
  45 + </tr>
  46 + </table>
  47 + <div>
  48 + <% button_bar do %>
  49 + <%= submit_button('save', c_('Save changes')) %>
  50 + <%= button :back, _('Back'), :controller => 'plugins' %>
  51 + <% end %>
  52 + </div>
  53 + <% end %>
  54 +<% end %>
... ...
plugins/organization_ratings/views/organization_ratings_plugin_profile/_new_rating_fields.html.erb 0 → 100644
... ... @@ -0,0 +1,80 @@
  1 +<% min_rate = env_organization_ratings_config.minimum_ratings %>
  2 +<% default_rating = env_organization_ratings_config.default_rating %>
  3 +
  4 +<div class="star-page-title">
  5 + <%= @plugins.dispatch(:organization_ratings_title).collect { |content| instance_exec(&content) }.join("") %>
  6 +</div>
  7 +
  8 +<div class="star-rate-data">
  9 +
  10 + <div class="star-profile-information">
  11 + <div class="star-profile-image">
  12 + <%= profile_image(current_user.person, :portrait) %>
  13 + </div>
  14 +
  15 + <div class="star-profile-name">
  16 + <%= current_user.name %>
  17 + </div>
  18 + </div>
  19 +
  20 + <% if @rating_available %>
  21 + <div class="star-rate-form">
  22 + <div data-rate-url=<%= url_for controller: "organization_ratings_plugin_profile", :action => "rate" %>>
  23 + <div class="star-rate-text">
  24 + <%= @plugins.dispatch(:organization_ratings_plugin_star_message).collect { |content| instance_exec(&content) }.join("") %>
  25 + </div>
  26 +
  27 + <div class="star-container" data-min-rate="<%= min_rate %>">
  28 +
  29 + <% (1..5).each do |rate_number| %>
  30 + <% if rate_number <= default_rating %>
  31 + <div class="star-positive" data-star-rate="<%= rate_number %>"></div>
  32 + <% else %>
  33 + <div class="star-negative" data-star-rate="<%= rate_number %>"></div>
  34 + <% end %>
  35 + <% end %>
  36 + </div>
  37 +
  38 + <div class="star-notice star-hide">
  39 + <%= _("Rated as") %> <span></span> <%= _("stars") %>
  40 + </div>
  41 + </div>
  42 +
  43 + <div class="star-comment-container">
  44 + <%= form_for :comments do |c| %>
  45 + <div class="formfieldline formfield type-text">
  46 + <%= c.label :body, _('Comment (Optional):'), :class => "formlabel" %>
  47 + <%= c.text_area :body %>
  48 + </div>
  49 +
  50 + <%= @plugins.dispatch(:organization_ratings_plugin_comments_extra_fields).collect { |content| instance_exec(&content) }.join("") %>
  51 +
  52 + <div class="button-bar">
  53 + <%= submit_button(:save, _('Save'), :cancel => {controller: 'profile', action: 'index'}) %>
  54 + </div>
  55 +
  56 + <input type="hidden" id="selected-star-rate" name="organization_rating_value" value="<%= @default_rate %>">
  57 + <input type="hidden" id="minimum_stars" name="organization_rating_min_value" value="<%= min_rate %>">
  58 + <% end %>
  59 + </div>
  60 +
  61 + <% elsif env_organization_ratings_config.vote_once %>
  62 + <div class="star-rate-form rating-vote-once">
  63 + <%= _("Hi, %s! The administrators set that you can vote") % current_user.name %>
  64 + <strong><%= _("only once") %></strong>
  65 + <%= _("for this %s.") % profile.class.name.downcase %>
  66 + <%= render :partial => 'shared/rating_button', :locals => { :disabled => true } %>
  67 + </div>
  68 + <% else %>
  69 + <div class="star-rate-form rating-cooldown">
  70 + <%= _("Hi, %s! The administrators set the minimum time of") % current_user.name %>
  71 + <strong><%= _("%s hour(s)" % env_organization_ratings_config.cooldown) %></strong>
  72 + <%= _("between each evaluation.") %>
  73 +
  74 + <%= render :partial => 'shared/rating_button', :locals => { :disabled => true } %>
  75 + </div>
  76 + <% end %>
  77 +
  78 +
  79 + </div>
  80 +</div>
0 81 \ No newline at end of file
... ...
plugins/organization_ratings/views/organization_ratings_plugin_profile/new_rating.html.erb 0 → 100644
... ... @@ -0,0 +1,18 @@
  1 +<% config = env_organization_ratings_config %>
  2 +<% if logged_in? %>
  3 + <%= render :partial => "new_rating_fields" %>
  4 +<% else %>
  5 + <div class="ratings-list">
  6 + <%= render :partial => "shared/make_report_block" %>
  7 + </div>
  8 +<% end %>
  9 +
  10 +<div class="ratings-list">
  11 + <% @users_ratings.each do |user_rate| %>
  12 + <%= render :partial => "shared/user_rating_container", :locals => {:user_rate => user_rate} %>
  13 + <% end %>
  14 +</div>
  15 +
  16 +<div id='pagination-profiles'>
  17 + <%= pagination_links @users_ratings, :param_name => 'npage' %>
  18 +</div>
0 19 \ No newline at end of file
... ...
plugins/organization_ratings/views/shared/_make_report_block.html.erb 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +<% logged_in_image = profile_image(current_user.person, :portrait) if current_user %>
  2 +<% logged_out_image = image_tag('plugins/organization_ratings/public/images/user-not-logged.png') %>
  3 +
  4 +<div class="make-report-block">
  5 + <div class="star-profile-information">
  6 + <div class="star-profile-image">
  7 + <%= logged_in? ? logged_in_image : logged_out_image %>
  8 + </div>
  9 +
  10 + <div class="star-profile-name">
  11 + <%= logged_in? ? current_user.person.name : _('User not logged *') %>
  12 + </div>
  13 + </div>
  14 +
  15 + <div class="make-report-container">
  16 + <div class="make-report-message">
  17 + <%= _('Report your experiences.') %>
  18 + </div>
  19 +
  20 + <%= render :partial => 'shared/rating_button', :locals => { :disabled => false } %>
  21 +
  22 + <% unless logged_in? %>
  23 + <div class="alert">
  24 + <%= _('* You must be logged in to submit a report.') %>
  25 + </div>
  26 + <% end %>
  27 + </div>
  28 +</div>
0 29 \ No newline at end of file
... ...
plugins/organization_ratings/views/shared/_rating_button.html.erb 0 → 100644
... ... @@ -0,0 +1,10 @@
  1 +<% button_bar do %>
  2 + <% if logged_in? %>
  3 + <%= button(:new,_("Rate %s ") % profile.class.name,
  4 + {:controller => "organization_ratings_plugin_profile",
  5 + :action => "new_rating"}) %>
  6 + <% else %>
  7 + <%= button(:login,_("Log in") , {:controller => 'account',
  8 + :action => 'login'}) %>
  9 + <% end %>
  10 +<% end %>
... ...
plugins/organization_ratings/views/shared/_user_rating_container.html.erb 0 → 100644
... ... @@ -0,0 +1,33 @@
  1 +<div class="user-rating-block">
  2 + <div class="star-profile-information">
  3 + <div class="star-profile-image">
  4 + <%= profile_image(user_rate.person, :portrait) %>
  5 + </div>
  6 +
  7 + <div class="star-profile-name">
  8 + <%= user_rate.person.name %>
  9 + </div>
  10 + </div>
  11 +
  12 + <div class="user-testimony-container">
  13 + <div class="testimony-rate-date">
  14 + <%= time_ago_in_words(user_rate.created_at) %>
  15 + </div>
  16 +
  17 + <div class="star-container">
  18 + <% (1..5).each do |rate_number| %>
  19 + <% if rate_number <= user_rate.value %>
  20 + <div class="small-star-positive"></div>
  21 + <% else %>
  22 + <div class="small-star-negative"></div>
  23 + <% end %>
  24 + <% end %>
  25 + </div>
  26 +
  27 + <div class="user-testimony">
  28 + <%= user_rate.comment.nil? ? _("No comment") : user_rate.comment.body %>
  29 + </div>
  30 +
  31 + <%= @plugins.dispatch(:organization_ratings_plugin_extra_fields_show_data, user_rate).collect { |content| instance_exec(&content) }.join("") %>
  32 + </div>
  33 +</div>
... ...
plugins/organization_ratings/views/tasks/_create_organization_rating_comment_accept_details.html.erb 0 → 100644
... ... @@ -0,0 +1,4 @@
  1 +<div class="organization-rating-comment-body">
  2 + <%= _("Comment:")%>
  3 + <%= "\"#{task.body}\""%>
  4 +</div>
... ...
plugins/statistics/lib/statistics_block.rb
... ... @@ -128,11 +128,12 @@ class StatisticsBlock &lt; Block
128 128 end
129 129 end
130 130  
  131 + include Noosfero::Plugin::HotSpot
131 132 def comments
132 133 if owner.kind_of?(Environment) then
133   - owner.profiles.joins(:articles).sum(:comments_count).to_i
  134 + owner.articles.sum(:comments_count).to_i + plugins.dispatch(:more_comments_count, owner).first.to_i
134 135 elsif owner.kind_of?(Profile) then
135   - owner.articles.sum(:comments_count)
  136 + owner.articles.sum(:comments_count) + plugins.dispatch(:more_comments_count, owner).first.to_i
136 137 else
137 138 0
138 139 end
... ...