diff --git a/plugins/communities_ratings/controllers/communities_ratings_plugin_admin_controller.rb b/plugins/communities_ratings/controllers/communities_ratings_plugin_admin_controller.rb
new file mode 100644
index 0000000..bcd123c
--- /dev/null
+++ b/plugins/communities_ratings/controllers/communities_ratings_plugin_admin_controller.rb
@@ -0,0 +1,17 @@
+class CommunitiesRatingsPluginAdminController < PluginAdminController
+
+ append_view_path File.join(File.dirname(__FILE__) + '/../views')
+
+ def index
+ end
+
+ def update
+ if @environment.update_attributes(params[:environment])
+ session[:notice] = _('Configuration updated successfully.')
+ else
+ session[:notice] = _('Configuration could not be saved.')
+ end
+ render :action => 'index'
+ end
+
+end
\ No newline at end of file
diff --git a/plugins/communities_ratings/controllers/communities_ratings_plugin_profile_controller.rb b/plugins/communities_ratings/controllers/communities_ratings_plugin_profile_controller.rb
new file mode 100644
index 0000000..b8b2504
--- /dev/null
+++ b/plugins/communities_ratings/controllers/communities_ratings_plugin_profile_controller.rb
@@ -0,0 +1,80 @@
+class CommunitiesRatingsPluginProfileController < ProfileController
+ include RatingsHelper
+
+ def new_rating
+ @rating_available = can_rate_now?
+ @users_ratings = get_ratings(profile.id)
+ @users_ratings = @users_ratings.paginate(
+ :per_page => environment.communities_ratings_per_page,
+ :page => params[:npage]
+ )
+ @default_rate = environment.communities_ratings_default_rating
+ @min_rate = Environment.communities_ratings_min_rating
+
+ if request.post?
+ if @rating_available
+ create_new_rate
+ else
+ session[:notice] = _("You cant vote on this community")
+ end
+ end
+ end
+
+ private
+
+ def can_rate_now?
+ return false unless user
+
+ ratings = CommunityRating.where(
+ :community_id=>profile.id,
+ :person_id=>user.id
+ )
+
+ return false if !ratings.empty? && environment.communities_ratings_vote_once
+
+ if ratings.empty?
+ true
+ else
+ elapsed_time_since_last_rating = Time.zone.now - ratings.last.created_at
+ elapsed_time_since_last_rating > environment.communities_ratings_cooldown.hours
+ end
+ end
+
+ def create_new_rate
+ community_rating = CommunityRating.new(params[:community_rating])
+ community_rating.person = current_user.person
+ community_rating.community = profile
+ community_rating.value = params[:community_rating_value] if params[:community_rating_value]
+
+ if params[:comments] and (not params[:comments][:body].empty?)
+ if !environment.communities_ratings_are_moderated
+ comment = Comment.new(params[:comments])
+ comment.author = community_rating.person
+ comment.community = community_rating.community
+ comment.save
+
+ community_rating.comment = comment
+ else
+ create_comment = CreateCommunityRatingComment.create!(
+ params[:comments].merge(
+ :requestor => community_rating.person,
+ :source => community_rating.community,
+ :community_rating => community_rating,
+ :organization => community_rating.community
+ )
+ )
+ end
+ end
+
+ if community_rating.save
+ session[:notice] = _("#{profile.name} successfully rated!")
+ redirect_to :controller => 'profile', :action => 'index'
+ else
+ session[:notice] = _("Sorry, there were problems rating this profile.")
+ end
+ end
+
+ def permission
+ :manage_memberships
+ end
+end
diff --git a/plugins/communities_ratings/db/migrate/20150701122801_create_community_ratings.rb b/plugins/communities_ratings/db/migrate/20150701122801_create_community_ratings.rb
new file mode 100644
index 0000000..5534983
--- /dev/null
+++ b/plugins/communities_ratings/db/migrate/20150701122801_create_community_ratings.rb
@@ -0,0 +1,11 @@
+class CreateCommunityRatings < ActiveRecord::Migration
+ def change
+ create_table :community_ratings do |t|
+ t.belongs_to :community
+ t.belongs_to :person
+ t.integer :value
+
+ t.timestamps
+ end
+ end
+end
diff --git a/plugins/communities_ratings/db/migrate/20150706161041_add_comments_count_to_community.rb b/plugins/communities_ratings/db/migrate/20150706161041_add_comments_count_to_community.rb
new file mode 100644
index 0000000..d3bd9a4
--- /dev/null
+++ b/plugins/communities_ratings/db/migrate/20150706161041_add_comments_count_to_community.rb
@@ -0,0 +1,11 @@
+class AddCommentsCountToCommunity < ActiveRecord::Migration
+ def self.up
+ change_table :profiles do |t|
+ t.integer :comments_count
+ end
+ end
+
+ def self.down
+ remove_column :profiles, :comments_count
+ end
+end
diff --git a/plugins/communities_ratings/db/migrate/20150707133834_add_community_rating_to_comments.rb b/plugins/communities_ratings/db/migrate/20150707133834_add_community_rating_to_comments.rb
new file mode 100644
index 0000000..10c7bda
--- /dev/null
+++ b/plugins/communities_ratings/db/migrate/20150707133834_add_community_rating_to_comments.rb
@@ -0,0 +1,11 @@
+class AddCommunityRatingToComments < ActiveRecord::Migration
+ def self.up
+ change_table :comments do |t|
+ t.belongs_to :community_rating
+ end
+ end
+
+ def self.down
+ remove_column :comments, :community_rating_id
+ end
+end
diff --git a/plugins/communities_ratings/db/migrate/20150806192933_create_community_rating_comment_task.rb b/plugins/communities_ratings/db/migrate/20150806192933_create_community_rating_comment_task.rb
new file mode 100644
index 0000000..e5d6a98
--- /dev/null
+++ b/plugins/communities_ratings/db/migrate/20150806192933_create_community_rating_comment_task.rb
@@ -0,0 +1,13 @@
+class CreateCommunityRatingCommentTask < ActiveRecord::Migration
+ def up
+ change_table :tasks do |t|
+ t.belongs_to :community_rating
+ t.belongs_to :source, :foreign_key => :source_id
+ end
+ end
+
+ def down
+ remove_column :tasks, :community_ratings_id
+ remove_column :tasks, :source_id
+ end
+end
diff --git a/plugins/communities_ratings/db/migrate/20151010171028_add_communities_rating_config_to_environment.rb b/plugins/communities_ratings/db/migrate/20151010171028_add_communities_rating_config_to_environment.rb
new file mode 100644
index 0000000..4a7c9dc
--- /dev/null
+++ b/plugins/communities_ratings/db/migrate/20151010171028_add_communities_rating_config_to_environment.rb
@@ -0,0 +1,11 @@
+class AddCommunitiesRatingConfigToEnvironment < ActiveRecord::Migration
+
+ def change
+ add_column :environments, :communities_ratings_cooldown, :integer, :default => 24
+ add_column :environments, :communities_ratings_default_rating, :integer, :default => 1
+ add_column :environments, :communities_ratings_order, :string, :default => "most recent"
+ add_column :environments, :communities_ratings_per_page, :integer, :default => 10
+ add_column :environments, :communities_ratings_vote_once, :boolean, :default => false
+ add_column :environments, :communities_ratings_are_moderated, :boolean, :default => true
+ end
+end
diff --git a/plugins/communities_ratings/lib/communities_ratings_block.rb b/plugins/communities_ratings/lib/communities_ratings_block.rb
new file mode 100644
index 0000000..fcee628
--- /dev/null
+++ b/plugins/communities_ratings/lib/communities_ratings_block.rb
@@ -0,0 +1,31 @@
+class CommunitiesRatingsBlock < Block
+ include RatingsHelper
+
+ def self.description
+ _('Community Ratings')
+ end
+
+ def help
+ _('This block displays the community ratings.')
+ end
+
+ def content(args = {})
+ block = self
+
+ proc do
+ render(
+ :file => 'blocks/communities_ratings_block',
+ :locals => {:block => block}
+ )
+ end
+ end
+
+ def limit_number_of_ratings
+ count = self.owner.community_ratings.count
+ count > 3 ? 3 : count
+ end
+
+ def cacheable?
+ false
+ end
+end
diff --git a/plugins/communities_ratings/lib/communities_ratings_plugin.rb b/plugins/communities_ratings/lib/communities_ratings_plugin.rb
new file mode 100644
index 0000000..eb618a2
--- /dev/null
+++ b/plugins/communities_ratings/lib/communities_ratings_plugin.rb
@@ -0,0 +1,62 @@
+class CommunitiesRatingsPlugin < Noosfero::Plugin
+ include Noosfero::Plugin::HotSpot
+
+ def self.plugin_name
+ "Communities Ratings"
+ end
+
+ def self.plugin_description
+ _("A plugin that allows you to rate a community and comment about it.")
+ end
+
+ module Hotspots
+ def communities_ratings_plugin_comments_extra_fields
+ nil
+ end
+
+ def communities_ratings_title
+ nil
+ end
+
+ def communities_ratings_plugin_star_message
+ nil
+ end
+
+ def communities_ratings_plugin_extra_fields_show_data user_rating
+ nil
+ end
+ end
+
+ # Plugin Hotspot to display the average rating
+ def display_community_average_rating community
+ unless community.nil?
+ average_rating = CommunityRating.average_rating community.id
+
+ Proc::new {
+ render :file => 'hotspots/display_community_average_rating',
+ :locals => {
+ :profile_identifier => community.identifier,
+ :average_rating => average_rating
+ }
+ }
+ end
+ end
+
+ def self.extra_blocks
+ {
+ CommunitiesRatingsBlock => { :type => [Community], :position => ['1']}
+ }
+ end
+
+ def stylesheet?
+ true
+ end
+
+ def js_files
+ %w(
+ public/rate.js
+ public/comunities_rating_management.js
+ )
+ end
+
+end
diff --git a/plugins/communities_ratings/lib/community_rating.rb b/plugins/communities_ratings/lib/community_rating.rb
new file mode 100644
index 0000000..a8f551a
--- /dev/null
+++ b/plugins/communities_ratings/lib/community_rating.rb
@@ -0,0 +1,26 @@
+class CommunityRating < ActiveRecord::Base
+ belongs_to :person
+ belongs_to :community
+
+ attr_accessible :value, :person, :community
+
+ validates :value,
+ :presence => true, :inclusion => {
+ in: 1..5, message: _("must be between 1 and 5")
+ }
+
+ validates :community_id, :person_id,
+ :presence => true
+
+ has_one :comment
+
+ def self.average_rating community_id
+ average = CommunityRating.where(community_id: community_id).average(:value)
+
+ if average
+ (average - average.truncate) >= 0.5 ? average.ceil : average.floor
+ else
+ nil
+ end
+ end
+end
diff --git a/plugins/communities_ratings/lib/create_community_rating_comment.rb b/plugins/communities_ratings/lib/create_community_rating_comment.rb
new file mode 100644
index 0000000..07a8a6b
--- /dev/null
+++ b/plugins/communities_ratings/lib/create_community_rating_comment.rb
@@ -0,0 +1,101 @@
+class CreateCommunityRatingComment < Task
+ include Rails.application.routes.url_helpers
+
+ validates_presence_of :requestor_id, :community_rating, :target_id
+
+ attr_accessible :community_rating, :source, :body, :requestor, :reject_explanation, :organization
+ belongs_to :source, :class_name => 'Community', :foreign_key => :source_id
+ belongs_to :community_rating
+
+ alias :organization :target
+ alias :organization= :target=
+
+ DATA_FIELDS = ['body']
+ DATA_FIELDS.each do |field|
+ settings_items field.to_sym
+ end
+
+
+ def perform
+ comment = Comment.create!(:source => self.source, :body => self.body, :author => self.requestor)
+
+ self.community_rating.comment = comment
+ self.community_rating.save!
+ end
+
+ def title
+ _("New Comment")
+ end
+
+ def information
+ message = _("
") %
+ {:requestor => self.requestor.name, :source => self.source.name, :body => self.body }
+
+ {:message => message}
+ end
+
+ def reject_details
+ true
+ end
+
+ def icon
+ {:type => :profile_image, :profile => requestor, :url => requestor.url}
+ end
+
+ # tells if this request was rejected
+ def rejected?
+ self.status == Task::Status::CANCELLED
+ end
+
+ # tells if this request was appoved
+ def approved?
+ self.status == Task::Status::FINISHED
+ end
+
+ def target_notification_description
+ _('%{requestor} wants to create a comment in the \"%{source}\" community') %
+ {:requestor => self.requestor.name, :source => self.source.name }
+ end
+
+ def target_notification_message
+ _("User \"%{user}\" just requested to create a comment in the \"%{source}\" community.
+ You have to approve or reject it through the \"Pending Validations\"
+ section in your control panel.\n") %
+ { :user => self.requestor.name, :source => self.source.name }
+ end
+
+ def task_created_message
+
+ _("Your request for commenting at %{source} was
+ just sent. Environment administrator will receive it and will approve or
+ reject your request according to his methods and criteria.
+
+ You will be notified as soon as environment administrator has a position
+ about your request.") %
+ { :source => self.source.name }
+ end
+
+ def task_cancelled_message
+ _("Your request for commenting at %{source} was
+ not approved by the environment administrator. The following explanation
+ was given: \n\n%{explanation}") %
+ { :source => self.source.name,
+ :explanation => self.reject_explanation }
+ end
+
+ def task_finished_message
+ _('Your request for commenting was approved.
+ You can access %{url} to see your comment.') %
+ { :url => mount_url }
+ end
+
+ private
+
+ def mount_url
+ identifier = self.source.identifier
+ # The use of url_for doesn't allow the /social within the Public Software
+ # portal. That's why the url is mounted so 'hard coded'
+ url = "#{organization.top_url}/profile/#{identifier}"
+ end
+
+end
diff --git a/plugins/communities_ratings/lib/ext/comments.rb b/plugins/communities_ratings/lib/ext/comments.rb
new file mode 100644
index 0000000..3a14edd
--- /dev/null
+++ b/plugins/communities_ratings/lib/ext/comments.rb
@@ -0,0 +1,8 @@
+require_dependency "comment"
+
+Comment.class_eval do
+ alias :community :source
+ alias :community= :source=
+
+ belongs_to :community_rating
+end
diff --git a/plugins/communities_ratings/lib/ext/community.rb b/plugins/communities_ratings/lib/ext/community.rb
new file mode 100644
index 0000000..d89ca6a
--- /dev/null
+++ b/plugins/communities_ratings/lib/ext/community.rb
@@ -0,0 +1,7 @@
+require_dependency 'community'
+
+Community.class_eval do
+ has_many :community_ratings
+
+ has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc'
+end
diff --git a/plugins/communities_ratings/lib/ext/environment.rb b/plugins/communities_ratings/lib/ext/environment.rb
new file mode 100644
index 0000000..a38f958
--- /dev/null
+++ b/plugins/communities_ratings/lib/ext/environment.rb
@@ -0,0 +1,35 @@
+require_dependency 'environment'
+
+Environment.class_eval do
+ attr_accessible :communities_ratings_cooldown, :communities_ratings_default_rating, :communities_ratings_order, :communities_ratings_per_page, :communities_ratings_vote_once, :communities_ratings_are_moderated
+
+ COMMUNITIES_RATINGS_ORDER_OPTIONS = ["Most Recent", "Best Ratings"]
+ COMMUNITIES_RATINGS_MINIMUM_RATING = 1
+ COMMUNITIES_RATINGS_MAX_COOLDOWN = 1000
+
+ validates :communities_ratings_default_rating,
+ :presence => true, :numericality => {
+ greater_than_or_equal_to: COMMUNITIES_RATINGS_MINIMUM_RATING,
+ less_than_or_equal_to: 5
+ }
+
+ validates :communities_ratings_cooldown,
+ :presence => true, :numericality => {
+ greater_than_or_equal_to: 0,
+ less_than_or_equal_to: COMMUNITIES_RATINGS_MAX_COOLDOWN
+ }
+
+ validates :communities_ratings_per_page,
+ :presence => true, :numericality => {
+ :greater_than_or_equal_to => 5,
+ :less_than_or_equal_to => 20
+ }
+
+ def self.communities_ratings_min_rating
+ COMMUNITIES_RATINGS_MINIMUM_RATING
+ end
+
+ def self.communities_ratings_order_options
+ COMMUNITIES_RATINGS_ORDER_OPTIONS
+ end
+end
diff --git a/plugins/communities_ratings/lib/ext/person.rb b/plugins/communities_ratings/lib/ext/person.rb
new file mode 100644
index 0000000..f0839f7
--- /dev/null
+++ b/plugins/communities_ratings/lib/ext/person.rb
@@ -0,0 +1,5 @@
+require_dependency 'person'
+
+Person.class_eval do
+ has_many :community_ratings
+end
diff --git a/plugins/communities_ratings/lib/ratings_helper.rb b/plugins/communities_ratings/lib/ratings_helper.rb
new file mode 100644
index 0000000..1692a91
--- /dev/null
+++ b/plugins/communities_ratings/lib/ratings_helper.rb
@@ -0,0 +1,10 @@
+module RatingsHelper
+
+ def get_ratings (profile_id)
+ if Environment.default.communities_ratings_order.downcase == ("best ratings")
+ ratings = CommunityRating.where(community_id: profile_id).order("value DESC")
+ else
+ ratings = CommunityRating.where(community_id: profile_id).order("created_at DESC")
+ end
+ end
+end
\ No newline at end of file
diff --git a/plugins/communities_ratings/public/comunities_rating_management.js b/plugins/communities_ratings/public/comunities_rating_management.js
new file mode 100644
index 0000000..6281b6d
--- /dev/null
+++ b/plugins/communities_ratings/public/comunities_rating_management.js
@@ -0,0 +1,35 @@
+(function($) {
+ "use strict";
+
+ var VoteOnce = {
+ init: function() {
+ this.cacheDom();
+ this.setEvents();
+ },
+
+
+ cacheDom: function() {
+ this.$vote_once_checkbox = $("#environment_communities_ratings_vote_once");
+ this.$hours_timer_input = $("#environment_communities_ratings_cooldown");
+ },
+
+
+ setEvents: function() {
+ this.$vote_once_checkbox.on("click", this.verifyHoursTimerDisable.bind(this));
+ },
+
+
+ verifyHoursTimerDisable: function() {
+ if (this.$vote_once_checkbox.is(":checked")) {
+ this.$hours_timer_input.attr("disabled", "disabled");
+ } else {
+ this.$hours_timer_input.removeAttr("disabled");
+ }
+ }
+ }
+
+
+ $(document).ready(function() {
+ VoteOnce.init();
+ });
+}) (jQuery);
diff --git a/plugins/communities_ratings/public/images/small-star-negative.png b/plugins/communities_ratings/public/images/small-star-negative.png
new file mode 100644
index 0000000..eabea40
Binary files /dev/null and b/plugins/communities_ratings/public/images/small-star-negative.png differ
diff --git a/plugins/communities_ratings/public/images/small-star-positive.png b/plugins/communities_ratings/public/images/small-star-positive.png
new file mode 100644
index 0000000..febf0de
Binary files /dev/null and b/plugins/communities_ratings/public/images/small-star-positive.png differ
diff --git a/plugins/communities_ratings/public/images/star-negative-medium.png b/plugins/communities_ratings/public/images/star-negative-medium.png
new file mode 100644
index 0000000..41973e7
Binary files /dev/null and b/plugins/communities_ratings/public/images/star-negative-medium.png differ
diff --git a/plugins/communities_ratings/public/images/star-negative.png b/plugins/communities_ratings/public/images/star-negative.png
new file mode 100644
index 0000000..41973e7
Binary files /dev/null and b/plugins/communities_ratings/public/images/star-negative.png differ
diff --git a/plugins/communities_ratings/public/images/star-positive-medium.png b/plugins/communities_ratings/public/images/star-positive-medium.png
new file mode 100644
index 0000000..ca15335
Binary files /dev/null and b/plugins/communities_ratings/public/images/star-positive-medium.png differ
diff --git a/plugins/communities_ratings/public/images/star-positive.png b/plugins/communities_ratings/public/images/star-positive.png
new file mode 100644
index 0000000..ca15335
Binary files /dev/null and b/plugins/communities_ratings/public/images/star-positive.png differ
diff --git a/plugins/communities_ratings/public/images/user-not-logged.png b/plugins/communities_ratings/public/images/user-not-logged.png
new file mode 100644
index 0000000..7b433a4
Binary files /dev/null and b/plugins/communities_ratings/public/images/user-not-logged.png differ
diff --git a/plugins/communities_ratings/public/rate.js b/plugins/communities_ratings/public/rate.js
new file mode 100644
index 0000000..3094ad6
--- /dev/null
+++ b/plugins/communities_ratings/public/rate.js
@@ -0,0 +1,122 @@
+;(function($, undefined) {
+ "use strict";
+
+ /*
+ * All global data that are used in the stars feature.
+ */
+ var DATA = {
+ selected_rate: 0, // The actual selected star when the user click on a star
+ MAXIMUM_STARS: 5, // (const) The maximum number of allowed stars
+ MINIMUM_STARS: 1, // (const) The minimum number of allowed stars
+ DATA_RATE_ATTRIBUTE: "data-star-rate", // (const) The data attribute with the star rate
+ NOT_SELECTED_VALUE: 0 // (const) The value when there is no selected rate
+ }
+
+
+ /*
+ * Prepare the global data that are variable.
+ * If the user already rated the community, set the selected_rate as the rated value
+ */
+ function set_global_data() {
+ var selected_rate = parseInt($("#selected-star-rate").val());
+ var MINIMUM_STARS = parseInt($("#MINIMUM_STARS").val());
+ DATA.selected_rate = selected_rate;
+ DATA.MINIMUM_STARS = MINIMUM_STARS;
+ }
+
+
+ /*
+ * Given a start rate, an end rate and the elements, it makes a regex that filter
+ * the elements by the given range and returns it.
+ */
+ function star_filter(start, end, elements) {
+ var test_regex = undefined;
+
+ // Verify if it is a valid range and makes its range regex: /[start-end]/
+ if (end >= start) {
+ test_regex = new RegExp("["+(start)+"-"+(end)+"]");
+ } else {
+ // If the range is invalid, make a regex that will return no element
+ test_regex = new RegExp("[]");
+ }
+
+ // Filter the elements that are in the given range
+ var result = elements.filter(function(i, element) {
+ var rate = parseInt(element.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
+
+ return test_regex.test(rate);
+ });
+
+ return result;
+ }
+
+
+ /*
+ * Show or hide the stars depending on the mouse position and the limit rate.
+ * Given the mouseover rate, the limit rate and the css classes to be swapped,
+ *
+ * It verify if the user already selected a star rate:
+ * If true:
+ * It swap the css classes from the selected star up to the given limit rate
+ * If false:
+ * It swap the css classes from the minimum rate up to the mouseover rate
+ */
+ function change_stars_class(rate_mouseover, limit_rate, remove_class, add_class) {
+ var previous_stars = undefined;
+
+ // The default not selected rate value is 0 and minimum is 1.
+ if (DATA.selected_rate >= DATA.MINIMUM_STARS) {
+ previous_stars = star_filter(DATA.selected_rate+1, limit_rate, $("."+remove_class));
+ } else {
+ previous_stars = star_filter(DATA.MINIMUM_STARS, rate_mouseover, $("."+remove_class));
+ }
+
+ previous_stars.switchClass(remove_class, add_class);
+ }
+
+
+ /*
+ * Sets the stars mouse events.
+ */
+ function set_star_hover_actions() {
+ $(".star-negative, .star-positive")
+ .on("mouseover", function() { // On mouse over, show the current rate star
+ var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
+
+ change_stars_class(rate_mouseover, rate_mouseover, "star-negative", "star-positive");
+ })
+
+ .on("mouseout", function() { // On mouse out, hide the stars
+ var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
+
+ change_stars_class(rate_mouseover, DATA.MAXIMUM_STARS, "star-positive", "star-negative");
+ })
+
+ .on("click", function() { // On mouse click, set the selected star rate
+ var rate_mouseover = parseInt(this.getAttribute(DATA.DATA_RATE_ATTRIBUTE));
+
+ // If the new rate is different from actual, update it
+ if (rate_mouseover !== DATA.selected_rate && rate_mouseover > DATA.MINIMUM_STARS) {
+ DATA.selected_rate = rate_mouseover;
+ } else { // or else, uncheck it
+ DATA.selected_rate = DATA.MINIMUM_STARS;
+ }
+
+ // Mark the selected_rate
+ $("#selected-star-rate").val(DATA.selected_rate);
+
+ var star_notice = $(".star-notice");
+ star_notice.find("span").html(DATA.selected_rate);
+ star_notice.removeClass("star-hide");
+ });
+ }
+
+
+ /*
+ * When the page DOM is ready, set all the stars events
+ */
+ $(document).ready(function() {
+ set_global_data();
+ set_star_hover_actions();
+ });
+}) (jQuery);
diff --git a/plugins/communities_ratings/style.css b/plugins/communities_ratings/style.css
new file mode 100644
index 0000000..565d2b5
--- /dev/null
+++ b/plugins/communities_ratings/style.css
@@ -0,0 +1,196 @@
+.star-container {
+ width: 100%;
+ height: 20px;
+}
+
+.star-negative, .star-positive {
+ width: 20px;
+ height: 20px;
+ background-repeat: no-repeat;
+ margin-right: 2px;
+ position: relative;
+ float: left;
+ cursor: pointer;
+}
+
+.star-negative {
+ background-image: url('public/images/star-negative.png');
+}
+
+.star-positive {
+ background-image: url('public/images/star-positive.png');
+}
+
+.small-star-negative, .small-star-positive {
+ background-repeat: no-repeat;
+ float: left;
+ height: 15px;
+ margin-right: 2px;
+ position: relative;
+ width: 15px;
+}
+
+.small-star-negative {
+ background-image: url('public/images/small-star-negative.png');
+}
+
+.small-star-positive {
+ background-image: url('public/images/small-star-positive.png');
+}
+
+.medium-star-negative, .medium-star-positive {
+ background-repeat: no-repeat;
+ float: left;
+ height: 20px;
+ margin-right: 2px;
+ position: relative;
+ width: 20px;
+}
+
+.medium-star-positive {
+ background-image: url('public/images/star-positive-medium.png');
+}
+
+.medium-star-negative {
+ background-image: url('public/images/star-negative-medium.png');
+}
+
+.star-hide {
+ display: none;
+}
+
+.community-average-rating-container {
+ border-top: 1px dotted #D3D6DE;
+ margin-top: 20px;
+ padding-top: 10px;
+}
+
+.community-average-rating-container .star-rate-text {
+ float: left;
+ margin-right: 10px;
+ padding-top: 5px;
+}
+
+.community-average-rating-container .rating-invitation {
+ font-size: 14px;
+ float: left;
+ margin-right: 10px;
+ padding-top: 3px;
+}
+
+.community-average-rating-container .star-container {
+ float: left;
+ width: 120px;
+}
+
+.community-average-rating-container .rate-this-community {
+ border-left: 1px dotted #D3D6DE;
+ float: left;
+ padding: 4px 0px 2px 10px;
+}
+
+.star-rate-data {
+ width: 100%;
+ padding-top: 20px;
+ position: relative;
+ overflow: auto;
+}
+
+.star-profile-information, .star-rate-form {
+ display: table-cell;
+ vertical-align: top;
+ width: 362px;
+}
+
+.star-profile-information {
+ width: 134px;
+}
+
+.star-rate-form {
+ display: table-cell;
+ vertical-align: top;
+}
+
+.star-profile-image, .star-profile-name {
+ text-align: center;
+}
+
+.star-profile-name {
+ word-break: break-word;
+ margin: auto;
+ margin-top: 5px;
+ width: 66px;
+}
+
+.star-rate-data .star-rate-form .star-comment-container .formfield textarea {
+ width: 361px;
+}
+
+/************* Users ratings list ****************/
+
+.ratings-list .user-rating-block,
+.ratings-list .make-report-block {
+ border-top: 1px solid #D3D6DE;
+ margin-top: 25px;
+ padding-top: 20px;
+}
+
+.ratings-list .make-report-block {
+ padding-bottom: 25px;
+}
+
+.ratings-list .see-more{
+ border-top: 1px solid #D3D6DE;
+}
+.ratings-list .user-rating-block .user-testimony-container {
+ display: table-cell;
+ padding-left: 20px;
+}
+
+.ratings-list .make-report-block .make-report-container {
+ display: table-cell;
+}
+
+.ratings-list .user-rating-block .user-testimony-container .star-container {
+ display: table-cell;
+}
+
+.ratings-list .user-rating-block .user-testimony-container .testimony-rate-date {
+ display: table-cell;
+ max-width: 95px;
+ min-width: 95px;
+ padding-right: 160px;
+ white-space: nowrap;
+}
+
+.ratings-list .user-rating-block .user-testimony-container .user-testimony {
+ margin-top: 10px;
+ word-break: break-word;
+}
+
+.ratings-list .make-report-block .make-report-container .make-report-message {
+ font-size: 14px;
+ font-style: italic;
+ word-break: break-word;
+}
+
+.ratings-list .make-report-block .make-report-container .button-bar {
+ overflow: auto;
+ padding-top: 15px;
+}
+
+.ratings-list .user-rating-block .star-profile-information {
+ border-right: 1px dotted #D3D6DE;
+}
+
+.ratings-list .icon-arrow-right-p {
+ background: url(/designs/themes/base/imgs/arrow-right-p.png) 100% 50% no-repeat;
+ display: block;
+ float: right;
+ margin-top: 20px;
+ padding-right: 15px;
+}
+
+.task_information .comment {
+ padding-left: 60px;
+}
\ No newline at end of file
diff --git a/plugins/communities_ratings/test/functional/communities_ratings_plugin_admin_controller_test.rb b/plugins/communities_ratings/test/functional/communities_ratings_plugin_admin_controller_test.rb
new file mode 100644
index 0000000..06e1394
--- /dev/null
+++ b/plugins/communities_ratings/test/functional/communities_ratings_plugin_admin_controller_test.rb
@@ -0,0 +1,49 @@
+require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
+require File.expand_path(File.dirname(__FILE__)) + '/../../controllers/communities_ratings_plugin_admin_controller'
+
+# Re-raise errors caught by the controller.
+class CommunitiesRatingsPluginAdminController; def rescue_action(e) raise e end; end
+
+class CommunitiesRatingsPluginAdminControllerTest < ActionController::TestCase
+
+ def setup
+ @controller = CommunitiesRatingsPluginAdminController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ @environment = Environment.default
+ @environment.enabled_plugins = ['CommunitiesRatingsPlugin']
+ @environment.save
+
+ @community = Community.create(:name => "TestCommunity")
+
+ login_as(create_admin_user(@environment))
+ end
+
+ test "should update communities rating plugin configuration" do
+ post :update, :environment => { :communities_ratings_default_rating => 5,
+ :communities_ratings_cooldown => 12,
+ :communities_ratings_order => "Most Recent",
+ :communities_ratings_per_page => 10,
+ :communities_ratings_vote_once => true }
+
+ assert :success
+ @environment.reload
+ assert_equal 5, @environment.communities_ratings_default_rating
+ assert_equal "Configuration updated successfully.", session[:notice]
+ end
+
+ test "should not update communities rating plugin configuration with wrong cooldown time" do
+ post :update, :environment => { :communities_ratings_default_rating => 5,
+ :communities_ratings_cooldown => -50,
+ :communities_ratings_order => "Most Recent",
+ :communities_ratings_per_page => 10,
+ :communities_ratings_vote_once => true }
+
+ assert :success
+ @environment.reload
+ assert_equal 24, @environment.communities_ratings_cooldown
+ assert_equal "Configuration could not be saved.", session[:notice]
+ end
+end
+
diff --git a/plugins/communities_ratings/test/functional/communities_ratings_plugin_profile_controller_test.rb b/plugins/communities_ratings/test/functional/communities_ratings_plugin_profile_controller_test.rb
new file mode 100644
index 0000000..3ee14c2
--- /dev/null
+++ b/plugins/communities_ratings/test/functional/communities_ratings_plugin_profile_controller_test.rb
@@ -0,0 +1,65 @@
+require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
+require File.expand_path(File.dirname(__FILE__)) + '/../../controllers/communities_ratings_plugin_profile_controller'
+
+# Re-raise errors caught by the controller.
+class CommunitiesRatingsPluginProfileController; def rescue_action(e) raise e end; end
+
+class CommunitiesRatingsPluginProfileControllerTest < ActionController::TestCase
+
+ def setup
+ @controller = CommunitiesRatingsPluginProfileController.new
+ @request = ActionController::TestRequest.new
+ @response = ActionController::TestResponse.new
+
+ @environment = Environment.default
+ @environment.enabled_plugins = ['CommunitiesRatingsPlugin']
+ @environment.save
+
+ @person = create_user('testuser').person
+ @community = Community.create(:name => "TestCommunity")
+
+ login_as(@person.identifier)
+ @controller.stubs(:logged_in?).returns(true)
+ @controller.stubs(:current_user).returns(@person.user)
+ end
+
+ test "should add new comment to community" do
+ post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test"}, :community_rating_value => 4
+ assert_equal "#{@community.name} successfully rated!", session[:notice]
+ end
+
+ test "Create community_rating without comment body" do
+ post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :community_rating_value => 2
+
+ assert_equal "#{@community.name} successfully rated!", session[:notice]
+ end
+
+ test "Do not create community_rating without a rate value" do
+ post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :community_rating_value => nil
+
+ assert_equal "Sorry, there were problems rating this profile.", session[:notice]
+ end
+
+ test "do not create two ratings when environment vote once is true" do
+ @environment.communities_ratings_vote_once = true
+ @environment.save
+ post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test"}, :community_rating_value => 3
+
+ assert_equal "#{@community.name} successfully rated!", session[:notice]
+
+ post :new_rating, profile: @community.identifier, :comments => {:body => "This is a test 2"}, :community_rating_value => 3
+ assert_equal "You cant vote on this community", session[:notice]
+ end
+
+ test "Display unavailable rating message for users that must wait the rating cooldown time" do
+ post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :community_rating_value => 3
+ assert_not_match(/The administrators set the minimum time of/, @response.body)
+ valid_rating = CommunityRating.last
+
+ post :new_rating, profile: @community.identifier, :comments => {:body => ""}, :community_rating_value => 3
+ assert_match(/The administrators set the minimum time of/, @response.body)
+ new_rating = CommunityRating.last
+
+ assert_equal valid_rating.id, new_rating.id
+ end
+end
diff --git a/plugins/communities_ratings/test/unit/community_rating_test.rb b/plugins/communities_ratings/test/unit/community_rating_test.rb
new file mode 100644
index 0000000..671b6c1
--- /dev/null
+++ b/plugins/communities_ratings/test/unit/community_rating_test.rb
@@ -0,0 +1,65 @@
+require 'test_helper'
+
+class CommunityRatingTest < ActiveSupport::TestCase
+ test "The value must be between 1 and 5" do
+ community_rating1 = CommunityRating.new :value => -1
+ community_rating2 = CommunityRating.new :value => 6
+
+ assert_equal false, community_rating1.valid?
+ assert_equal false, community_rating2.valid?
+
+ assert_equal true, community_rating1.errors[:value].include?("must be between 1 and 5")
+ assert_equal true, community_rating2.errors[:value].include?("must be between 1 and 5")
+
+ community_rating1.value = 1
+ community_rating1.valid?
+
+ community_rating2.value = 5
+ community_rating2.valid?
+
+ assert_equal false, community_rating1.errors[:value].include?("must be between 1 and 5")
+ assert_equal false, community_rating2.errors[:value].include?("must be between 1 and 5")
+ end
+
+ test "Create task for create a rating comment" do
+ person = create_user('molly').person
+ person.email = "person@email.com"
+ person.save!
+
+ community = fast_create(Community)
+ community.add_admin(person)
+
+ community_rating = CommunityRating.create!(
+ :value => 3,
+ :person => person,
+ :community => community
+ )
+
+ create_community_rating_comment = CreateCommunityRatingComment.create!(
+ :requestor => person,
+ :source => community,
+ :community_rating => community_rating,
+ :organization => community
+ )
+
+ assert community.tasks.include?(create_community_rating_comment)
+ end
+
+ test "Should calculate community's rating average" do
+ community = fast_create Community
+ p1 = fast_create Person, :name=>"Person 1"
+ p2 = fast_create Person, :name=>"Person 2"
+ p3 = fast_create Person, :name=>"Person 3"
+
+ CommunityRating.create! :value => 2, :community => community, :person => p1
+ CommunityRating.create! :value => 3, :community => community, :person => p2
+ CommunityRating.create! :value => 5, :community => community, :person => p3
+
+ assert_equal 3, CommunityRating.average_rating(community)
+
+ p4 = fast_create Person, :name=>"Person 4"
+ CommunityRating.create! :value => 4, :community => community, :person => p4
+
+ assert_equal 4, CommunityRating.average_rating(community)
+ end
+end
diff --git a/plugins/communities_ratings/test/unit/environment_test.rb b/plugins/communities_ratings/test/unit/environment_test.rb
new file mode 100644
index 0000000..6af365a
--- /dev/null
+++ b/plugins/communities_ratings/test/unit/environment_test.rb
@@ -0,0 +1,34 @@
+require 'test_helper'
+
+class EnvironmentTest < ActiveSupport::TestCase
+ test "Communities ratings default rating validation" do
+ environment = Environment.new :communities_ratings_default_rating => 0
+ environment.valid?
+
+ assert_equal "must be greater than or equal to 1", environment.errors[:communities_ratings_default_rating].first
+
+ environment.communities_ratings_default_rating = 6
+ environment.valid?
+
+ assert_equal "must be less than or equal to 5", environment.errors[:communities_ratings_default_rating].first
+ end
+
+ test "Communities ratings cooldown validation" do
+ environment = Environment.new :communities_ratings_cooldown => -1
+ environment.valid?
+
+ assert_equal "must be greater than or equal to 0", environment.errors[:communities_ratings_cooldown].first
+ end
+
+ test "communities ratings per page validation" do
+ environment = Environment.new :communities_ratings_per_page => 4
+ environment.valid?
+
+ assert_equal "must be greater than or equal to 5", environment.errors[:communities_ratings_per_page].first
+
+ environment.communities_ratings_per_page = 21
+ environment.valid?
+
+ assert_equal "must be less than or equal to 20", environment.errors[:communities_ratings_per_page].first
+ end
+end
diff --git a/plugins/communities_ratings/test/unit/ratings_helper_test.rb b/plugins/communities_ratings/test/unit/ratings_helper_test.rb
new file mode 100644
index 0000000..9a28638
--- /dev/null
+++ b/plugins/communities_ratings/test/unit/ratings_helper_test.rb
@@ -0,0 +1,62 @@
+require File.expand_path(File.dirname(__FILE__)) + '/../../../../test/test_helper'
+require 'ratings_helper'
+
+class RatingsHelperTest < ActiveSupport::TestCase
+ include RatingsHelper
+
+ def setup
+
+ @environment = Environment.default
+ @environment.enabled_plugins = ['CommunitiesRatingsPlugin']
+ @environment.save
+ @person = create_user('testuser').person
+ @community = Community.create(:name => "TestCommunity")
+ end
+
+ should "get the ratings of a community ordered by most recent ratings" do
+ ratings_array = []
+
+ first_rating = CommunityRating.new
+ first_rating.community = @community
+ first_rating.person = @person
+ first_rating.value = 3
+ first_rating.save
+
+ most_recent_rating = CommunityRating.new
+ most_recent_rating.community = @community
+ most_recent_rating.person = @person
+ most_recent_rating.value = 5
+ sleep 2
+ most_recent_rating.save
+
+ ratings_array << most_recent_rating
+ ratings_array << first_rating
+
+ assert_equal @environment.communities_ratings_order, "most recent"
+ assert_equal ratings_array, get_ratings(@community.id)
+ end
+
+ should "get the ratings of a community ordered by best ratings" do
+ ratings_array = []
+ @environment.communities_ratings_order = "best ratings"
+ @environment.save
+
+ first_rating = CommunityRating.new
+ first_rating.community = @community
+ first_rating.person = @person
+ first_rating.value = 3
+ first_rating.save
+
+ second_rating = CommunityRating.new
+ second_rating.community = @community
+ second_rating.person = @person
+ second_rating.value = 5
+ sleep 2
+ second_rating.save
+
+ ratings_array << second_rating
+ ratings_array << first_rating
+
+ assert_equal ratings_array, get_ratings(@community.id)
+ end
+end
diff --git a/plugins/communities_ratings/views/blocks/communities_ratings_block.html.erb b/plugins/communities_ratings/views/blocks/communities_ratings_block.html.erb
new file mode 100644
index 0000000..4d93e70
--- /dev/null
+++ b/plugins/communities_ratings/views/blocks/communities_ratings_block.html.erb
@@ -0,0 +1,21 @@
+
+ <%= block_title(block.title) %>
+ <% if block.get_ratings(block.owner.id).empty? %>
+
+ <%= _("This community does not have any ratings") %>
+ <%= render :partial => 'shared/make_report_block' %>
+
+ <% else %>
+
+ <% block.get_ratings(block.owner.id).each_with_index do |r, index| %>
+ <% break if index >= block.limit_number_of_ratings %>
+ <%= render :partial => "shared/user_rating_container", :locals => {:user_rate => r} %>
+ <% end %>
+
+ <%= render :partial => 'shared/make_report_block' %>
+
+
+ <%= link_to _('See more'), url_for(:controller => 'communities_ratings_plugin_profile', :action => 'new_rating'), :class => 'icon-arrow-right-p' %>
+
+<% end %>
+
diff --git a/plugins/communities_ratings/views/communities_ratings_plugin_admin/index.html.erb b/plugins/communities_ratings/views/communities_ratings_plugin_admin/index.html.erb
new file mode 100644
index 0000000..e4b9dfb
--- /dev/null
+++ b/plugins/communities_ratings/views/communities_ratings_plugin_admin/index.html.erb
@@ -0,0 +1,53 @@
+
<%= _("Communities Rating Management") %>
+
+<%= labelled_form_for(:environment, :url => {:action => 'update'}) do |f| %>
+
+
+ <%= c_('Configuration') %> |
+ <%= _('Value') %> |
+
+
+
+ <%= _('Default amount of stars marked on evaluations') %> |
+ <%= select :environment, :communities_ratings_default_rating, (Environment.communities_ratings_min_rating)..5 %> |
+
+
+
+ <%= _('Can only vote for one community once') %> |
+ <%= check_box :environment, :communities_ratings_vote_once %> |
+
+
+ <%= _('The comments are moderated') %> |
+ <%= check_box :environment, :communities_ratings_are_moderated %> |
+
+
+ <%= _('Time cooldown between evaluations from the same user') %> |
+
+ <% hours_options = {size: 1} %>
+ <% hours_options[:disabled] = "disabled" if environment.communities_ratings_vote_once %>
+ <%= text_field :environment, :communities_ratings_cooldown, hours_options %>
+ <%= _('hours') %>
+ |
+
+
+
+ <%= _('Order ratings by') %> |
+ <%= select :environment, :communities_ratings_order, (Environment.communities_ratings_order_options) %> |
+
+
+
+ <%= _('Ratings per page') %> |
+
+ <%= select :environment, :communities_ratings_per_page, 5..20 %>
+ |
+
+
+
+
+ <% button_bar do %>
+ <%= submit_button('save', c_('Save changes')) %>
+ <%= button :back, _('Back'), :controller => 'plugins' %>
+ <% end %>
+
+
+<% end %>
diff --git a/plugins/communities_ratings/views/communities_ratings_plugin_profile/_new_rating_fields.html.erb b/plugins/communities_ratings/views/communities_ratings_plugin_profile/_new_rating_fields.html.erb
new file mode 100644
index 0000000..783c0f4
--- /dev/null
+++ b/plugins/communities_ratings/views/communities_ratings_plugin_profile/_new_rating_fields.html.erb
@@ -0,0 +1,79 @@
+
+ <%= @plugins.dispatch(:communities_ratings_title).collect { |content| instance_exec(&content) }.join("") %>
+
+
+
+
+
+
+ <% if @rating_available %>
+
+
\ No newline at end of file
diff --git a/plugins/communities_ratings/views/communities_ratings_plugin_profile/new_rating.html.erb b/plugins/communities_ratings/views/communities_ratings_plugin_profile/new_rating.html.erb
new file mode 100644
index 0000000..b9da0ca
--- /dev/null
+++ b/plugins/communities_ratings/views/communities_ratings_plugin_profile/new_rating.html.erb
@@ -0,0 +1,17 @@
+<% if logged_in? %>
+ <%= render :partial => "new_rating_fields" %>
+<% else %>
+
+ <%= render :partial => "shared/make_report_block" %>
+
+<% end %>
+
+
+ <% @users_ratings.each do |user_rate| %>
+ <%= render :partial => "shared/user_rating_container", :locals => {:user_rate => user_rate} %>
+ <% end %>
+
+
+
\ No newline at end of file
diff --git a/plugins/communities_ratings/views/hotspots/display_community_average_rating.html.erb b/plugins/communities_ratings/views/hotspots/display_community_average_rating.html.erb
new file mode 100644
index 0000000..d0dc51e
--- /dev/null
+++ b/plugins/communities_ratings/views/hotspots/display_community_average_rating.html.erb
@@ -0,0 +1,25 @@
+
\ No newline at end of file
diff --git a/plugins/communities_ratings/views/shared/_make_report_block.html.erb b/plugins/communities_ratings/views/shared/_make_report_block.html.erb
new file mode 100644
index 0000000..9654e6e
--- /dev/null
+++ b/plugins/communities_ratings/views/shared/_make_report_block.html.erb
@@ -0,0 +1,28 @@
+<% logged_in_image = profile_image(current_user.person, :portrait) if current_user %>
+<% logged_out_image = image_tag('plugins/communities_ratings/public/images/user-not-logged.png') %>
+
+
+
+
+
+
+ <%= _('Report your experiences.') %>
+
+
+ <%= render :partial => 'shared/rating_button', :locals => { :disabled => false } %>
+
+ <% unless logged_in? %>
+
+ <%= _('* You must be logged in to submit a report.') %>
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/plugins/communities_ratings/views/shared/_rating_button.html.erb b/plugins/communities_ratings/views/shared/_rating_button.html.erb
new file mode 100644
index 0000000..57627a0
--- /dev/null
+++ b/plugins/communities_ratings/views/shared/_rating_button.html.erb
@@ -0,0 +1,9 @@
+
+ <% options = disabled ? {:disabled => 'disabled', :class => 'disabled-button'} : {} %>
+
+ <% if logged_in? %>
+ <%= button('rate',_('Rate Community'), {:controller => 'communities_ratings_plugin_profile', :action => 'new_rating'}, options) %>
+ <% else %>
+ <%= button('rate',_('Rate Community'), {:controller => 'account', :action => 'login'}, options) %>
+ <% end %>
+
\ No newline at end of file
diff --git a/plugins/communities_ratings/views/shared/_user_rating_container.html.erb b/plugins/communities_ratings/views/shared/_user_rating_container.html.erb
new file mode 100644
index 0000000..935ee77
--- /dev/null
+++ b/plugins/communities_ratings/views/shared/_user_rating_container.html.erb
@@ -0,0 +1,33 @@
+
+
+
+
+
+ <%= time_ago_in_words(user_rate.created_at) %>
+
+
+
+ <% (1..5).each do |rate_number| %>
+ <% if rate_number <= user_rate.value %>
+
+ <% else %>
+
+ <% end %>
+ <% end %>
+
+
+
+ <%= user_rate.comment.body unless user_rate.comment.nil? %>
+
+
+ <%= @plugins.dispatch(:communities_ratings_plugin_extra_fields_show_data, user_rate).collect { |content| instance_exec(&content) }.join("") %>
+
+
--
libgit2 0.21.2
Comment:
\"%{body}\"