Commit 696c40b48461f31544cd564af214e6f871729fac

Authored by Hugo Melo
2 parents bdf09ff4 5125e5a8

Merge branch '100_add_badges_with_more_than_one_element' into gamification_test

Conflicts:
	lib/gamification_plugin/api.rb
db/migrate/20151003000212_move_badge_threshold_to_action_key.rb 0 → 100644
... ... @@ -0,0 +1,26 @@
  1 +class MoveBadgeThresholdToActionKey < ActiveRecord::Migration
  2 + def up
  3 + change_table :gamification_plugin_badges do |t|
  4 + t.change :custom_fields, :text
  5 + end
  6 + GamificationPlugin::Badge.all.each do |badge|
  7 + next if Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].nil?
  8 + Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].each do |setting|
  9 + badge.custom_fields[setting[:action]] = {threshold: badge.custom_fields[:threshold]} unless badge.custom_fields[:threshold].nil?
  10 + badge.save
  11 + end
  12 + end
  13 + end
  14 +
  15 + def down
  16 + GamificationPlugin::Badge.all.each do |badge|
  17 + next if Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].nil?
  18 + setting = Merit::BadgeRules::AVAILABLE_RULES[badge.name.to_sym].first
  19 + badge.custom_fields = {threshold: badge.custom_fields.fetch(setting[:action], {}).fetch(:threshold, "")}
  20 + badge.save
  21 + end
  22 + change_table :gamification_plugin_badges do |t|
  23 + t.change :custom_fields, :string
  24 + end
  25 + end
  26 +end
... ...
lib/ext/article_follower.rb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +require_dependency 'article_follower'
  2 +
  3 +class ArticleFollower
  4 +
  5 + has_merit
  6 + has_merit_actions
  7 +
  8 +end
... ...
lib/gamification_plugin.rb
... ... @@ -50,7 +50,7 @@ class GamificationPlugin &lt; Noosfero::Plugin
50 50 end
51 51  
52 52 def js_files
53   - ['jquery.noty.packaged.min.js', 'jquery.easypiechart.min.js', 'main.js']
  53 + ['jquery.noty.packaged.min.js', 'jquery.easypiechart.min.js', 'main.js', 'admin.js']
54 54 end
55 55  
56 56  
... ...
lib/merit/badge_rules.rb
... ... @@ -9,58 +9,157 @@ module Merit
9 9 include Merit::BadgeRulesMethods
10 10  
11 11 AVAILABLE_RULES = {
12   - :comment_author => {
13   - :action => 'comment#create',
14   - :default_threshold => 5,
15   - :to => :author,
16   - :value => lambda { |comment| comment.author.present? ? comment.author.comments.count : 0 }
17   - },
18   - :comment_received => {
19   - :action => 'comment#create',
20   - :default_threshold => 5,
21   - :to => lambda {|comment| comment.source.author},
22   - :value => lambda { |comment| comment.source.author.present? ? Comment.where(:source_id => Article.where(:author_id => comment.source.author.id)).count : 0 }
23   - },
24   - :article_author => {
25   - :action => 'article#create',
26   - :default_threshold => 5,
27   - :to => :author,
28   - :value => lambda { |article| article.author.present? ? article.environment.articles.text_articles.where(:author_id => article.author.id).count : 0 }
29   - },
30   - :positive_votes_received => {
31   - :action => 'vote#create',
32   - :default_threshold => 5,
33   - :to => lambda {|vote| vote.voteable.author},
34   - :value => lambda { |vote| Vote.for_voteable(vote.voteable).where('vote > 0').count }
35   - },
36   - :negative_votes_received => {
37   - :action => 'vote#create',
38   - :default_threshold => 5,
39   - :to => lambda {|vote| vote.voteable.author},
40   - :value => lambda { |vote| Vote.for_voteable(vote.voteable).where('vote < 0').count }
41   - },
42   - :votes_performed => {
43   - :action => 'vote#create',
44   - :default_threshold => 5,
45   - :to => lambda {|vote| vote.voter},
46   - :value => lambda { |vote| Vote.for_voter(vote.voter).count }
47   - },
48   - :friendly => {
49   - :action => 'friendship#create',
50   - :default_threshold => 5,
51   - :to => lambda {|friendship| friendship.person},
52   - :value => lambda { |friendship| friendship.person.friends.count }
53   - }
  12 + comment_author: [
  13 + {
  14 + action: 'comment#create',
  15 + default_threshold: 5,
  16 + to: :author,
  17 + value: lambda { |comment, author| author.present? ? author.conference_comments.count : 0 }
  18 + }
  19 + ],
  20 + comment_received: [
  21 + {
  22 + action: 'comment#create',
  23 + default_threshold: 5,
  24 + to: lambda {|comment| comment.source.author},
  25 + value: lambda { |comment, author| author.present? ? Comment.where(source_id: Article.conference_articles.where(author_id: author.id)).count : 0 }
  26 + }
  27 + ],
  28 + article_author: [
  29 + {
  30 + action: 'article#create',
  31 + default_threshold: 5,
  32 + to: :author,
  33 + value: lambda { |article, author| author.present? ? TextArticle.conference_articles.comments.where(author_id: author.id).count : 0 }
  34 + },
  35 + ],
  36 + positive_votes_received: [
  37 + {
  38 + action: 'vote#create',
  39 + default_threshold: 5,
  40 + to: lambda {|vote| vote.voteable.author},
  41 + value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote > 0').count }
  42 + }
  43 + ],
  44 + negative_votes_received: [
  45 + {
  46 + action: 'vote#create',
  47 + default_threshold: 5,
  48 + to: lambda {|vote| vote.voteable.author},
  49 + value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote < 0').count }
  50 + }
  51 + ],
  52 + votes_performed: [
  53 + {
  54 + action: 'vote#create',
  55 + default_threshold: 5,
  56 + to: lambda {|vote| vote.voter},
  57 + value: lambda { |vote, voter| Vote.for_voter(voter).count }
  58 + }
  59 + ],
  60 + friendly: [
  61 + {
  62 + action: 'friendship#create',
  63 + default_threshold: 5,
  64 + to: lambda {|friendship| friendship.person},
  65 + value: lambda { |friendship, person| person.friends.count }
  66 + }
  67 + ],
  68 + creative: [
  69 + {
  70 + action: 'comment#create',
  71 + default_threshold: 5,
  72 + to: :author,
  73 + value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
  74 + },
  75 + {
  76 + action: 'article#create',
  77 + default_threshold: 5,
  78 + to: :author,
  79 + value: lambda { |article, author| author.present? ? author.articles.count : 0 }
  80 + },
  81 + ],
  82 + observer: [
  83 + {
  84 + action: 'article_follower#create',
  85 + default_threshold: 5,
  86 + to: lambda {|article| article.person },
  87 + value: lambda { |article, person| person.present? ? person.article_followers.count : 0 }
  88 + }
  89 + ],
  90 + mobilizer: [
  91 + {
  92 + action: 'Vote#create',
  93 + default_threshold: 5,
  94 + to: lambda { |vote| vote.voter },
  95 + value: lambda { |vote, voter| Vote.for_voter(voter).count }
  96 + },
  97 + {
  98 + action: 'Event#create',
  99 + default_threshold: 5,
  100 + to: lambda { |article| article.author },
  101 + value: lambda { |event, author| author.events.count }
  102 + },
  103 + ],
  104 + generous: [
  105 + {
  106 + action: 'vote#create',
  107 + default_threshold: 5,
  108 + to: lambda {|vote| vote.voter},
  109 + value: lambda { |vote, voter| voter.votes.where('vote > 0').count }
  110 + },
  111 + {
  112 + action: 'comment#create',
  113 + default_threshold: 5,
  114 + to: :author,
  115 + value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
  116 + }
  117 + ],
  118 + articulator: [
  119 + {
  120 + action: 'article_follower#create',
  121 + default_threshold: 5,
  122 + to: :person,
  123 + value: lambda { |article_follower, person| person.present? ? person.article_followers.count : 0 }
  124 + },
  125 + {
  126 + action: 'comment#create',
  127 + default_threshold: 5,
  128 + to: :author,
  129 + value: lambda { |comment, author| author.present? ? author.comments.count : 0 }
  130 + },
  131 + #mobilizer#create
  132 + ]
54 133 }
55 134  
56 135 def initialize(environment=nil)
57 136 return if environment.nil?
58 137 @environment = environment
59 138  
  139 + rules = AVAILABLE_RULES
  140 + rules.merge! CONFERENCE_RULES if defined? CONFERENCE_RULES
  141 +
60 142 environment.gamification_plugin_badges.all.each do |badge|
61   - setting = AVAILABLE_RULES[badge.name.to_sym]
62   - grant_on setting[:action], :badge => badge.name, :level => badge.level, :to => setting[:to] do |source|
63   - setting[:value].call(source) >= (badge.custom_fields || {}).fetch(:threshold, setting[:default_threshold]).to_i
  143 + next if rules[badge.name.to_sym].nil?
  144 + rules[badge.name.to_sym].each do |setting|
  145 + grant_on setting[:action], badge: badge.name, level: badge.level, to: setting[:to] do |source|
  146 + can_be_granted = true
  147 + rules[badge.name.to_sym].each do |s|
  148 + if setting[:to].is_a? Symbol
  149 + to = source.send(setting[:to])
  150 + else
  151 + begin
  152 + to = setting[:to].call(source)
  153 + rescue
  154 + to = nil
  155 + end
  156 + end
  157 + # pass source and to for different situations
  158 + action = (badge.custom_fields || {}).fetch(s[:action], {})
  159 + can_be_granted &= s[:value].call(source, to) >= action.fetch(:threshold, s[:default_threshold]).to_i
  160 + end
  161 + can_be_granted
  162 + end
64 163 end
65 164 end
66 165 end
... ...
public/admin.js
... ... @@ -4,5 +4,20 @@ var gamificationPluginAdmin = {
4 4 var template = $('.gamification-plugin-rank-rules .template-level > div').clone();
5 5 template.find('.level-value').text($('.gamification-plugin-rank-rules .rank-rules .items .level').length + 1);
6 6 $('.gamification-plugin-rank-rules .rank-rules .items').append(template);
  7 + },
  8 +
  9 + selectCustomFieldsOnNameChange: function() {
  10 + jQuery('.controller-actions').find('input').attr('disabled', 'disabled');
  11 + jQuery('.controller-actions').hide();
  12 + console.log('.name_'+jQuery('#gamification-plugin-form-badge-name').val());
  13 + var name = jQuery('#gamification-plugin-form-badge-name').find('option:selected').text();
  14 + jQuery('.name_'+name).show();
  15 + jQuery('.name_'+name).find('input').removeAttr('disabled');
7 16 }
  17 +
8 18 }
  19 +
  20 +jQuery(function() {
  21 + $('#gamification-plugin-form-badge-name').on('change', gamificationPluginAdmin.selectCustomFieldsOnNameChange);
  22 + gamificationPluginAdmin.selectCustomFieldsOnNameChange();
  23 +});
... ...
views/gamification_plugin_badges/_form.html.erb
... ... @@ -11,9 +11,11 @@
11 11 </div>
12 12 <% end %>
13 13  
14   - <div class="field">
  14 + <% rules = Merit::BadgeRules::AVAILABLE_RULES %>
  15 + <% rules.merge! Merit::BadgeRules::CONFERENCE_RULES %>
  16 + <div class="field" id="gamification-plugin-form-badge-name">
15 17 <%= f.label :name %><br />
16   - <%= f.select :name, Merit::BadgeRules::AVAILABLE_RULES.map{ |key, rule| key } %>
  18 + <%= f.select :name, rules.map{ |key, rule| key } %>
17 19 </div>
18 20 <div class="field">
19 21 <%= f.label :title %><br />
... ... @@ -27,11 +29,22 @@
27 29 <%= f.label :level %><br />
28 30 <%= f.text_field :level %>
29 31 </div>
  32 + <h4><%= _('Actions') %></h4>
30 33 <%= f.fields_for :custom_fields do |c| %>
31   - <div class="field">
32   - <%= c.label :threshold %><br />
33   - <%= c.text_field :threshold %>
34   - </div>
  34 + <% rules.each do |name, settings| %>
  35 + <div class='controller-actions <%= "name_#{name}" %>'>
  36 + <% settings.each do |setting| %>
  37 + <%= c.label _(setting[:action]) %>
  38 + <%= c.fields_for setting[:action] do |d| %>
  39 + <% action = (@gamification_plugin_badge.custom_fields || {}).fetch(setting[:action], {}) %>
  40 + <div class="field">
  41 + <%= d.label :threshold %><br />
  42 + <%= d.text_field :threshold, {value: action.fetch('threshold', "")} %>
  43 + </div>
  44 + <% end %>
  45 + <% end %>
  46 + </div>
  47 + <% end %>
35 48 <% end %>
36 49 <div class="actions">
37 50 <%= f.submit %>
... ...