Compare View
Commits (15)
-
Add script to fix pontuation See merge request !3
-
This issue is caused by delayed_job. See more on https://softwarepublico.gov.br/gitlab/noosfero-plugins/gamification/issues/1
Showing
29 changed files
Show diff stats
controllers/admin/gamification_plugin_badges_controller.rb
1 | 1 | class GamificationPluginBadgesController < PluginAdminController |
2 | 2 | |
3 | 3 | def index |
4 | - @gamification_plugin_badges = environment.gamification_plugin_badges | |
4 | + @gamification_plugin_badges = environment.gamification_plugin_badges.group_by(&:owner) | |
5 | 5 | end |
6 | 6 | |
7 | 7 | def show |
... | ... | @@ -17,8 +17,13 @@ class GamificationPluginBadgesController < PluginAdminController |
17 | 17 | end |
18 | 18 | |
19 | 19 | def create |
20 | + owner_id = params[:gamification_plugin_badge].delete(:owner_id) | |
20 | 21 | @gamification_plugin_badge = GamificationPlugin::Badge.new(params[:gamification_plugin_badge]) |
21 | - @gamification_plugin_badge.owner = environment | |
22 | + if owner_id.present? | |
23 | + @gamification_plugin_badge.owner = environment.organizations.find(owner_id) | |
24 | + else | |
25 | + @gamification_plugin_badge.owner = environment | |
26 | + end | |
22 | 27 | |
23 | 28 | if @gamification_plugin_badge.save |
24 | 29 | session[:notice] = _('Badge was successfully created.') |
... | ... | @@ -31,6 +36,14 @@ class GamificationPluginBadgesController < PluginAdminController |
31 | 36 | def update |
32 | 37 | @gamification_plugin_badge = environment.gamification_plugin_badges.find(params[:id]) |
33 | 38 | |
39 | + # FIXME avoid code duplication | |
40 | + owner_id = params[:gamification_plugin_badge].delete(:owner_id) | |
41 | + if owner_id.present? | |
42 | + @gamification_plugin_badge.owner = environment.organizations.find(owner_id) | |
43 | + else | |
44 | + @gamification_plugin_badge.owner = environment | |
45 | + end | |
46 | + | |
34 | 47 | if @gamification_plugin_badge.update_attributes(params[:gamification_plugin_badge]) |
35 | 48 | session[:notice] = _('Badge was successfully updated.') |
36 | 49 | redirect_to :action => :index |
... | ... | @@ -39,6 +52,10 @@ class GamificationPluginBadgesController < PluginAdminController |
39 | 52 | end |
40 | 53 | end |
41 | 54 | |
55 | + def search_owners | |
56 | + render :text => prepare_to_token_input(environment.organizations).to_json | |
57 | + end | |
58 | + | |
42 | 59 | def destroy |
43 | 60 | @gamification_plugin_badge = environment.gamification_plugin_badges.find(params[:id]) |
44 | 61 | @gamification_plugin_badge.destroy | ... | ... |
lib/ext/environment.rb
... | ... | @@ -2,6 +2,11 @@ require_dependency 'environment' |
2 | 2 | |
3 | 3 | class Environment |
4 | 4 | |
5 | - has_many :gamification_plugin_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner | |
5 | + has_many :gamification_plugin_environment_badges, :class_name => 'GamificationPlugin::Badge', :foreign_key => 'owner_id', :source => :owner | |
6 | + has_many :gamification_plugin_organization_badges, :through => :organizations | |
7 | + | |
8 | + def gamification_plugin_badges | |
9 | + GamificationPlugin::Badge.from("#{gamification_plugin_organization_badges.union(gamification_plugin_environment_badges).to_sql} as #{GamificationPlugin::Badge.table_name}") | |
10 | + end | |
6 | 11 | |
7 | 12 | end | ... | ... |
lib/gamification_plugin/api.rb
... | ... | @@ -57,7 +57,7 @@ class GamificationPlugin::API < Grape::API |
57 | 57 | get ':id/points_by_profile' do |
58 | 58 | person = environment.people.visible_for_person(current_person).find_by_id(params[:id]) |
59 | 59 | return not_found! if person.blank? |
60 | - {points: person.points_by_type(params[:profile]) } | |
60 | + {points: person.points_by_profile(params[:profile]) } | |
61 | 61 | end |
62 | 62 | |
63 | 63 | get ':id/points_out_of_profiles' do | ... | ... |
lib/gamification_plugin/dashboard_helper.rb
... | ... | @@ -12,10 +12,19 @@ module GamificationPlugin::DashboardHelper |
12 | 12 | end |
13 | 13 | |
14 | 14 | def score_point_category(point) |
15 | - point = GamificationPlugin::PointsType.where(name: point.score.category).first | |
15 | + point = GamificationPlugin::PointsType.where(id: point.score.category).first | |
16 | 16 | point.nil? ? '' : point.description |
17 | 17 | end |
18 | 18 | |
19 | + def score_point_target_link(point, text) | |
20 | + url = Merit::PointRules.target_url(point) | |
21 | + url.present? ? link_to(text, url) : text | |
22 | + end | |
23 | + | |
24 | + def score_point_action_class(point) | |
25 | + point.undo_rule? ? 'undo_action':'do_action' | |
26 | + end | |
27 | + | |
19 | 28 | def ranking(target, from_date=nil, limit=10) |
20 | 29 | # FIXME move these queries to profile model |
21 | 30 | ranking = Profile.select('profiles.*, sum(num_points) as gamification_points, ROW_NUMBER() OVER(order by sum(num_points) DESC) as gamification_position').joins(:sash => {:scores => :score_points}).where(:type => target.class).order('sum(num_points) DESC').group('profiles.id') |
... | ... | @@ -35,4 +44,15 @@ module GamificationPlugin::DashboardHelper |
35 | 44 | (context_ranking.blank? ? '' : render(:partial => 'gamification/ranking', :locals => {:ranking => context_ranking, :target_ranking => target_ranking, :ranking_class => 'context'})) |
36 | 45 | end |
37 | 46 | |
47 | + def badges_title(owner) | |
48 | + return _('Badges for %s' % owner.name) if owner.kind_of?(Organization) | |
49 | + _('Badges') | |
50 | + end | |
51 | + | |
52 | + def grouped_badges | |
53 | + environment.gamification_plugin_badges.all.group_by(&:owner).sort do |a, b| | |
54 | + a.first.kind_of?(Environment) ? -1 : a.first.name <=> b.first.name | |
55 | + end | |
56 | + end | |
57 | + | |
38 | 58 | end | ... | ... |
lib/merit/badge_rules.rb
... | ... | @@ -14,6 +14,7 @@ module Merit |
14 | 14 | action: 'comment#create', |
15 | 15 | default_threshold: 5, |
16 | 16 | to: :author, |
17 | + target_profile: lambda {|comment| comment.profile }, | |
17 | 18 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
18 | 19 | } |
19 | 20 | ], |
... | ... | @@ -22,6 +23,7 @@ module Merit |
22 | 23 | action: 'comment#create', |
23 | 24 | default_threshold: 5, |
24 | 25 | to: lambda {|comment| comment.source.author}, |
26 | + target_profile: lambda {|comment| comment.profile }, | |
25 | 27 | value: lambda { |comment, author| author.present? ? Comment.where(source_id: Article.where(author_id: author.id)).count : 0 } |
26 | 28 | } |
27 | 29 | ], |
... | ... | @@ -30,6 +32,7 @@ module Merit |
30 | 32 | action: 'article#create', |
31 | 33 | default_threshold: 5, |
32 | 34 | to: :author, |
35 | + target_profile: lambda {|article| article.profile }, | |
33 | 36 | value: lambda { |article, author| author.present? ? TextArticle.where(author_id: author.id).count : 0 } |
34 | 37 | }, |
35 | 38 | ], |
... | ... | @@ -38,6 +41,7 @@ module Merit |
38 | 41 | action: 'vote#create', |
39 | 42 | default_threshold: 5, |
40 | 43 | to: lambda {|vote| vote.voteable.author}, |
44 | + target_profile: lambda {|vote| vote.voteable.profile }, | |
41 | 45 | value: lambda { |vote, author| vote.voteable ? Vote.for_voteable(vote.voteable).where('vote > 0').count : 0} |
42 | 46 | } |
43 | 47 | ], |
... | ... | @@ -46,6 +50,7 @@ module Merit |
46 | 50 | action: 'vote#create', |
47 | 51 | default_threshold: 5, |
48 | 52 | to: lambda {|vote| vote.voteable.author}, |
53 | + target_profile: lambda {|vote| vote.voteable.profile }, | |
49 | 54 | value: lambda { |vote, author| Vote.for_voteable(vote.voteable).where('vote < 0').count } |
50 | 55 | } |
51 | 56 | ], |
... | ... | @@ -54,6 +59,7 @@ module Merit |
54 | 59 | action: 'vote#create', |
55 | 60 | default_threshold: 5, |
56 | 61 | to: lambda {|vote| vote.voter}, |
62 | + target_profile: lambda {|vote| vote.voteable.profile }, | |
57 | 63 | value: lambda { |vote, voter| voter ? Vote.for_voter(voter).count : 0 } |
58 | 64 | } |
59 | 65 | ], |
... | ... | @@ -65,6 +71,7 @@ module Merit |
65 | 71 | value: lambda { |friendship, person| person.friends.count } |
66 | 72 | } |
67 | 73 | ], |
74 | + manual: [], | |
68 | 75 | |
69 | 76 | #FIXME review the name of the badges and see a way to make it generic |
70 | 77 | creative: [ |
... | ... | @@ -72,12 +79,14 @@ module Merit |
72 | 79 | action: 'comment#create', |
73 | 80 | default_threshold: 5, |
74 | 81 | to: :author, |
82 | + target_profile: lambda {|comment| comment.profile }, | |
75 | 83 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
76 | 84 | }, |
77 | 85 | { |
78 | 86 | action: 'article#create', |
79 | 87 | default_threshold: 5, |
80 | 88 | to: :author, |
89 | + target_profile: lambda {|article| article.profile }, | |
81 | 90 | value: lambda { |article, author| author.present? ? author.articles.count : 0 } |
82 | 91 | }, |
83 | 92 | ], |
... | ... | @@ -86,6 +95,7 @@ module Merit |
86 | 95 | action: 'articlefollower#create', |
87 | 96 | default_threshold: 5, |
88 | 97 | to: lambda {|article| article.person }, |
98 | + target_profile: lambda {|article_follower| article_follower.article.profile }, | |
89 | 99 | model: 'ArticleFollower', |
90 | 100 | value: lambda { |article, person| person.present? ? person.article_followers.count : 0 } |
91 | 101 | } |
... | ... | @@ -95,12 +105,14 @@ module Merit |
95 | 105 | action: 'Vote#create', |
96 | 106 | default_threshold: 5, |
97 | 107 | to: lambda { |vote| vote.voter }, |
108 | + target_profile: lambda {|vote| vote.voteable.profile }, | |
98 | 109 | value: lambda { |vote, voter| Vote.for_voter(voter).count } |
99 | 110 | }, |
100 | 111 | { |
101 | 112 | action: 'Event#create', |
102 | 113 | default_threshold: 5, |
103 | 114 | to: lambda { |article| article.author }, |
115 | + target_profile: lambda {|article| article.profile }, | |
104 | 116 | value: lambda { |event, author| author.events.count } |
105 | 117 | }, |
106 | 118 | ], |
... | ... | @@ -109,12 +121,14 @@ module Merit |
109 | 121 | action: 'vote#create', |
110 | 122 | default_threshold: 5, |
111 | 123 | to: lambda {|vote| vote.voter}, |
124 | + target_profile: lambda {|vote| vote.voteable.profile }, | |
112 | 125 | value: lambda { |vote, voter| voter ? voter.votes.where('vote > 0').count : 0 } |
113 | 126 | }, |
114 | 127 | { |
115 | 128 | action: 'comment#create', |
116 | 129 | default_threshold: 5, |
117 | 130 | to: :author, |
131 | + target_profile: lambda {|comment| comment.profile }, | |
118 | 132 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
119 | 133 | } |
120 | 134 | ], |
... | ... | @@ -123,6 +137,7 @@ module Merit |
123 | 137 | action: 'articlefollower#create', |
124 | 138 | default_threshold: 5, |
125 | 139 | to: :person, |
140 | + target_profile: lambda {|article_follower| article_follower.article.profile }, | |
126 | 141 | model: 'ArticleFollower', |
127 | 142 | value: lambda { |article_follower, person| person.present? ? person.article_followers.count : 0 } |
128 | 143 | }, |
... | ... | @@ -130,11 +145,28 @@ module Merit |
130 | 145 | action: 'comment#create', |
131 | 146 | default_threshold: 5, |
132 | 147 | to: :author, |
148 | + target_profile: lambda {|comment| comment.profile }, | |
133 | 149 | value: lambda { |comment, author| author.present? ? author.comments.count : 0 } |
134 | 150 | }, |
135 | 151 | ] |
136 | 152 | } |
137 | 153 | |
154 | + def target_author(source, setting) | |
155 | + if setting[:to].is_a? Symbol | |
156 | + source.send(setting[:to]) | |
157 | + else | |
158 | + setting[:to].call(source) rescue nil | |
159 | + end | |
160 | + end | |
161 | + | |
162 | + def target_profile(source, setting) | |
163 | + setting[:target_profile].present? ? setting[:target_profile].call(source) : nil | |
164 | + end | |
165 | + | |
166 | + def check_organization_badge(badge, source, setting) | |
167 | + !badge.owner.kind_of?(Organization) || badge.owner == target_profile(source, setting) | |
168 | + end | |
169 | + | |
138 | 170 | def initialize(environment=nil) |
139 | 171 | return if environment.nil? |
140 | 172 | @environment = environment |
... | ... | @@ -142,7 +174,7 @@ module Merit |
142 | 174 | rules = AVAILABLE_RULES |
143 | 175 | rules.merge! CONFERENCE_RULES if defined? CONFERENCE_RULES |
144 | 176 | |
145 | - environment.gamification_plugin_badges.all.each do |badge| | |
177 | + environment.gamification_plugin_badges.each do |badge| | |
146 | 178 | next if rules[badge.name.to_sym].nil? |
147 | 179 | rules[badge.name.to_sym].each do |setting| |
148 | 180 | options = {badge: badge.name, level: badge.level, to: setting[:to]} |
... | ... | @@ -150,18 +182,11 @@ module Merit |
150 | 182 | grant_on setting[:action], options do |source| |
151 | 183 | can_be_granted = true |
152 | 184 | rules[badge.name.to_sym].each do |s| |
153 | - if setting[:to].is_a? Symbol | |
154 | - to = source.send(setting[:to]) | |
155 | - else | |
156 | - begin | |
157 | - to = setting[:to].call(source) | |
158 | - rescue | |
159 | - to = nil | |
160 | - end | |
161 | - end | |
162 | - # pass source and to for different situations | |
185 | + to = target_author(source, setting) | |
186 | + # pass source and to for different situations | |
163 | 187 | action = (badge.custom_fields || {}).fetch(s[:action], {}) |
164 | 188 | can_be_granted &= s[:value].call(source, to) >= action.fetch(:threshold, s[:default_threshold]).to_i |
189 | + can_be_granted &= check_organization_badge(badge, source, setting) | |
165 | 190 | end |
166 | 191 | can_be_granted |
167 | 192 | end | ... | ... |
lib/merit/point_rules.rb
... | ... | @@ -11,6 +11,7 @@ module Merit |
11 | 11 | description: _('Comment author'), |
12 | 12 | default_weight: 40, |
13 | 13 | target_profile: lambda {|comment| comment.source.profile }, |
14 | + target_url: lambda {|comment| comment.url}, | |
14 | 15 | }, |
15 | 16 | comment_article_author: { |
16 | 17 | action: 'comment#create', |
... | ... | @@ -20,6 +21,7 @@ module Merit |
20 | 21 | description: _('Article author of a comment'), |
21 | 22 | default_weight: 50, |
22 | 23 | target_profile: lambda {|comment| comment.source.profile }, |
24 | + target_url: lambda {|comment| comment.url}, | |
23 | 25 | }, |
24 | 26 | comment_article: { |
25 | 27 | action: 'comment#create', |
... | ... | @@ -29,6 +31,7 @@ module Merit |
29 | 31 | description: _('Source article of a comment'), |
30 | 32 | default_weight: 50, |
31 | 33 | target_profile: lambda {|comment| comment.source.profile }, |
34 | + target_url: lambda {|comment| comment.url}, | |
32 | 35 | }, |
33 | 36 | comment_community: { |
34 | 37 | action: 'comment#create', |
... | ... | @@ -38,7 +41,8 @@ module Merit |
38 | 41 | description: _('Article community of a comment'), |
39 | 42 | default_weight: 50, |
40 | 43 | target_profile: lambda {|comment| comment.source.profile }, |
41 | - condition: lambda {|comment, profile| comment.profile.community?} | |
44 | + condition: lambda {|comment, profile| comment.profile.community?}, | |
45 | + target_url: lambda {|comment| comment.url}, | |
42 | 46 | }, |
43 | 47 | article_author: { |
44 | 48 | action: 'article#create', |
... | ... | @@ -48,6 +52,7 @@ module Merit |
48 | 52 | description: _('Article author'), |
49 | 53 | default_weight: 50, |
50 | 54 | target_profile: lambda {|article| article.profile }, |
55 | + target_url: lambda {|article| article.url}, | |
51 | 56 | }, |
52 | 57 | article_community: { |
53 | 58 | action: 'article#create', |
... | ... | @@ -57,7 +62,8 @@ module Merit |
57 | 62 | description: _('Article community'), |
58 | 63 | default_weight: 10, |
59 | 64 | target_profile: lambda {|article| article.profile }, |
60 | - condition: lambda {|article, profile| article.profile.present? and article.profile.community? } | |
65 | + condition: lambda {|article, profile| article.profile.present? and article.profile.community? }, | |
66 | + target_url: lambda {|article| article.url}, | |
61 | 67 | }, |
62 | 68 | vote_voteable_author: { |
63 | 69 | action: 'vote#create', |
... | ... | @@ -67,6 +73,7 @@ module Merit |
67 | 73 | description: _('Author of a voted content'), |
68 | 74 | default_weight: 20, |
69 | 75 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, |
76 | + target_url: lambda {|vote| vote.voteable.url}, | |
70 | 77 | }, |
71 | 78 | vote_voteable: { |
72 | 79 | action: 'vote#create', |
... | ... | @@ -76,6 +83,7 @@ module Merit |
76 | 83 | description: _('Voted content'), |
77 | 84 | default_weight: 30, |
78 | 85 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, |
86 | + target_url: lambda {|vote| vote.voteable.url}, | |
79 | 87 | }, |
80 | 88 | vote_voter: { |
81 | 89 | action: 'vote#create', |
... | ... | @@ -85,6 +93,7 @@ module Merit |
85 | 93 | description: _('Voter'), |
86 | 94 | default_weight: 10, |
87 | 95 | target_profile: lambda {|vote| vote.voteable.present? ? vote.voteable.profile : nil }, |
96 | + target_url: lambda {|vote| vote.voteable.url}, | |
88 | 97 | }, |
89 | 98 | friends: { |
90 | 99 | action: 'friendship#create', |
... | ... | @@ -150,6 +159,7 @@ module Merit |
150 | 159 | end |
151 | 160 | |
152 | 161 | def profile_condition(setting, target, profile) |
162 | + return false if target == true | |
153 | 163 | profile.nil? || setting[:target_profile].blank? || setting[:target_profile].call(target) == profile |
154 | 164 | end |
155 | 165 | |
... | ... | @@ -163,6 +173,15 @@ module Merit |
163 | 173 | end |
164 | 174 | end |
165 | 175 | |
176 | + def self.target_url(point) | |
177 | + rule_name = point.point_type.present? ? point.point_type.name : point.score.category | |
178 | + target_url = AVAILABLE_RULES[rule_name.to_sym][:target_url] | |
179 | + return nil if target_url.blank? || point.action.blank? | |
180 | + | |
181 | + model = BaseTargetFinder.new(Merit::Rule.new, point.action).get_target_from_database | |
182 | + model.present? ? target_url.call(model) : nil | |
183 | + end | |
184 | + | |
166 | 185 | def initialize(environment=nil) |
167 | 186 | return if environment.nil? |
168 | 187 | @environment = environment | ... | ... |
lib/merit_ext.rb
... | ... | @@ -17,6 +17,15 @@ module Merit |
17 | 17 | class Score |
18 | 18 | class Point |
19 | 19 | belongs_to :action |
20 | + | |
21 | + def point_type | |
22 | + @point_type ||= GamificationPlugin::PointsType.where(id: score.category).first | |
23 | + end | |
24 | + | |
25 | + def undo_rule? | |
26 | + rule = Merit::PointRules::AVAILABLE_RULES[point_type.name.to_sym] | |
27 | + rule[:undo_action] == "#{action.target_model}##{action.action_method}" | |
28 | + end | |
20 | 29 | end |
21 | 30 | end |
22 | 31 | ... | ... |
models/gamification_plugin/points_categorization.rb
1 | -class GamificationPlugin::PointsCategorization < Noosfero::Plugin::ActiveRecord | |
1 | +class GamificationPlugin::PointsCategorization < ActiveRecord::Base | |
2 | 2 | belongs_to :profile |
3 | 3 | belongs_to :point_type, class_name: 'GamificationPlugin::PointsType', foreign_key: :point_type_id |
4 | 4 | attr_accessible :profile_id, :profile, :point_type_id, :weight |
... | ... | @@ -10,5 +10,5 @@ class GamificationPlugin::PointsCategorization < Noosfero::Plugin::ActiveRecord |
10 | 10 | scope :for_type, lambda { |p_type| joins(:point_type).where(gamification_plugin_points_types: {name: p_type}) } |
11 | 11 | scope :for_profile, lambda { |p_profile| joins(:profile).where(profiles: {identifier: p_profile}) } |
12 | 12 | |
13 | - scope :grouped_profiles, select(:profile_id).group(:profile_id).includes(:profile) | |
13 | + scope :grouped_profiles, -> { select(:profile_id).group(:profile_id).includes(:profile) } | |
14 | 14 | end | ... | ... |
models/gamification_plugin/points_type.rb
public/admin.css
public/admin.js
... | ... | @@ -13,6 +13,11 @@ var gamificationPluginAdmin = { |
13 | 13 | var name = jQuery('#gamification-plugin-form-badge-name').find('option:selected').text(); |
14 | 14 | jQuery('.name_'+name).show(); |
15 | 15 | jQuery('.name_'+name).find('input').removeAttr('disabled'); |
16 | + if(jQuery('.name_'+name).children().length>0) { | |
17 | + jQuery('.action-fields').show(); | |
18 | + } else { | |
19 | + jQuery('.action-fields').hide(); | |
20 | + } | |
16 | 21 | } |
17 | 22 | |
18 | 23 | } | ... | ... |
public/style.css
test/functional/gamification_plugin_badges_controller_test.rb
... | ... | @@ -25,6 +25,14 @@ class GamificationPluginBadgesControllerTest < ActionController::TestCase |
25 | 25 | end |
26 | 26 | end |
27 | 27 | |
28 | + should "should create gamification_plugin_badge with organization as owner" do | |
29 | + organization = fast_create(Organization) | |
30 | + assert_difference('GamificationPlugin::Badge.count') do | |
31 | + post :create, gamification_plugin_badge: { description: @gamification_plugin_badge.description, level: @gamification_plugin_badge.level, name: @gamification_plugin_badge.name, custom_fields: {threshold: @gamification_plugin_badge.threshold}, owner_id: organization.id } | |
32 | + assert_equal organization, GamificationPlugin::Badge.last.owner | |
33 | + end | |
34 | + end | |
35 | + | |
28 | 36 | should "should show gamification_plugin_badge" do |
29 | 37 | get :show, id: @gamification_plugin_badge |
30 | 38 | assert_response :success |
... | ... | @@ -40,6 +48,23 @@ class GamificationPluginBadgesControllerTest < ActionController::TestCase |
40 | 48 | assert assigns(:gamification_plugin_badge) |
41 | 49 | end |
42 | 50 | |
51 | + should "should change badge owner" do | |
52 | + organization = fast_create(Organization) | |
53 | + put :update, id: @gamification_plugin_badge, gamification_plugin_badge: { description: @gamification_plugin_badge.description, level: @gamification_plugin_badge.level, name: @gamification_plugin_badge.name, custom_fields: {threshold: @gamification_plugin_badge.threshold}, owner_id: organization.id } | |
54 | + assert assigns(:gamification_plugin_badge) | |
55 | + assert_equal organization, @gamification_plugin_badge.reload.owner | |
56 | + end | |
57 | + | |
58 | + should "should keep badge owner when update" do | |
59 | + organization = fast_create(Organization) | |
60 | + @gamification_plugin_badge.owner = organization | |
61 | + @gamification_plugin_badge.save! | |
62 | + | |
63 | + put :update, id: @gamification_plugin_badge, gamification_plugin_badge: { description: @gamification_plugin_badge.description, level: @gamification_plugin_badge.level, name: @gamification_plugin_badge.name, custom_fields: {threshold: @gamification_plugin_badge.threshold}, owner_id: organization.id } | |
64 | + assert assigns(:gamification_plugin_badge) | |
65 | + assert_equal organization, @gamification_plugin_badge.reload.owner | |
66 | + end | |
67 | + | |
43 | 68 | should "should destroy gamification_plugin_badge" do |
44 | 69 | assert_difference('GamificationPlugin::Badge.count', -1) do |
45 | 70 | delete :destroy, id: @gamification_plugin_badge | ... | ... |
test/functional/gamification_plugin_profile_controller_test.rb
... | ... | @@ -11,12 +11,13 @@ class GamificationPluginProfileControllerTest < ActionController::TestCase |
11 | 11 | attr_accessor :person, :environment |
12 | 12 | |
13 | 13 | should 'display points in gamification dashboard' do |
14 | - person.add_points(20, :category => :comment_author) | |
15 | - person.add_points(30, :category => :article_author) | |
14 | + create_all_point_rules | |
15 | + article = create(TextArticle, :profile_id => fast_create(Community).id, :author => person) | |
16 | + create(Comment, :source => article, :author_id => create_user.person.id) | |
16 | 17 | get :dashboard, :profile => person.identifier |
17 | - assert_tag :div, :attributes => {:class => 'score article_author positive'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => '30'} | |
18 | - assert_tag :div, :attributes => {:class => 'score comment_author positive'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => '20'} | |
19 | - assert_tag :div, :attributes => {:class => 'score total'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => '50'} | |
18 | + assert_tag :div, :attributes => {:class => 'score article_author positive do_action'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => default_point_weight(:article_author).to_s} | |
19 | + assert_tag :div, :attributes => {:class => 'score comment_article_author positive do_action'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => default_point_weight(:comment_article_author).to_s} | |
20 | + assert_tag :div, :attributes => {:class => 'score total'}, :child => {:tag => 'span', :attributes => {:class => 'value'}, :content => (default_point_weight(:comment_article_author) + default_point_weight(:article_author)).to_s} | |
20 | 21 | end |
21 | 22 | |
22 | 23 | should 'display level in gamification dashboard' do | ... | ... |
test/test_helper.rb
... | ... | @@ -15,6 +15,10 @@ def create_all_point_rules |
15 | 15 | end |
16 | 16 | end |
17 | 17 | |
18 | +def default_point_weight(rule_name) | |
19 | + Merit::PointRules::AVAILABLE_RULES[rule_name][:default_weight] | |
20 | +end | |
21 | + | |
18 | 22 | def load_point_rule(rule_name, config) |
19 | 23 | rule_config = Merit::PointRules::AVAILABLE_RULES[rule_name.to_sym] |
20 | 24 | raise "Point rule '#{rule_name}' is not available" if rule_config.nil? |
... | ... | @@ -22,7 +26,7 @@ def load_point_rule(rule_name, config) |
22 | 26 | rule_config |
23 | 27 | end |
24 | 28 | |
25 | -#person_points_debug(person) | |
29 | +#person_points_debug(person) | |
26 | 30 | def person_points_debug(person) |
27 | 31 | person.score_points.map do |sp| |
28 | 32 | puts 'Ponto:' | ... | ... |
test/unit/api_test.rb
... | ... | @@ -8,6 +8,7 @@ class APITest < ActiveSupport::TestCase |
8 | 8 | environment = Environment.default |
9 | 9 | environment.enable_plugin(GamificationPlugin) |
10 | 10 | GamificationPlugin.gamification_set_rules(@environment) |
11 | + create_all_point_rules | |
11 | 12 | end |
12 | 13 | |
13 | 14 | should 'get my own badges' do |
... | ... | @@ -27,14 +28,6 @@ class APITest < ActiveSupport::TestCase |
27 | 28 | assert_not_nil json['percent'] |
28 | 29 | end |
29 | 30 | |
30 | - should 'get my total pontuation' do | |
31 | - badge = GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') | |
32 | - person.add_badge(badge.id) | |
33 | - get "/api/v1/gamification_plugin/my/points?#{params.to_query}" | |
34 | - json = JSON.parse(last_response.body) | |
35 | - assert_not_nil json['points'] | |
36 | - end | |
37 | - | |
38 | 31 | should 'get badges of the public person' do |
39 | 32 | badge = GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') |
40 | 33 | another_person = create(User, :environment => environment).person |
... | ... | @@ -76,4 +69,95 @@ class APITest < ActiveSupport::TestCase |
76 | 69 | assert_equal 404, last_response.status |
77 | 70 | end |
78 | 71 | |
72 | + should 'get amount of environment badges grouped by name' do | |
73 | + 3.times { GamificationPlugin::Badge.create!(:owner => environment, :name => 'test_badge') } | |
74 | + get "/api/v1/gamification_plugin/badges" | |
75 | + json = JSON.parse(last_response.body) | |
76 | + assert_equal 3, json['test_badge'] | |
77 | + end | |
78 | + | |
79 | + should 'get my points' do | |
80 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | |
81 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | |
82 | + | |
83 | + get "/api/v1/gamification_plugin/my/points?#{params.to_query}" | |
84 | + json = JSON.parse(last_response.body) | |
85 | + assert_equal default_point_weight(:article_author) + default_point_weight(:comment_article_author), json['points'] | |
86 | + end | |
87 | + | |
88 | + should 'get my points filtered by type' do | |
89 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | |
90 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | |
91 | + params[:type] = 'article_author' | |
92 | + | |
93 | + get "/api/v1/gamification_plugin/my/points_by_type?#{params.to_query}" | |
94 | + json = JSON.parse(last_response.body) | |
95 | + assert_equal default_point_weight(:article_author), json['points'] | |
96 | + end | |
97 | + | |
98 | + should 'get my points filtered by profile' do | |
99 | + community = fast_create(Community) | |
100 | + create_point_rule_definition('article_author', community) | |
101 | + create(TextArticle, :profile_id => @person.id, :author => @person) | |
102 | + create(TextArticle, :profile_id => community.id, :author => @person) | |
103 | + params[:profile] = community.identifier | |
104 | + | |
105 | + get "/api/v1/gamification_plugin/my/points_by_profile?#{params.to_query}" | |
106 | + json = JSON.parse(last_response.body) | |
107 | + assert_equal default_point_weight(:article_author), json['points'] | |
108 | + end | |
109 | + | |
110 | + should 'get my points excluding points earned in profiles' do | |
111 | + community = fast_create(Community) | |
112 | + create_point_rule_definition('article_author', community) | |
113 | + create(TextArticle, :profile_id => @person.id, :author => @person) | |
114 | + create(TextArticle, :profile_id => community.id, :author => @person) | |
115 | + | |
116 | + get "/api/v1/gamification_plugin/my/points_out_of_profiles?#{params.to_query}" | |
117 | + json = JSON.parse(last_response.body) | |
118 | + assert_equal 2*default_point_weight(:article_author), json['points'] | |
119 | + end | |
120 | + | |
121 | + should 'get points of a person' do | |
122 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | |
123 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | |
124 | + | |
125 | + get "/api/v1/gamification_plugin/people/#{person.id}/points?#{params.to_query}" | |
126 | + json = JSON.parse(last_response.body) | |
127 | + assert_equal default_point_weight(:article_author) + default_point_weight(:comment_article_author), json['points'] | |
128 | + end | |
129 | + | |
130 | + should 'get points of a person filtered by type' do | |
131 | + article = create(TextArticle, :profile_id => @person.id, :author => @person) | |
132 | + create(Comment, :source_id => article.id, :author => fast_create(Person)) | |
133 | + params[:type] = 'article_author' | |
134 | + | |
135 | + get "/api/v1/gamification_plugin/people/#{@person.id}/points_by_type?#{params.to_query}" | |
136 | + json = JSON.parse(last_response.body) | |
137 | + assert_equal default_point_weight(:article_author), json['points'] | |
138 | + end | |
139 | + | |
140 | + should 'get points of a person filtered by profile' do | |
141 | + community = fast_create(Community) | |
142 | + create_point_rule_definition('article_author', community) | |
143 | + create(TextArticle, :profile_id => @person.id, :author => @person) | |
144 | + create(TextArticle, :profile_id => community.id, :author => @person) | |
145 | + params[:profile] = community.identifier | |
146 | + | |
147 | + get "/api/v1/gamification_plugin/people/#{@person.id}/points_by_profile?#{params.to_query}" | |
148 | + json = JSON.parse(last_response.body) | |
149 | + assert_equal default_point_weight(:article_author), json['points'] | |
150 | + end | |
151 | + | |
152 | + should 'get points of a person excluding points earned in profiles' do | |
153 | + community = fast_create(Community) | |
154 | + create_point_rule_definition('article_author', community) | |
155 | + create(TextArticle, :profile_id => @person.id, :author => @person) | |
156 | + create(TextArticle, :profile_id => community.id, :author => @person) | |
157 | + | |
158 | + get "/api/v1/gamification_plugin/people/#{@person.id}/points_out_of_profiles?#{params.to_query}" | |
159 | + json = JSON.parse(last_response.body) | |
160 | + assert_equal 2*default_point_weight(:article_author), json['points'] | |
161 | + end | |
162 | + | |
79 | 163 | end | ... | ... |
test/unit/article_test.rb
... | ... | @@ -189,4 +189,24 @@ class ArticleTest < ActiveSupport::TestCase |
189 | 189 | end |
190 | 190 | end |
191 | 191 | |
192 | + should "add organization's merit badge to author when create 5 new articles" do | |
193 | + organization = fast_create(Organization) | |
194 | + GamificationPlugin::Badge.create!(:owner => organization, :name => 'article_author', :level => 1) | |
195 | + GamificationPlugin.gamification_set_rules(environment) | |
196 | + | |
197 | + 5.times { create(TextArticle, :profile_id => organization.id, :author => person) } | |
198 | + assert_equal 'article_author', person.badges.first.name | |
199 | + assert_equal 1, person.badges.first.level | |
200 | + end | |
201 | + | |
202 | + should "do not earn organization's badge when the article is not posted in the organization itself" do | |
203 | + organization = fast_create(Organization) | |
204 | + other_organization = fast_create(Organization) | |
205 | + GamificationPlugin::Badge.create!(:owner => organization, :name => 'article_author', :level => 1) | |
206 | + GamificationPlugin.gamification_set_rules(environment) | |
207 | + | |
208 | + 5.times { create(TextArticle, :profile_id => other_organization.id, :author => person) } | |
209 | + assert_equal [], person.badges | |
210 | + end | |
211 | + | |
192 | 212 | end | ... | ... |
... | ... | @@ -0,0 +1,48 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class BadgeRulesTest < ActiveSupport::TestCase | |
4 | + | |
5 | + def setup | |
6 | + @environment = Environment.default | |
7 | + end | |
8 | + | |
9 | + attr_accessor :environment | |
10 | + | |
11 | + should "define badge rules for environment's badges" do | |
12 | + badge = GamificationPlugin::Badge.create!(:owner => environment, :name => :comment_author) | |
13 | + badge_rules = Merit::BadgeRules.new(environment) | |
14 | + assert_equal [Merit::BadgeRules::AVAILABLE_RULES[badge.name].first[:action]], badge_rules.defined_rules.keys | |
15 | + end | |
16 | + | |
17 | + should "define badge rules for organization's badges" do | |
18 | + organization = fast_create(Organization) | |
19 | + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author) | |
20 | + badge_rules = Merit::BadgeRules.new(environment) | |
21 | + assert_equal [Merit::BadgeRules::AVAILABLE_RULES[badge.name].first[:action]], badge_rules.defined_rules.keys | |
22 | + end | |
23 | + | |
24 | + should 'check organization returns true when badge belongs to the environment' do | |
25 | + badge = GamificationPlugin::Badge.create!(:owner => environment, :name => :comment_author) | |
26 | + badge_rules = Merit::BadgeRules.new(environment) | |
27 | + comment = fast_create(Comment) | |
28 | + assert badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name].first) | |
29 | + end | |
30 | + | |
31 | + should 'check organization returns true when the comment belongs to the organization' do | |
32 | + organization = fast_create(Organization) | |
33 | + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author) | |
34 | + badge_rules = Merit::BadgeRules.new(environment) | |
35 | + article = fast_create(Article,:profile_id => organization.id) | |
36 | + comment = fast_create(Comment, :source_id => article.id) | |
37 | + assert badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name].first) | |
38 | + end | |
39 | + | |
40 | + should 'check organization returns false when the comment does not belongs to the organization' do | |
41 | + organization = fast_create(Organization) | |
42 | + badge = GamificationPlugin::Badge.create!(:owner => organization, :name => :comment_author) | |
43 | + badge_rules = Merit::BadgeRules.new(environment) | |
44 | + comment = fast_create(Comment) | |
45 | + assert !badge_rules.check_organization_badge(badge, comment, Merit::BadgeRules::AVAILABLE_RULES[badge.name].first) | |
46 | + end | |
47 | + | |
48 | +end | ... | ... |
test/unit/badge_test.rb
... | ... | @@ -5,9 +5,10 @@ class BadgeTest < ActiveSupport::TestCase |
5 | 5 | def setup |
6 | 6 | @person = create_user('testuser').person |
7 | 7 | @environment = Environment.default |
8 | + @organization = fast_create(Organization) | |
8 | 9 | end |
9 | 10 | |
10 | - attr_accessor :person, :environment | |
11 | + attr_accessor :person, :environment, :organization | |
11 | 12 | |
12 | 13 | should 'add badge to person' do |
13 | 14 | badge = GamificationPlugin::Badge.create!(:owner => environment) |
... | ... | @@ -37,4 +38,16 @@ class BadgeTest < ActiveSupport::TestCase |
37 | 38 | assert_equal [badge2], person.badges.notification_pending |
38 | 39 | end |
39 | 40 | |
41 | + should 'add badge to person with organization as the badge owner' do | |
42 | + badge = GamificationPlugin::Badge.create(:owner => organization) | |
43 | + person.add_badge(badge.id) | |
44 | + assert_equal [badge], person.badges | |
45 | + end | |
46 | + | |
47 | + should 'add a manual badge to person' do | |
48 | + badge = GamificationPlugin::Badge.create!(:name => :manual, :owner => environment) | |
49 | + person.add_badge(badge.id) | |
50 | + assert_equal [badge], person.badges | |
51 | + end | |
52 | + | |
40 | 53 | end | ... | ... |
test/unit/comment_test.rb
... | ... | @@ -276,5 +276,14 @@ class CommentTest < ActiveSupport::TestCase |
276 | 276 | end |
277 | 277 | end |
278 | 278 | |
279 | + should "add organization's merit badge to author when create 5 new comments" do | |
280 | + organization = fast_create(Organization) | |
281 | + GamificationPlugin::Badge.create!(:owner => organization, :name => 'comment_author') | |
282 | + GamificationPlugin.gamification_set_rules(environment) | |
283 | + article.profile = organization | |
284 | + | |
285 | + 5.times { create(Comment, :source => article, :author_id => person.id) } | |
286 | + assert_equal 'comment_author', person.badges.first.name | |
287 | + end | |
279 | 288 | |
280 | 289 | end | ... | ... |
... | ... | @@ -0,0 +1,34 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class DashboardHelperTest < ActiveSupport::TestCase | |
4 | + | |
5 | + include GamificationPlugin::DashboardHelper | |
6 | + | |
7 | + should 'return title for global badges' do | |
8 | + owner = Environment.new | |
9 | + assert_equal 'Badges', badges_title(owner) | |
10 | + end | |
11 | + | |
12 | + should 'return title for organization badges' do | |
13 | + owner = Organization.new(:name => 'organization') | |
14 | + assert_equal 'Badges for organization', badges_title(owner) | |
15 | + end | |
16 | + | |
17 | + should 'return badges grouped by owner' do | |
18 | + environment = Environment.default | |
19 | + expects(:environment).at_least_once.returns(environment) | |
20 | + badge1 = GamificationPlugin::Badge.create!(:owner => fast_create(Organization)) | |
21 | + badge2 = GamificationPlugin::Badge.create!(:owner => environment) | |
22 | + assert_equal [[badge2.owner, [badge2]], [badge1.owner, [badge1]]], grouped_badges | |
23 | + end | |
24 | + | |
25 | + should 'return category of a score point' do | |
26 | + point_type = GamificationPlugin::PointsType.create!(name: "point category", description: "point category") | |
27 | + score = Merit::Score.new | |
28 | + score.category = point_type.id.to_s | |
29 | + score.save! | |
30 | + point = score.score_points.create! | |
31 | + assert_equal "point category", score_point_category(point) | |
32 | + end | |
33 | + | |
34 | +end | ... | ... |
test/unit/gamification_plugin_test.rb
... | ... | @@ -0,0 +1,27 @@ |
1 | +require_relative "../test_helper" | |
2 | + | |
3 | +class MeritExtTest < ActiveSupport::TestCase | |
4 | + | |
5 | + should 'check if the point was originated by an undo action' do | |
6 | + point = Merit::Score::Point.new | |
7 | + point_type = GamificationPlugin::PointsType.new(name: :comment_author) | |
8 | + point.expects(:point_type).returns(point_type) | |
9 | + action = mock | |
10 | + action.expects(:target_model).returns('comment') | |
11 | + action.expects(:action_method).returns('destroy') | |
12 | + point.expects(:action).at_least_once.returns(action) | |
13 | + assert point.undo_rule? | |
14 | + end | |
15 | + | |
16 | + should 'check if the point was originated by a do action' do | |
17 | + point = Merit::Score::Point.new | |
18 | + point_type = GamificationPlugin::PointsType.new(name: :comment_author) | |
19 | + point.expects(:point_type).returns(point_type) | |
20 | + action = mock | |
21 | + action.expects(:target_model).returns('comment') | |
22 | + action.expects(:action_method).returns('create') | |
23 | + point.expects(:action).at_least_once.returns(action) | |
24 | + assert !point.undo_rule? | |
25 | + end | |
26 | + | |
27 | +end | ... | ... |
test/unit/point_rules_test.rb
... | ... | @@ -19,4 +19,21 @@ class PointRulesTest < ActiveSupport::TestCase |
19 | 19 | assert point_rules.defined_rules.present? |
20 | 20 | end |
21 | 21 | |
22 | + should 'return target url for a point related to article creation' do | |
23 | + person = create_user('testuser').person | |
24 | + create_point_rule_definition('article_author') | |
25 | + article = create(TextArticle, :profile_id => person.id, :author => person) | |
26 | + url = Merit::PointRules.target_url(person.score_points.last) | |
27 | + assert_equal article.url, url | |
28 | + end | |
29 | + | |
30 | + should 'return target url for a point related to comment creation' do | |
31 | + person = create_user('testuser').person | |
32 | + create_point_rule_definition('comment_author') | |
33 | + article = create(Article, :profile_id => person.id, :author => person) | |
34 | + comment = create(Comment, :source_id => article.id, :author => person) | |
35 | + url = Merit::PointRules.target_url(person.score_points.last) | |
36 | + assert_equal comment.url, url | |
37 | + end | |
38 | + | |
22 | 39 | end | ... | ... |
views/gamification/dashboard.html.erb
... | ... | @@ -22,9 +22,9 @@ |
22 | 22 | <div class="scores"> |
23 | 23 | <h3><%= _('Latest Score Points') %></h3> |
24 | 24 | <% @target.score_points.order('created_at desc').limit(5).each do |point| %> |
25 | - <div class="score <%= point.score.category %> <%= score_point_class(point) %>"> | |
25 | + <div class="score <%= point.point_type.name %> <%= score_point_class(point) %> <%= score_point_action_class(point) %>"> | |
26 | 26 | <span class="value"><%= point.num_points %></span> |
27 | - <span class="category"><%= _(score_point_category(point)) %></span> | |
27 | + <span class="category"><%= score_point_target_link point, _(score_point_category(point)) %></span> | |
28 | 28 | <span class="date timeago" title="<%= point.created_at %>"><%= point.created_at %></span> |
29 | 29 | </div> |
30 | 30 | <% end %> |
... | ... | @@ -34,24 +34,26 @@ |
34 | 34 | |
35 | 35 | <% unless environment.gamification_plugin_badges.empty? %> |
36 | 36 | <div class="badges"> |
37 | - <h3><%= _('Badges') %></h3> | |
38 | - <ul class="badge-list"> | |
39 | - <% environment.gamification_plugin_badges.group(:name).count.each do |badge_name, amount| %> | |
40 | - <% person_badge = @target.badges.where(:name => badge_name).last %> | |
41 | - <% badge = environment.gamification_plugin_badges.where(:name => badge_name).last %> | |
42 | - <li class="badge <%= badge.name %>"> | |
43 | - <div class="badge" title="<%= badge.description %>"> | |
44 | - <div class="image <%= badge.name %>"></div> | |
45 | - <ul class="level rating"> | |
46 | - <% 1.upto(badge.level).map do |n|%> | |
47 | - <span class="star <%= (person_badge && person_badge.level >= n) ? 'earned' : 'not-earned' %>" >★</span> | |
48 | - <% end %> | |
49 | - </ul> | |
50 | - <div class="title"><%= badge.title %></div> | |
51 | - </div> | |
52 | - </li> | |
37 | + <% grouped_badges.each do |owner, badges| %> | |
38 | + <h3><%= badges_title owner %></h3> | |
39 | + <ul class="badge-list"> | |
40 | + <% badges.group_by(&:name).each do |badge_name, badges_group| %> | |
41 | + <% badge = badges_group.sort_by(&:level).last %> | |
42 | + <% person_badge = @target.badges.where(:name => badge.name).last %> | |
43 | + <li class="badge <%= badge.name %>"> | |
44 | + <div class="badge" title="<%= badge.description %>"> | |
45 | + <div class="image <%= badge.name %>"></div> | |
46 | + <ul class="level rating"> | |
47 | + <% 1.upto(badge.level).map do |n|%> | |
48 | + <span class="star <%= (person_badge && person_badge.level >= n) ? 'earned' : 'not-earned' %>" >★</span> | |
49 | + <% end %> | |
50 | + </ul> | |
51 | + <div class="title"><%= badge.title %></div> | |
52 | + </div> | |
53 | + </li> | |
54 | + <% end %> | |
55 | + </ul> | |
53 | 56 | <% end %> |
54 | - </ul> | |
55 | 57 | </div> |
56 | 58 | <% end %> |
57 | 59 | </div> | ... | ... |
views/gamification_plugin_badges/_form.html.erb
... | ... | @@ -29,24 +29,31 @@ |
29 | 29 | <%= f.label :level %><br /> |
30 | 30 | <%= f.text_field :level %> |
31 | 31 | </div> |
32 | - <h4><%= _('Actions') %></h4> | |
33 | - <%= f.fields_for :custom_fields do |c| %> | |
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 | - <br> | |
32 | + <div class="field"> | |
33 | + <%= f.label :profile_owner %><br /> | |
34 | + <% tokenized_owner = @gamification_plugin_badge.owner.present? && @gamification_plugin_badge.owner.kind_of?(Organization) ? prepare_to_token_input([@gamification_plugin_badge.owner]) : nil %> | |
35 | + <%= token_input_field_tag('gamification_plugin_badge[owner_id]', 'badge-owner', {:action => 'search_owners'}, {:focus => false, :hint_text => _('Choose a profile or leave it blank for a global badge'), :token_limit => 1, :pre_populate => tokenized_owner}) %> | |
36 | + </div> | |
37 | + <div class="action-fields"> | |
38 | + <h4><%= _('Actions') %></h4> | |
39 | + <%= f.fields_for :custom_fields do |c| %> | |
40 | + <% rules.each do |name, settings| %> | |
41 | + <div class='controller-actions <%= "name_#{name}" %>'> | |
42 | + <% settings.select {|s| s[:action].present?}.each do |setting| %> | |
43 | + <%= c.label _(setting[:action]) %> | |
44 | + <%= c.fields_for setting[:action] do |d| %> | |
45 | + <% action = (@gamification_plugin_badge.custom_fields || {}).fetch(setting[:action], {}) %> | |
46 | + <div class="field"> | |
47 | + <%= d.label :threshold %><br /> | |
48 | + <%= d.text_field :threshold, {value: action.fetch('threshold', "")} %> | |
49 | + </div> | |
50 | + <br> | |
51 | + <% end %> | |
45 | 52 | <% end %> |
46 | - <% end %> | |
47 | - </div> | |
53 | + </div> | |
54 | + <% end %> | |
48 | 55 | <% end %> |
49 | - <% end %> | |
56 | + </div> | |
50 | 57 | <div class="actions"> |
51 | 58 | <%= f.submit %> |
52 | 59 | </div> | ... | ... |
views/gamification_plugin_badges/index.html.erb
1 | +<%= stylesheet_link_tag 'plugins/gamification/admin.css' %> | |
2 | + | |
1 | 3 | <h1><%= _('Gamification Settings: Listing Badges') %></h1> |
2 | 4 | |
3 | -<table> | |
5 | +<table class="gamification-plugin-badges"> | |
4 | 6 | <tr> |
5 | 7 | <th>Name</th> |
6 | 8 | <th>Title</th> |
... | ... | @@ -10,7 +12,11 @@ |
10 | 12 | <th></th> |
11 | 13 | </tr> |
12 | 14 | |
13 | -<% @gamification_plugin_badges.each do |gamification_plugin_badge| %> | |
15 | +<% @gamification_plugin_badges.each do |owner, badges| %> | |
16 | + <% if owner.present? %> | |
17 | + <tr><td class="badge-owner-group" colspan="6"><%= _("Badges for:") %> <%= owner.name %></td></tr> | |
18 | + <% end %> | |
19 | + <% badges.each do |gamification_plugin_badge| %> | |
14 | 20 | <tr> |
15 | 21 | <td><%= gamification_plugin_badge.name %></td> |
16 | 22 | <td><%= gamification_plugin_badge.title %></td> |
... | ... | @@ -19,6 +25,7 @@ |
19 | 25 | <td><%= link_to 'Edit', :action => :edit, :id => gamification_plugin_badge.id %></td> |
20 | 26 | <td><%= button_without_text :delete, _('Remove'), {:action => :destroy, :id => gamification_plugin_badge.id}, :method => :post, :confirm => _('Are you sure?') %></td> |
21 | 27 | </tr> |
28 | + <% end %> | |
22 | 29 | <% end %> |
23 | 30 | </table> |
24 | 31 | ... | ... |
views/gamification_plugin_badges/show.html.erb
... | ... | @@ -22,6 +22,13 @@ |
22 | 22 | <%= @gamification_plugin_badge.level %> |
23 | 23 | </p> |
24 | 24 | |
25 | +<% if @gamification_plugin_badge.owner.kind_of?(Organization) %> | |
26 | +<p> | |
27 | + <b><%= _('Profile owner:') %></b> | |
28 | + <%= @gamification_plugin_badge.owner.name %> | |
29 | + </p> | |
30 | +<% end %> | |
31 | + | |
25 | 32 | <p> |
26 | 33 | <b>Threshold:</b> |
27 | 34 | <% if @gamification_plugin_badge.custom_fields.is_a? Hash %> | ... | ... |