diff --git a/Gemfile b/Gemfile index 261b71b7d..6d9bb4ada 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,7 @@ gem "coderay", "~> 1.0.6" gem "fastercsv", "~> 1.5.0", :platforms => [:mri_18, :mingw_18, :jruby] gem "builder", "3.0.0" gem 'acts-as-taggable-on' + # Optional gem for LDAP authentication group :ldap do gem "net-ldap", "~> 0.3.1" diff --git a/Gemfile.lock b/Gemfile.lock index 99f29e915..6713a9977 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -98,6 +98,8 @@ GEM rmagick (2.13.2) ruby-openid (2.1.8) rubyzip (0.9.9) + jquery-rails + rails selenium-webdriver (2.33.0) childprocess (>= 0.2.5) multi_json (~> 1.0) diff --git a/app/assets/javascripts/praise_tread.js b/app/assets/javascripts/praise_tread.js new file mode 100644 index 000000000..dee720fac --- /dev/null +++ b/app/assets/javascripts/praise_tread.js @@ -0,0 +1,2 @@ +// Place all the behaviors and hooks related to the matching controller here. +// All this logic will automatically be available in application.js. diff --git a/app/assets/javascripts/rateable/jRating.js.erb b/app/assets/javascripts/rateable/jRating.js.erb new file mode 100644 index 000000000..4f43a4f97 --- /dev/null +++ b/app/assets/javascripts/rateable/jRating.js.erb @@ -0,0 +1,225 @@ +/************************************************************************ +************************************************************************* +@Name : jRating - jQuery Plugin +@Revison : 3.0 +@Date : 28/01/2013 +@Author: ALPIXEL - (www.myjqueryplugins.com - www.alpixel.fr) +@License : Open Source - MIT License : http://www.opensource.org/licenses/mit-license.php + +************************************************************************** +*************************************************************************/ +(function($) { + $.fn.jRating = function(op) { + var defaults = { + /** String vars **/ + bigStarsPath : '<%= image_path "seems_rateable/stars.png" %>', // path of the icon stars.png + smallStarsPath : '<%= image_path "seems_rateable/small.png" %>', // path of the icon small.png + path : '<%= SeemsRateable::Engine.routes.url_helpers.ratings_path %>', + type : 'big', // can be set to 'small' or 'big' + + /** Boolean vars **/ + step:false, // if true, mouseover binded star by star, + isDisabled:false, + showRateInfo: false, + canRateAgain : false, + + /** Integer vars **/ + length:5, // number of star to display + decimalLength : 0, // number of decimals.. Max 3, but you can complete the function 'getNote' + rateMax : 20, // maximal rate - integer from 0 to 9999 (or more) + rateInfosX : -45, // relative position in X axis of the info box when mouseover + rateInfosY : 5, // relative position in Y axis of the info box when mouseover + nbRates : 1, + + /** Functions **/ + onSuccess : null, + onError : null + }; + + if(this.length>0) + return this.each(function() { + /*vars*/ + var opts = $.extend(defaults, op), + newWidth = 0, + starWidth = 0, + starHeight = 0, + bgPath = '', + hasRated = false, + globalWidth = 0, + nbOfRates = opts.nbRates; + + if($(this).hasClass('jDisabled') || opts.isDisabled) + var jDisabled = true; + else + var jDisabled = false; + + getStarWidth(); + $(this).height(starHeight); + + + + var average = parseFloat($(this).attr('data-average')), // get the average of all rates + idBox = parseInt($(this).attr('data-id')), // get the id of the box + kls = $(this).attr('data-kls'), + dimension = $(this).attr('data-dimension'), + widthRatingContainer = starWidth*opts.length, // Width of the Container + widthColor = average/opts.rateMax*widthRatingContainer, // Width of the color Container + quotient = + $('
',{ + 'class' : 'jRatingInfos', + html : getNote(relativeX)+' / '+opts.rateMax+'', + css : { + top: (e.pageY + opts.rateInfosY), + left: (e.pageX + opts.rateInfosX) + } + }).appendTo('body').show(); + }, + mouseover : function(e){ + $(this).css('cursor','pointer'); + }, + mouseout : function(){ + $(this).css('cursor','default'); + if(hasRated) average.width(globalWidth); + else average.width(0); + }, + mousemove : function(e){ + var realOffsetLeft = findRealLeft(this); + var relativeX = e.pageX - realOffsetLeft; + if(opts.step) newWidth = Math.floor(relativeX/starWidth)*starWidth + starWidth; + else newWidth = relativeX; + average.width(newWidth); + if (opts.showRateInfo) + $("p.jRatingInfos") + .css({ + left: (e.pageX + opts.rateInfosX) + }) + .html(getNote(newWidth) +' / '+opts.rateMax+''); + }, + mouseleave : function(){ + $("p.jRatingInfos").remove(); + }, + click : function(e){ + var element = this; + + /*set vars*/ + hasRated = true; + globalWidth = newWidth; + nbOfRates--; + + if(!opts.canRateAgain || parseInt(nbOfRates) <= 0) $(this).unbind().css('cursor','default').addClass('jDisabled'); + + if (opts.showRateInfo) $("p.jRatingInfos").fadeOut('fast',function(){$(this).remove();}); + e.preventDefault(); + var rate = getNote(newWidth); + average.width(newWidth); + + + $.post(defaults.path, + { + idBox : idBox, + rate : rate, + kls : kls, + dimension : dimension + /** action : 'rating' **/ + }, + function(data) { + if(!data.error) + { + /** Here you can display an alert box, + or use the jNotify Plugin :) http://www.myqjqueryplugins.com/jNotify + exemple : */ + if(opts.onSuccess) opts.onSuccess( element, rate ); + } + else + { + + /** Here you can display an alert box, + or use the jNotify Plugin :) http://www.myqjqueryplugins.com/jNotify + exemple : */ + if(opts.onError) opts.onError( element, rate ); + } + }, + 'json' + ); + } + }); + + function getNote(relativeX) { + var noteBrut = parseFloat((relativeX*100/widthRatingContainer)*opts.rateMax/100); + switch(opts.decimalLength) { + case 1 : + var note = Math.round(noteBrut*10)/10; + break; + case 2 : + var note = Math.round(noteBrut*100)/100; + break; + case 3 : + var note = Math.round(noteBrut*1000)/1000; + break; + default : + var note = Math.round(noteBrut*1)/1; + } + return note; + }; + + function getStarWidth(){ + switch(opts.type) { + case 'small' : + starWidth = 12; // width of the picture small.png + starHeight = 10; // height of the picture small.png + bgPath = opts.smallStarsPath; + break; + default : + starWidth = 23; // width of the picture stars.png + starHeight = 20; // height of the picture stars.png + bgPath = opts.bigStarsPath; + } + }; + + function findRealLeft(obj) { + if( !obj ) return 0; + return obj.offsetLeft + findRealLeft( obj.offsetParent ); + }; + }); + + } +})(jQuery); diff --git a/app/assets/javascripts/rateable/rateable.js.erb b/app/assets/javascripts/rateable/rateable.js.erb new file mode 100644 index 000000000..da6cc3097 --- /dev/null +++ b/app/assets/javascripts/rateable/rateable.js.erb @@ -0,0 +1,25 @@ +$(document).ready(function(){ + $(".rateable").jRating({ + //default options displayed below -> + + rateMax: 5, //Maximal rate + length : 5, //Number of stars + //decimalLength : 0, //Number of decimals in the rate + //type : 'big', //Big or small + //step : true, //If set to true, filling of the stars is done star by star (step by step). + //isDisabled: false, //Set true to display static rating + //showRateInfo:false, //Rate info panel, set true to display + //rateInfosX : 45, //In pixel - Absolute left position of the information box during mousemove. + //rateInfosY : 5, //In pixel - Absolute top position of the information box during mousemove. + path : '<%= SeemsRateable::Engine.routes.url_helpers.ratings_path %>', + onSuccess : function(element, rate){ + //something like -> + //alert('success'); + $('Thanks for rating!').insertAfter(element) + }, + onError : function(element, rate) { + $('You have already rated!').insertAfter(element) + } + }); + +}); diff --git a/app/assets/stylesheets/praise_tread.css b/app/assets/stylesheets/praise_tread.css new file mode 100644 index 000000000..afad32db0 --- /dev/null +++ b/app/assets/stylesheets/praise_tread.css @@ -0,0 +1,4 @@ +/* + Place all the styles related to the matching controller here. + They will automatically be included in application.css. +*/ diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 2a4b5fb53..f57983e30 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -95,6 +95,9 @@ class ApplicationController < ActionController::Base # Returns the current user or nil if no user is logged in # and starts a session if needed + def current_user + find_current_user + end def find_current_user user = nil unless api_request? diff --git a/app/controllers/praise_tread_controller.rb b/app/controllers/praise_tread_controller.rb new file mode 100644 index 000000000..528011102 --- /dev/null +++ b/app/controllers/praise_tread_controller.rb @@ -0,0 +1,68 @@ +class PraiseTreadController < ApplicationController + + def praise_plus + @obj = nil + if request.get? + @obj = params[:obj] # 传的是对象,最后变成id了 + + #首先创建或更新praise_tread 表 + @pt = PraiseTread.find_by_user_id_and_praise_tread_object_id(User.current.id,@obj) + @pt = @pt.nil? ? PraiseTread.new : @pt + + @pt.user_id = User.current.id + @pt.praise_tread_object_id = @obj.to_i + @pt.praise_tread_object_type = User.find_by_id(@obj).class.name.underscore + @pt.praise_or_tread = 1 + @pt.save + + #再创建或更新praise_tread_cache表 + @ptc = PraiseTreadCache.find_by_object_id(@obj) + @ptc = @ptc.nil? ? PraiseTreadCache.new : @ptc + @ptc.object_id = @obj.to_i + @ptc.object_type = User.find_by_id(@obj).class.name.underscore + @ptc.plus(1) + @ptc.save + end + @obj = User.find_by_id(@obj) + respond_to do |format| + format.html + format.js + end + end + + def praise_minus + @obj = nil + if request.get? + @obj = params[:obj] # 传的是对象,最后变成id了 + + #首先更新praise_tread 表 删除关注记录 + @pt = PraiseTread.find_by_user_id_and_praise_tread_object_id_and_praise_tread_object_type(User.current.id,@obj,"user") + @pt.delete + + #再更新praise_tread_cache表 使相应的记录减1 当为0时删除 + @ptc = PraiseTreadCache.find_by_object_id(@obj) + @ptc.minus(1) + if @ptc.praise_num == 0 + @ptc.delete + end + + end + @obj = User.find_by_id(@obj) + respond_to do |format| + format.html + format.js + end + end + + def tread_plus + + end + + def tread_minus + respond_to do |format| + format.html + format.js + end + end + +end diff --git a/app/controllers/tags_controller.rb b/app/controllers/tags_controller.rb index 233a2b308..b725b9fc2 100644 --- a/app/controllers/tags_controller.rb +++ b/app/controllers/tags_controller.rb @@ -2,9 +2,7 @@ class TagsController < ApplicationController before_filter :require_admin,:only => :show - #Added by nie - #before_filter :require_login,:only => :add_tag - #end + include ProjectsHelper include IssuesHelper include UsersHelper @@ -78,5 +76,10 @@ class TagsController < ApplicationController def show end + + def show_all + @tags = ActsAsTaggableOn::Tag.find(:all) + @tags = @tags.to_a + end end diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index a93698de8..6568149d3 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -17,9 +17,13 @@ class UsersController < ApplicationController layout 'base_users' - before_filter :require_admin, :except => [:show, :index,:tag_save, :user_projects, :user_newfeedback, :user_comments, :watch_bids, :info] - before_filter :find_user, :only => [:show, :edit, :update, :destroy, :edit_membership, :destroy_membership, :user_activities, :user_projects, :user_newfeedback, :user_comments, :watch_bids, :info] + before_filter :require_admin, :except => [:show, :index,:tag_save, :user_projects, :user_newfeedback, :user_comments, :watch_bids, :info, :user_watchlist, :user_fanslist] + before_filter :find_user, :only => [:user_fanslist, :user_watchlist, :show, :edit, :update, :destroy, :edit_membership, :destroy_membership, :user_activities, :user_projects, :user_newfeedback, :user_comments, :watch_bids, :info] accept_api_auth :index, :show, :create, :update, :destroy + + #william + before_filter :require_login,:only=>[:tag_save] + helper :sort include SortHelper @@ -27,7 +31,7 @@ class UsersController < ApplicationController include CustomFieldsHelper include AvatarHelper - # added by liuping 关注 + # added by liuping 关注 helper :watchers helper :activities @@ -379,7 +383,16 @@ class UsersController < ApplicationController respond_to do |format| format.html format.js - end + end + end + + ###add by huang + def user_watchlist + + end + ###add by huang + def user_fanslist + end private diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8d14e63f7..ea87f47bf 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -26,12 +26,9 @@ module ApplicationHelper include GravatarHelper::PublicMethods include Redmine::Pagination::Helper include AvatarHelper - - ### added by william - include ActsAsTaggableOn::TagsHelper - # include WatchersHelper - - + ## added by william + include PraiseTreadHelper + extend Forwardable def_delegators :wiki_helper, :wikitoolbar_for, :heads_for_wiki_formatter @@ -1309,4 +1306,14 @@ module ApplicationHelper html.html_safe end #end +# add by huang + def show_watcher_list(user) + html = '' + for user in User.watched_by(user.id) + html << (link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :class => "avatar", :title => "#{user.name}") + end + html.html_safe + end +# end + end diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index 4ecc33690..06ea865c7 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -377,7 +377,7 @@ module IssuesHelper # this method is used to get all projects that tagged one tag # added by william def get_issues_by_tag(tag_name) - Issue.tagged_with(tag_name) + Issue.tagged_with(tag_name).by_join_date end end diff --git a/app/helpers/praise_tread_helper.rb b/app/helpers/praise_tread_helper.rb new file mode 100644 index 000000000..9b2eba969 --- /dev/null +++ b/app/helpers/praise_tread_helper.rb @@ -0,0 +1,23 @@ +module PraiseTreadHelper + #added by william + def is_praise_or_tread(object,user_id) + @obj_type = object.class.name.underscore + @obj_id = object.id + @is_praise = PraiseTread.find_by_sql("select * from praise_treads where user_id=#{user_id} and " + + "praise_tread_object_type='#{@obj_type}' and praise_tread_object_id=#{@obj_id} ") + return @is_praise + end + #end + + def get_praise_num(object) + @obj_type = object.class.name.underscore + @obj_id = object.id + @record = PraiseTreadCache.find_by_object_id_and_object_type(@obj_id,@obj_type) + if @record + return @record.praise_num + else + return 0 + end + end + +end diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index cbe57d1c7..d4738a831 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -85,7 +85,7 @@ module ProjectsHelper # this method is used to get all projects that tagged one tag # added by william def get_projects_by_tag(tag_name) - Project.tagged_with(tag_name) + Project.tagged_with(tag_name).by_join_date end end diff --git a/app/helpers/users_helper.rb b/app/helpers/users_helper.rb index 9b6f85d2a..1f32990c1 100644 --- a/app/helpers/users_helper.rb +++ b/app/helpers/users_helper.rb @@ -58,7 +58,7 @@ module UsersHelper # this method is used to get all projects that tagged one tag # added by william def get_users_by_tag(tag_name) - User.tagged_with(tag_name) + User.tagged_with(tag_name).by_join_date end end diff --git a/app/models/issue.rb b/app/models/issue.rb index 5ecadb672..8d6f6e7c5 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -60,7 +60,8 @@ class Issue < ActiveRecord::Base ###########################added by william acts_as_taggable - + scope :by_join_date, order("created_at DESC") + ##end DONE_RATIO_OPTIONS = %w(issue_field issue_status) attr_reader :current_journal diff --git a/app/models/praise_tread.rb b/app/models/praise_tread.rb new file mode 100644 index 000000000..901a31660 --- /dev/null +++ b/app/models/praise_tread.rb @@ -0,0 +1,4 @@ +class PraiseTread < ActiveRecord::Base + attr_accessible :user_id,:praise_tread_object_id,:praise_tread_object_type,:praise_or_tread + +end diff --git a/app/models/praise_tread_cache.rb b/app/models/praise_tread_cache.rb new file mode 100644 index 000000000..330e197cf --- /dev/null +++ b/app/models/praise_tread_cache.rb @@ -0,0 +1,11 @@ +class PraiseTreadCache < ActiveRecord::Base + attr_accessible :object_id,:object_type,:praise_num,:tread_num + + def plus(num) + self.update_attribute(:praise_num, self.praise_num.to_i + num) + end + + def minus(num) + self.update_attribute(:praise_num, self.praise_num.to_i - num) + end +end diff --git a/app/models/project.rb b/app/models/project.rb index 6c1be04af..47494ff31 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -78,7 +78,7 @@ class Project < ActiveRecord::Base :author => nil ############################added by william acts_as_taggable - + scope :by_join_date, order("created_at DESC") ###################added by liuping 关注 acts_as_watchable diff --git a/app/models/user.rb b/app/models/user.rb index 6e720c06d..373252e14 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -102,8 +102,8 @@ class User < Principal acts_as_customizable ############################added by william - acts_as_taggable - + acts_as_taggable + scope :by_join_date, order("created_at DESC") ############################# added by liuping 关注 acts_as_watchable diff --git a/app/views/layouts/_tag.html.erb b/app/views/layouts/_tag.html.erb index 5873c6294..e0e2b49fd 100644 --- a/app/views/layouts/_tag.html.erb +++ b/app/views/layouts/_tag.html.erb @@ -4,7 +4,7 @@ <% if object_flag == '3' %> - <%= toggle_link (image_tag "/images/sidebar/add.png"), 'put-tag-form-issue', {:focus => 'name'} %> + <%= toggle_link (image_tag "/images/sidebar/add.png"), 'put-tag-form-issue', {:focus => 'name-issue'} %>
diff --git a/app/views/layouts/base_projects.html.erb b/app/views/layouts/base_projects.html.erb index 0ee2c64a0..00ff23a0d 100644 --- a/app/views/layouts/base_projects.html.erb +++ b/app/views/layouts/base_projects.html.erb @@ -30,7 +30,7 @@<%= link_to image_tag(avatar_image(@project), :class => 'avatar') %> | +<%= link_to image_tag(url_to_avatar(@project), :class => 'avatar') %> |
<%= textilizable @project.name %>
@@ -42,6 +42,7 @@
|
<%= link_to image_tag(url_to_avatar(user), :class => "avatar"), user_path(user), :title => "#{user.name}" %> | +
|
+
<%= link_to_user(membership.user) if membership.respond_to?(:user) %> 创建了 <%= link_to_project(membership.project) %> | +<%= link_to_user(membership.user) if membership.respond_to?(:user) %> + 创建了 <%= link_to_project(membership.project) %> | |||||||||
diff --git a/app/views/users/user_watchlist.html.erb b/app/views/users/user_watchlist.html.erb
new file mode 100644
index 000000000..222ac117e
--- /dev/null
+++ b/app/views/users/user_watchlist.html.erb
@@ -0,0 +1,32 @@
+
+<%= l(:label_user_watcher)%>+
+ <% for user in User.watched_by(@user.id) %>
+
\ No newline at end of file
diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb
index 438652557..df0a561b0 100644
--- a/app/views/welcome/index.html.erb
+++ b/app/views/welcome/index.html.erb
@@ -137,7 +137,7 @@
项目需求 添加描述添加描述添加描述添加描述... |
- 发现开源 +项目需求 添加描述添加描述添加描述添加描述... |
seems_rateable
to routes.rb file
+
+Include stylesheet adding <%= seems_rateable_stylesheet %>
to your layout header
+
+Also make sure you have an existing current_user
helper method
+
+Don't forget to run
+
+ $ rake db:migrate
+
+To prepare model add seems_rateable
to your rateable model file. You can also pass a hash of options to
+customize the functionality
+
+:dimensions
Array of dimensions e.g :dimensions => [:quality, :quantity]
:allow_update
Allowing user to re-rate his own ratings, default set to false e.g :allow_update=> true
rates
method, to get dimension rates pass an argument eg :
+
+ @object.rates
+ @object.rates(:quality)
+ @object.rates(:quantity)
+
+This also applies to cached average rating e.g
+
+ @object.average
+ @object.average(:quality)
+ @object.average(:quantity)
+
+And to object's raters e.g
+
+ @object.raters
+ @object.raters(:quality)
+ @object.raters(:quantity)
+
+To track user's given ratings add seems_rateable_rater
to your rater model.
+If your rater class is not "User"(e.g "Client" or "Customer") change configuration in initializer generated by this engine.
+Now you can access user's ratings by @user.ratings_given
+
+### Usage
+
+To display star rating use helper method rating_for
in your view
+
+ #index.html.erb
+
+ rating_for @post
+
+ rating_for @post, :dimension => :quality, :class => 'post', :id => 'list'
+
+ rating_for @post, :static => true
+
+You can specify these options :
+:dimension
The dimension of the object:static
Set to true to display static star rating, default false:class
Class of the div, default set to 'rateable':id
ID of the div e.g :id => "info"
, default nil',{ + 'class' : 'jRatingInfos', + html : getNote(relativeX)+' / '+opts.rateMax+'', + css : { + top: (e.pageY + opts.rateInfosY), + left: (e.pageX + opts.rateInfosX) + } + }).appendTo('body').show(); + }, + mouseover : function(e){ + $(this).css('cursor','pointer'); + }, + mouseout : function(){ + $(this).css('cursor','default'); + if(hasRated) average.width(globalWidth); + else average.width(0); + }, + mousemove : function(e){ + var realOffsetLeft = findRealLeft(this); + var relativeX = e.pageX - realOffsetLeft; + if(opts.step) newWidth = Math.floor(relativeX/starWidth)*starWidth + starWidth; + else newWidth = relativeX; + average.width(newWidth); + if (opts.showRateInfo) + $("p.jRatingInfos") + .css({ + left: (e.pageX + opts.rateInfosX) + }) + .html(getNote(newWidth) +' / '+opts.rateMax+''); + }, + mouseleave : function(){ + $("p.jRatingInfos").remove(); + }, + click : function(e){ + var element = this; + + /*set vars*/ + hasRated = true; + globalWidth = newWidth; + nbOfRates--; + + if(!opts.canRateAgain || parseInt(nbOfRates) <= 0) $(this).unbind().css('cursor','default').addClass('jDisabled'); + + if (opts.showRateInfo) $("p.jRatingInfos").fadeOut('fast',function(){$(this).remove();}); + e.preventDefault(); + var rate = getNote(newWidth); + average.width(newWidth); + + + $.post(defaults.path, + { + idBox : idBox, + rate : rate, + kls : kls, + dimension : dimension + /** action : 'rating' **/ + }, + function(data) { + if(!data.error) + { + /** Here you can display an alert box, + or use the jNotify Plugin :) http://www.myqjqueryplugins.com/jNotify + exemple : */ + if(opts.onSuccess) opts.onSuccess( element, rate ); + } + else + { + + /** Here you can display an alert box, + or use the jNotify Plugin :) http://www.myqjqueryplugins.com/jNotify + exemple : */ + if(opts.onError) opts.onError( element, rate ); + } + }, + 'json' + ); + } + }); + + function getNote(relativeX) { + var noteBrut = parseFloat((relativeX*100/widthRatingContainer)*opts.rateMax/100); + switch(opts.decimalLength) { + case 1 : + var note = Math.round(noteBrut*10)/10; + break; + case 2 : + var note = Math.round(noteBrut*100)/100; + break; + case 3 : + var note = Math.round(noteBrut*1000)/1000; + break; + default : + var note = Math.round(noteBrut*1)/1; + } + return note; + }; + + function getStarWidth(){ + switch(opts.type) { + case 'small' : + starWidth = 12; // width of the picture small.png + starHeight = 10; // height of the picture small.png + bgPath = opts.smallStarsPath; + break; + default : + starWidth = 23; // width of the picture stars.png + starHeight = 20; // height of the picture stars.png + bgPath = opts.bigStarsPath; + } + }; + + function findRealLeft(obj) { + if( !obj ) return 0; + return obj.offsetLeft + findRealLeft( obj.offsetParent ); + }; + }); + + } +})(jQuery); diff --git a/lib/plugins/seems_rateable-master/lib/generators/seems_rateable/install/templates/rateable.js.erb b/lib/plugins/seems_rateable-master/lib/generators/seems_rateable/install/templates/rateable.js.erb new file mode 100644 index 000000000..da6cc3097 --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/generators/seems_rateable/install/templates/rateable.js.erb @@ -0,0 +1,25 @@ +$(document).ready(function(){ + $(".rateable").jRating({ + //default options displayed below -> + + rateMax: 5, //Maximal rate + length : 5, //Number of stars + //decimalLength : 0, //Number of decimals in the rate + //type : 'big', //Big or small + //step : true, //If set to true, filling of the stars is done star by star (step by step). + //isDisabled: false, //Set true to display static rating + //showRateInfo:false, //Rate info panel, set true to display + //rateInfosX : 45, //In pixel - Absolute left position of the information box during mousemove. + //rateInfosY : 5, //In pixel - Absolute top position of the information box during mousemove. + path : '<%= SeemsRateable::Engine.routes.url_helpers.ratings_path %>', + onSuccess : function(element, rate){ + //something like -> + //alert('success'); + $('Thanks for rating!').insertAfter(element) + }, + onError : function(element, rate) { + $('You have already rated!').insertAfter(element) + } + }); + +}); diff --git a/lib/plugins/seems_rateable-master/lib/generators/seems_rateable/install/templates/rates_migration.rb b/lib/plugins/seems_rateable-master/lib/generators/seems_rateable/install/templates/rates_migration.rb new file mode 100644 index 000000000..40303f11c --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/generators/seems_rateable/install/templates/rates_migration.rb @@ -0,0 +1,18 @@ +class CreateSeemsRateableRates < ActiveRecord::Migration + def self.up + create_table :seems_rateable_rates do |t| + t.belongs_to :rater + t.belongs_to :rateable, :polymorphic => true + t.float :stars, :null => false + t.integer :rater_id, :limit => 8 + t.integer :rateable_id + t.string :rateable_type + t.string :dimension + t.timestamps + end + end + + def self.down + drop_table :rates + end +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable.rb new file mode 100644 index 000000000..5f84a8b8c --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable.rb @@ -0,0 +1,14 @@ +begin + require 'rails' +rescue LoadError +end + +require "seems_rateable/engine" +require "seems_rateable/errors" +require "seems_rateable/helpers" +require "seems_rateable/model" +require "seems_rateable/routes" +require "seems_rateable/version" + +module SeemsRateable +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable/engine.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable/engine.rb new file mode 100644 index 000000000..185d6f9d9 --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable/engine.rb @@ -0,0 +1,17 @@ +module SeemsRateable + class Engine < ::Rails::Engine + isolate_namespace SeemsRateable + + config.generators do |g| + g.test_framework :rspec, :fixture => false + g.fixture_replacement :factory_girl, :dir => 'spec/factories' + end + + initializer :seems_rateable do + ActiveRecord::Base.send :include, SeemsRateable::Model + ActionView::Base.send :include, SeemsRateable::Helpers + ActionDispatch::Routing::Mapper.send :include, SeemsRateable::Routes + end + + end +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable/errors.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable/errors.rb new file mode 100644 index 000000000..8a83059ba --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable/errors.rb @@ -0,0 +1,21 @@ +module SeemsRateable + module Errors + class InvalidRateableObjectError < StandardError + def to_s + "Stated object is not rateable. Add 'seems_rateable' to your object's class model." + end + end + + class NoCurrentUserInstanceError < StandardError + def to_s + "User instance current_user is not available." + end + end + + class AlreadyRatedError < StandardError + def to_s + "User has already rated an object." + end + end + end +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable/helpers.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable/helpers.rb new file mode 100644 index 000000000..399f06fd8 --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable/helpers.rb @@ -0,0 +1,27 @@ +module SeemsRateable + module Helpers + def rating_for(obj, opts={}) + raise Errors::InvalidRateableObjectError unless obj.class.respond_to?(:rateable?) + + options = { + :dimension => nil, + :static => false, + :class => 'rateable', + :id => nil + }.update(opts) + + content_tag :div, "", "data-average" => obj.average(options[:dimension]) ? obj.average(options[:dimension]).avg : 0, :id => options[:id], + :class => "#{options[:class]}#{jdisabled?(options[:static])}", + "data-id" => obj.id, "data-kls" => obj.class.name, "data-dimension" => options[:dimension] + end + + def seems_rateable_stylesheet + stylesheet_link_tag "seems_rateable/application", media: "all", "data-turbolinks-track" => true + end + + private + def jdisabled?(option) + " jDisabled" if option || !current_user + end + end +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable/model.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable/model.rb new file mode 100644 index 000000000..fa1b7af11 --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable/model.rb @@ -0,0 +1,111 @@ +require 'active_support/concern' +module SeemsRateable + module Model + extend ActiveSupport::Concern + + def rate(stars, user_id, dimension=nil) + if !has_rated?(user_id, dimension) + self.rates.create do |r| + r.stars = stars + r.rater_id = user_id + end + update_overall_average_rating(stars, dimension) + elsif has_rated?(user_id, dimension) && can_update? + update_users_rating(stars, user_id, dimension) + else + raise Errors::AlreadyRatedError + end + end + + def update_overall_average_rating(stars, dimension=nil) + if average(dimension).nil? + CachedRating.create do |r| + r.avg = stars + r.dimension = dimension + r.cacheable_id = self.id + r.cacheable_type = self.class.name + r.cnt = 1 + end + else + r = average(dimension) + r.avg = (r.avg * r.cnt + stars) / (r.cnt+1) + r.cnt += 1 + r.save! + end + end + + def update_users_rating(stars, user_id, dimension=nil) + obj = rates(dimension).where(:rater_id => user_id).first + current_record = average(dimension) + current_record.avg = (current_record.avg*current_record.cnt - obj.stars + stars) / (current_record.cnt) + current_record.save! + obj.stars = stars + obj.save! + end + + + def average(dimension=nil) + if dimension.nil? + self.send "rate_average_without_dimension" + else + self.send "#{dimension}_average" + end + end + + def rates(dimension=nil) + if dimension.nil? + self.send "rates_without_dimension" + else + self.send "#{dimension}_rates" + end + end + + def raters(dimension=nil) + if dimension.nil? + self.send "raters_without_dimension" + else + self.send "#{dimension}_raters" + end + end + + def has_rated?(user_id, dimension=nil) + record = self.rates(dimension).where(:rater_id => user_id) + record.empty? ? false : true + end + + def can_update? + self.class.can_update? + end + + module ClassMethods + def seems_rateable(opts={}) + #has_many :rates_without_dimension, -> { where(dimension: nil) }, :as => :rateable, :class_name => SeemsRateable::Rate, :dependent => :destroy + has_many :rates_without_dimension, :conditions => { dimension: nil }, :as => :rateable, :class_name => SeemsRateable::Rate, :dependent => :destroy + has_many :raters_without_dimension, :through => :rates_without_dimension, :source => :rater + has_one :rate_average_without_dimension, :conditions => { dimension: nil }, :as => :cacheable, :class_name => SeemsRateable::CachedRating, :dependent => :destroy + + @permission = opts[:allow_update] ? true : false + + def self.can_update? + @permission + end + + def self.rateable? + true + end + + if opts[:dimensions].is_a?(Array) + opts[:dimensions].each do |dimension| + has_many :"#{dimension}_rates", :conditions => { dimension: dimension.to_s }, :dependent => :destroy, :class_name => SeemsRateable::Rate, :as => :rateable + has_many :"#{dimension}_raters", :through => :"#{dimension}_rates", :source => :rater + has_one :"#{dimension}_average", :conditions => { dimension: dimension.to_s }, :as => :cacheable, :class_name => SeemsRateable::CachedRating, :dependent => :destroy + end + end + end + + def seems_rateable_rater + has_many :ratings_given, :class_name => SeemsRateable::Rate, :foreign_key => :rater_id + end + end + end +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable/routes.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable/routes.rb new file mode 100644 index 000000000..81a243339 --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable/routes.rb @@ -0,0 +1,7 @@ +module SeemsRateable + module Routes + def seems_rateable + mount SeemsRateable::Engine => '/rateable', :as => :rateable + end + end +end diff --git a/lib/plugins/seems_rateable-master/lib/seems_rateable/version.rb b/lib/plugins/seems_rateable-master/lib/seems_rateable/version.rb new file mode 100644 index 000000000..180e47824 --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/seems_rateable/version.rb @@ -0,0 +1,3 @@ +module SeemsRateable + VERSION = "1.0.9" +end diff --git a/lib/plugins/seems_rateable-master/lib/tasks/seems_rateable_tasks.rake b/lib/plugins/seems_rateable-master/lib/tasks/seems_rateable_tasks.rake new file mode 100644 index 000000000..98c5403ac --- /dev/null +++ b/lib/plugins/seems_rateable-master/lib/tasks/seems_rateable_tasks.rake @@ -0,0 +1,4 @@ +# desc "Explaining what the task does" +# task :seems_rateable do +# # Task goes here +# end diff --git a/lib/plugins/seems_rateable-master/seems_rateable.gemspec b/lib/plugins/seems_rateable-master/seems_rateable.gemspec new file mode 100644 index 000000000..b4f32a9fc --- /dev/null +++ b/lib/plugins/seems_rateable-master/seems_rateable.gemspec @@ -0,0 +1,25 @@ +$:.push File.expand_path("../lib", __FILE__) + +# Maintain your gem's version: +require "seems_rateable/version" + +# Describe your gem and declare its dependencies: +Gem::Specification.new do |s| + s.name = "seems_rateable" + s.version = SeemsRateable::VERSION + s.authors = ["Peter Toth"] + s.email = ["proximin@gmail.com"] + s.homepage = "http://rateable.herokuapp.com" + s.summary = "Star Rating Engine" + s.description = "Star rating engine using jQuery plugin jRating for Rails applications" + + s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.md"] + + s.add_dependency "rails" + s.add_dependency "jquery-rails" + + s.add_development_dependency "sqlite3" + s.add_development_dependency 'rspec-rails' + s.add_development_dependency 'capybara' + s.add_development_dependency 'factory_girl_rails' +end diff --git a/public/images/avatars/AnonymousUser/0 b/public/images/avatars/AnonymousUser/0 index 26e7db3e7..a4cc45467 100644 Binary files a/public/images/avatars/AnonymousUser/0 and b/public/images/avatars/AnonymousUser/0 differ diff --git a/public/images/avatars/Project/0 b/public/images/avatars/Project/0 index beea14904..585b4bfc0 100644 Binary files a/public/images/avatars/Project/0 and b/public/images/avatars/Project/0 differ diff --git a/public/images/avatars/Project/6315 b/public/images/avatars/Project/6315 new file mode 100644 index 000000000..cce3b9ccf Binary files /dev/null and b/public/images/avatars/Project/6315 differ diff --git a/public/images/avatars/Project/6322 b/public/images/avatars/Project/6322 new file mode 100644 index 000000000..1f0332907 Binary files /dev/null and b/public/images/avatars/Project/6322 differ diff --git a/public/images/avatars/User/0 b/public/images/avatars/User/0 index 26e7db3e7..a4cc45467 100644 Binary files a/public/images/avatars/User/0 and b/public/images/avatars/User/0 differ diff --git a/public/images/avatars/User/4874 b/public/images/avatars/User/4874 new file mode 100644 index 000000000..90e0e8474 Binary files /dev/null and b/public/images/avatars/User/4874 differ diff --git a/public/images/praise.png b/public/images/praise.png new file mode 100644 index 000000000..808d18134 Binary files /dev/null and b/public/images/praise.png differ diff --git a/public/images/tread.png b/public/images/tread.png new file mode 100644 index 000000000..a843cc3dc Binary files /dev/null and b/public/images/tread.png differ diff --git a/public/stylesheets/application.css b/public/stylesheets/application.css index 8aa00453d..91b74e767 100644 --- a/public/stylesheets/application.css +++ b/public/stylesheets/application.css @@ -11,6 +11,11 @@ h4 {border-bottom: 1px dotted #bbb;} /*new by huang*/ /**/ +ul.list_watch{list-style-type:none; + height:auto; + border-bottom: 1px dashed rgb(204, 204, 204); + } + .new_creat{ padding-top: 0px; float: right;