Merge pull request #2311 from vikhyat/badge-system
Add automatically assigned trust level badges
This commit is contained in:
commit
5914d0e132
|
@ -35,7 +35,7 @@ Discourse.Badge = Discourse.Model.extend({
|
|||
@type {String}
|
||||
**/
|
||||
displayName: function() {
|
||||
var i18nKey = "badges." + this.get('i18nNameKey') + ".name";
|
||||
var i18nKey = "badges.badge." + this.get('i18nNameKey') + ".name";
|
||||
return I18n.t(i18nKey, {defaultValue: this.get('name')});
|
||||
}.property('name', 'i18nNameKey'),
|
||||
|
||||
|
@ -46,7 +46,7 @@ Discourse.Badge = Discourse.Model.extend({
|
|||
@type {String}
|
||||
**/
|
||||
translatedDescription: function() {
|
||||
var i18nKey = "badges." + this.get('i18nNameKey') + ".description",
|
||||
var i18nKey = "badges.badge." + this.get('i18nNameKey') + ".description",
|
||||
translation = I18n.t(i18nKey);
|
||||
if (translation.indexOf(i18nKey) !== -1) {
|
||||
translation = null;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
{{#each}}
|
||||
<tr>
|
||||
<td class='badge'>{{user-badge badge=this}}</td>
|
||||
<td class='description'>{{description}}</td>
|
||||
<td class='description'>{{translatedDescription}}</td>
|
||||
<td class='grant-count'>{{i18n badges.granted count=grant_count}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
<table class='badges-listing'>
|
||||
<tr>
|
||||
<td class='badge'>{{user-badge badge=this}}</td>
|
||||
<td class='description'>{{description}}</td>
|
||||
<td class='description'>{{translatedDescription}}</td>
|
||||
<td class='grant-count'>{{i18n badges.granted count=grant_count}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{#link-to 'badges.show' badge}}
|
||||
<span {{bind-attr class=":user-badge badgeTypeClassName" data-badge-name="badge.name" title="badge.description"}}>
|
||||
<span {{bind-attr class=":user-badge badgeTypeClassName" data-badge-name="badge.name" title="badge.translatedDescription"}}>
|
||||
<i class='fa fa-certificate'></i>
|
||||
{{badge.name}}
|
||||
{{badge.displayName}}
|
||||
</span>
|
||||
{{/link-to}}
|
||||
|
|
|
@ -5,6 +5,10 @@ class Badge < ActiveRecord::Base
|
|||
validates :name, presence: true, uniqueness: true
|
||||
validates :badge_type, presence: true
|
||||
validates :allow_title, inclusion: [true, false]
|
||||
|
||||
def self.trust_level_badge_ids
|
||||
(1..4).to_a
|
||||
end
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
|
|
@ -447,6 +447,7 @@ class User < ActiveRecord::Base
|
|||
transaction do
|
||||
self.save!
|
||||
Group.user_trust_level_change!(self.id, self.trust_level)
|
||||
BadgeGranter.update_badges(self, trust_level: trust_level)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -24,9 +24,11 @@ class BadgeGranter
|
|||
StaffActionLogger.new(@granted_by).log_badge_grant(user_badge)
|
||||
end
|
||||
|
||||
@user.notifications.create(notification_type: Notification.types[:granted_badge],
|
||||
data: { badge_id: @badge.id,
|
||||
badge_name: @badge.name }.to_json)
|
||||
if SiteSetting.enable_badges?
|
||||
@user.notifications.create(notification_type: Notification.types[:granted_badge],
|
||||
data: { badge_id: @badge.id,
|
||||
badge_name: @badge.name }.to_json)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -54,4 +56,22 @@ class BadgeGranter
|
|||
end
|
||||
end
|
||||
|
||||
def self.update_badges(user, opts={})
|
||||
if opts.has_key?(:trust_level)
|
||||
# Update trust level badges.
|
||||
trust_level = opts[:trust_level]
|
||||
Badge.trust_level_badge_ids.each do |badge_id|
|
||||
user_badge = UserBadge.find_by(user_id: user.id, badge_id: badge_id)
|
||||
if user_badge
|
||||
# Revoke the badge if trust level was lowered.
|
||||
BadgeGranter.revoke(user_badge) if trust_level < badge_id
|
||||
else
|
||||
# Grant the badge if trust level was increased.
|
||||
badge = Badge.find(badge_id)
|
||||
BadgeGranter.grant(badge, user) if trust_level >= badge_id
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1850,6 +1850,16 @@ en:
|
|||
one: "1 granted"
|
||||
other: "%{count} granted"
|
||||
select_badge_for_title: Select a badge to use as your title
|
||||
example_badge:
|
||||
name: Example Badge
|
||||
description: This is a generic example badge.
|
||||
badge:
|
||||
basic_user:
|
||||
name: Basic User
|
||||
description: Trusted as a basic user.
|
||||
regular_user:
|
||||
name: Regular User
|
||||
description: Trusted as a regular user.
|
||||
leader:
|
||||
name: Leader
|
||||
description: One of the most active and prolific users.
|
||||
elder:
|
||||
name: Elder
|
||||
description: Long term community leader who has been around and seen everything.
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
def reset_badge_grant_count(badge)
|
||||
badge.grant_count = UserBadge.where(badge_id: badge.id).count
|
||||
badge.save!
|
||||
end
|
||||
|
||||
def grant_trust_level_badges_to_user(user)
|
||||
return if user.id == Discourse.system_user.id
|
||||
Badge.trust_level_badge_ids.each do |badge_id|
|
||||
user_badge = UserBadge.where(user_id: user.id, badge_id: badge_id).first
|
||||
if user_badge
|
||||
# Revoke the badge if the user is not supposed to have it.
|
||||
if user.trust_level < badge_id
|
||||
user_badge.destroy!
|
||||
end
|
||||
else
|
||||
# Grant the badge if the user is supposed to have it.
|
||||
badge = Badge.find(badge_id)
|
||||
if user.trust_level >= badge_id
|
||||
UserBadge.create!(badge: badge, user: user, granted_by: Discourse.system_user, granted_at: Time.now)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
trust_level_badges = [
|
||||
{id: 1, name: "Basic User", type: 3},
|
||||
{id: 2, name: "Regular User", type: 3},
|
||||
{id: 3, name: "Leader", type: 2},
|
||||
{id: 4, name: "Elder", type: 1}
|
||||
]
|
||||
|
||||
backfill_trust_level_badges = false
|
||||
|
||||
trust_level_badges.each do |spec|
|
||||
backfill_trust_level_badges ||= Badge.where(id: spec[:id]).first.nil?
|
||||
|
||||
Badge.seed do |b|
|
||||
b.id = spec[:id]
|
||||
b.name = spec[:name]
|
||||
b.badge_type_id = spec[:type]
|
||||
end
|
||||
end
|
||||
|
||||
if backfill_trust_level_badges
|
||||
User.find_each {|user| grant_trust_level_badges_to_user(user) }
|
||||
Badge.where(id: Badge.trust_level_badge_ids).each {|badge| reset_badge_grant_count(badge) }
|
||||
end
|
|
@ -5,6 +5,6 @@ class MigrateBookmarksToPostActions < ActiveRecord::Migration
|
|||
|
||||
def down
|
||||
# I can reverse this, but not really worth the work
|
||||
raise ActiveRecord::IrriversableMigration
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
|
|
|
@ -15,6 +15,6 @@ select
|
|||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrriversableMigration
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
|
|
|
@ -13,6 +13,6 @@ class FixSearch < ActiveRecord::Migration
|
|||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrriversableMigration
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
class IncrementReservedTrustLevelBadgeIds < ActiveRecord::Migration
|
||||
def up
|
||||
execute "ALTER SEQUENCE badges_id_seq START WITH 100"
|
||||
|
||||
max_badge_id = Badge.order('id DESC').limit(1).first.try(:id)
|
||||
Badge.where('id > 0 AND id <= 100').find_each do |badge|
|
||||
new_id = badge.id + max_badge_id + 100
|
||||
UserBadge.where(badge_id: badge.id).update_all badge_id: new_id
|
||||
badge.update_column :id, new_id
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
|
@ -18,6 +18,7 @@ class BoostTrustLevel
|
|||
@user.update_attributes!(trust_level: @level)
|
||||
end
|
||||
@logger.log_trust_level_change(@user, previous_level, @level)
|
||||
BadgeGranter.update_badges(@user, trust_level: @level)
|
||||
success
|
||||
end
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@ describe BadgesController do
|
|||
|
||||
response.status.should == 200
|
||||
parsed = JSON.parse(response.body)
|
||||
parsed["badges"].length.should == 1
|
||||
parsed["badges"].length.should == Badge.count
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,10 +1,15 @@
|
|||
require 'spec_helper'
|
||||
require_dependency 'boost_trust_level'
|
||||
|
||||
describe BadgeGranter do
|
||||
|
||||
let(:badge) { Fabricate(:badge) }
|
||||
let(:user) { Fabricate(:user) }
|
||||
|
||||
before do
|
||||
SiteSetting.enable_badges = true
|
||||
end
|
||||
|
||||
describe 'grant' do
|
||||
|
||||
it 'grants a badge' do
|
||||
|
@ -66,4 +71,17 @@ describe BadgeGranter do
|
|||
|
||||
end
|
||||
|
||||
context "update_badges" do
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:logger) { StaffActionLogger.new(Fabricate(:admin)) }
|
||||
|
||||
it "grants and revokes trust level badges" do
|
||||
user.change_trust_level!(:elder)
|
||||
UserBadge.where(user_id: user.id, badge_id: Badge.trust_level_badge_ids).count.should eq(4)
|
||||
BoostTrustLevel.new(user: user, level: 1, logger: logger).save!
|
||||
UserBadge.where(user_id: user.id, badge_id: 1).first.should_not be_nil
|
||||
UserBadge.where(user_id: user.id, badge_id: 2).first.should be_nil
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -13,7 +13,7 @@ test('displayName', function() {
|
|||
|
||||
this.stub(I18n, "t").returnsArg(0);
|
||||
var badge2 = Discourse.Badge.create({id: 2, name: "Test Badge 2"});
|
||||
equal(badge2.get('displayName'), "badges.test_badge_2.name", "uses translation when available");
|
||||
equal(badge2.get('displayName'), "badges.badge.test_badge_2.name", "uses translation when available");
|
||||
});
|
||||
|
||||
test('translatedDescription', function() {
|
||||
|
|
Loading…
Reference in New Issue