diff --git a/controllers/gamification_plugin_admin_controller.rb b/controllers/gamification_plugin_admin_controller.rb index dffacfa..d7ce01e 100644 --- a/controllers/gamification_plugin_admin_controller.rb +++ b/controllers/gamification_plugin_admin_controller.rb @@ -11,6 +11,14 @@ class GamificationPluginAdminController < PluginAdminController end end + def levels + if save_settings + render :file => 'gamification_plugin_admin/index' + else + render :file => 'gamification_plugin_admin/levels' + end + end + protected def save_settings diff --git a/lib/ext/profile.rb b/lib/ext/profile.rb index 51a43b2..6aff19d 100644 --- a/lib/ext/profile.rb +++ b/lib/ext/profile.rb @@ -4,4 +4,14 @@ class Profile has_merit + def gamification_plugin_calculate_level + settings = GamificationPlugin.settings(environment) + last_level = 0 + (settings.get_setting(:rank_rules) || []).sort_by {|r| r[:points] }.each do |rule| + return last_level if points < rule[:points] + last_level = rule[:level] + end + last_level + end + end diff --git a/lib/gamification_plugin.rb b/lib/gamification_plugin.rb index ae302cd..5af8f51 100644 --- a/lib/gamification_plugin.rb +++ b/lib/gamification_plugin.rb @@ -8,6 +8,10 @@ class GamificationPlugin < Noosfero::Plugin _("Gamification Plugin") end + def self.settings(environment) + Noosfero::Plugin::Settings.new(environment, GamificationPlugin) + end + def user_data_extras proc do current_person.present? ? {:gamification_plugin => {:points => current_person.points, :badges => current_person.badges, :level => current_person.level}} : {} @@ -54,6 +58,7 @@ class GamificationPlugin < Noosfero::Plugin config.checks_on_each_request = false config.user_model_name = 'Profile' config.current_user_method = 'current_person' + config.add_observer 'Merit::RankObserver' end require_dependency 'merit_ext' diff --git a/lib/merit/rank_observer.rb b/lib/merit/rank_observer.rb new file mode 100644 index 0000000..cd2ca39 --- /dev/null +++ b/lib/merit/rank_observer.rb @@ -0,0 +1,13 @@ +module Merit + + class RankObserver + def update(changed_data) + merit = changed_data[:merit_object] + if merit.kind_of?(Merit::Score::Point) + profile = merit.score.sash.profile + profile.update_attribute(:level, profile.gamification_plugin_calculate_level) if profile.present? + end + end + end + +end diff --git a/lib/merit/rank_rules.rb b/lib/merit/rank_rules.rb deleted file mode 100644 index 344237b..0000000 --- a/lib/merit/rank_rules.rb +++ /dev/null @@ -1,31 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# 5 stars is a common ranking use case. They are not given at specified -# actions like badges, you should define a cron job to test if ranks are to be -# granted. -# -# +set_rank+ accepts: -# * :+level+ ranking level (greater is better) -# * :+to+ model or scope to check if new rankings apply -# * :+level_name+ attribute name (default is empty and results in 'level' -# attribute, if set it's appended like 'level_#{level_name}') - -module Merit - class RankRules - include Merit::RankRulesMethods - - def initialize - # set_rank :level => 1, :to => Commiter.active do |commiter| - # commiter.repositories.count > 1 && commiter.followers >= 10 - # end - # - # set_rank :level => 2, :to => Commiter.active do |commiter| - # commiter.branches.count > 1 && commiter.followers >= 10 - # end - # - # set_rank :level => 3, :to => Commiter.active do |commiter| - # commiter.branches.count > 2 && commiter.followers >= 20 - # end - end - end -end diff --git a/lib/merit/sash.rb b/lib/merit/sash.rb index 25b4ea5..10872bf 100644 --- a/lib/merit/sash.rb +++ b/lib/merit/sash.rb @@ -3,6 +3,12 @@ module Merit class Sash has_many :gamification_plugin_badges, :through => :badges_sashes, :source => :gamification_plugin_badge alias :badges :gamification_plugin_badges + has_one :profile, :foreign_key => :sash_id, :class_name => 'Profile' + has_one :article, :foreign_key => :sash_id, :class_name => 'Article' + + def target + profile || article + end end def notify_all_badges_from_user diff --git a/public/admin.css b/public/admin.css new file mode 100644 index 0000000..bd7320b --- /dev/null +++ b/public/admin.css @@ -0,0 +1,3 @@ +.gamification-plugin-rank-rules .template-level { + display: none !important; +} diff --git a/public/admin.js b/public/admin.js new file mode 100644 index 0000000..b1da1d7 --- /dev/null +++ b/public/admin.js @@ -0,0 +1,8 @@ +var gamificationPluginAdmin = { + + addNewLevelRule: function() { + var template = $('.gamification-plugin-rank-rules .template-level > div').clone(); + template.find('.level-value').text($('.gamification-plugin-rank-rules .rank-rules .items .level').length + 1); + $('.gamification-plugin-rank-rules .rank-rules .items').append(template); + } +} diff --git a/test/functional/gamification_plugin_admin_controller_test.rb b/test/functional/gamification_plugin_admin_controller_test.rb index 0c84c7c..6899a91 100644 --- a/test/functional/gamification_plugin_admin_controller_test.rb +++ b/test/functional/gamification_plugin_admin_controller_test.rb @@ -31,5 +31,20 @@ class GamificationPluginAdminControllerTest < ActionController::TestCase assert_select 'input[name=?][value=?]', "settings[point_rules][comment_author[weight]]", 500 end + should 'save rank rules' do + post :levels, :settings => {:rank_rules => [{:level => 1, :points => 10}]} + @settings = Noosfero::Plugin::Settings.new(environment.reload, GamificationPlugin) + assert_equal({:rank_rules => [{'level' => '1', 'points' => '10'}]}, @settings.settings) + end + + should 'load saved levels' do + settings = Noosfero::Plugin::Settings.new(environment, GamificationPlugin, {}) + settings.set_setting(:rank_rules, [{'level' => '1', 'points' => '10'}, {'level' => '2', 'points' => '20'}]) + settings.save! + get :levels + assert_select 'input[name=?][value=?]', "settings[rank_rules][][points]", 10 + assert_select 'input[name=?][value=?]', "settings[rank_rules][][points]", 20 + end + end diff --git a/test/unit/profile_test.rb b/test/unit/profile_test.rb new file mode 100644 index 0000000..53b5b12 --- /dev/null +++ b/test/unit/profile_test.rb @@ -0,0 +1,42 @@ +require_relative "../test_helper" + +class ProfileTest < ActiveSupport::TestCase + + def setup + @environment = Environment.default + @profile = fast_create(Profile) + @settings = GamificationPlugin.settings(environment) + @settings.set_setting(:rank_rules, [ + {:level => 1, :points => 10}, + {:level => 2, :points => 20}, + {:level => 3, :points => 30} + ]) + @settings.save! + end + + attr_accessor :profile, :environment + + should 'calculate profile level' do + profile.stubs(:points).returns(25) + assert_equal 2, profile.gamification_plugin_calculate_level + end + + should 'calculate profile last level' do + profile.stubs(:points).returns(35) + assert_equal 3, profile.gamification_plugin_calculate_level + end + + should 'calculate profile first level' do + profile.stubs(:points).returns(10) + assert_equal 1, profile.gamification_plugin_calculate_level + end + + should 'update profile level when the score changes' do + GamificationPlugin.gamification_set_rules(environment) + person = create_user('testuser').person + assert_equal 0, person.level + create(Article, :profile_id => profile.id, :author => person) + assert_equal 3, person.reload.level + end + +end diff --git a/views/gamification_plugin_admin/_level.html.erb b/views/gamification_plugin_admin/_level.html.erb new file mode 100644 index 0000000..3e54e90 --- /dev/null +++ b/views/gamification_plugin_admin/_level.html.erb @@ -0,0 +1,4 @@ +
+ <%= _('Level') %> <%= level_counter + 1 %> + <%= text_field_tag("settings[rank_rules][][points]", level['points']) %> +
diff --git a/views/gamification_plugin_admin/index.html.erb b/views/gamification_plugin_admin/index.html.erb index 23cf9f2..8181f2d 100644 --- a/views/gamification_plugin_admin/index.html.erb +++ b/views/gamification_plugin_admin/index.html.erb @@ -1,15 +1,19 @@

<%= _('Gamification Settings')%>

-
- <%= link_to _('Manage Point Rules'), :controller => 'gamification_plugin_admin', :action => :points %> -
+ -<%= button :cancel, _('Cancel'), :controller => :plugins, :action => :index %> +
+ <%= button :cancel, _('Cancel'), :controller => :plugins, :action => :index %> +
diff --git a/views/gamification_plugin_admin/levels.html.erb b/views/gamification_plugin_admin/levels.html.erb new file mode 100644 index 0000000..754aa5c --- /dev/null +++ b/views/gamification_plugin_admin/levels.html.erb @@ -0,0 +1,26 @@ +<%= javascript_include_tag 'plugins/gamification/admin.js' %> +<%= stylesheet_link_tag 'plugins/gamification/admin.css' %> + +
+

<%= _('Gamification Settings: Rank Rules')%>

+ +<%= form_for(:settings) do |f| %> +
+

<%= _('Rank Rules') %>

+
+ <%= render :partial => 'gamification_plugin_admin/level', :collection => @settings.rank_rules %> +
+
+ + <% button_bar do %> + <%= link_to_function(_('New Level'), 'gamificationPluginAdmin.addNewLevelRule();', :class => 'button icon-add with-text') %> + <%= submit_button(:save, c_('Save'), :cancel => {:action => 'index'}) %> + <% end %> + +<% end %> + +
+ <%= render :partial => 'gamification_plugin_admin/level', :collection => [{}] %> +
+ +
-- libgit2 0.21.2