diff --git a/app/assets/javascripts/discourse/controllers/badges/index.js.es6 b/app/assets/javascripts/discourse/controllers/badges/index.js.es6
index 7a52169dd08..862ac75c41a 100644
--- a/app/assets/javascripts/discourse/controllers/badges/index.js.es6
+++ b/app/assets/javascripts/discourse/controllers/badges/index.js.es6
@@ -1,4 +1,32 @@
-export default Ember.ArrayController.extend({
- sortProperties: ['displayName'],
- sortAscending: true
+export default Ember.Controller.extend({
+ badgeGroups: function(){
+ var sorted = _.sortBy(this.get('model'), function(badge){
+ var pos = badge.get('badge_grouping.position');
+ var type = badge.get('badge_type_id');
+ var name = badge.get('displayName');
+
+ return ("000" + pos).slice(-4) + (10-type) + name;
+ });
+
+ var grouped = [];
+ var group = [], groupId;
+
+ sorted.forEach(function(badge){
+ if(groupId !== badge.badge_grouping_id){
+ if(group && group.length > 0){
+ grouped.push({badges: group, badgeGrouping: group[0].badge_grouping});
+ }
+ group = [];
+ groupId = badge.badge_grouping_id;
+ }
+ group.push(badge);
+ });
+
+ if(group && group.length > 0){
+ grouped.push({badges: group, badgeGrouping: group[0].badge_grouping});
+ }
+
+ return grouped;
+
+ }.property('model')
});
diff --git a/app/assets/javascripts/discourse/controllers/badges/show.js.es6 b/app/assets/javascripts/discourse/controllers/badges/show.js.es6
index 5d734809ef8..c448069af30 100644
--- a/app/assets/javascripts/discourse/controllers/badges/show.js.es6
+++ b/app/assets/javascripts/discourse/controllers/badges/show.js.es6
@@ -7,6 +7,23 @@
@module Discourse
**/
export default Discourse.ObjectController.extend({
+
+ actions: {
+ loadMore: function() {
+ var self = this;
+ var userBadges = this.get('userBadges');
+
+ Discourse.UserBadge.findByBadgeId(this.get('model.id'), {
+ offset: userBadges.length
+ }).then(function(userBadges) {
+ self.get('userBadges').pushObjects(userBadges);
+ if(userBadges.length === 0){
+ self.set('noMoreBadges', true);
+ }
+ });
+ }
+ },
+
layoutClass: function(){
var ub = this.get("userBadges");
if(ub && ub[0] && ub[0].post_id){
@@ -16,14 +33,15 @@ export default Discourse.ObjectController.extend({
}
}.property("userBadges"),
- grantDates: Em.computed.mapBy('userBadges', 'grantedAt'),
- minGrantedAt: Em.computed.min('grantDates'),
-
canLoadMore: function() {
+ if(this.get('noMoreBadges')) {
+ return false;
+ }
+
if (this.get('userBadges')) {
return this.get('model.grant_count') > this.get('userBadges.length');
} else {
return false;
}
- }.property('model.grant_count', 'userBadges.length')
+ }.property('noMoreBadges', 'model.grant_count', 'userBadges.length')
});
diff --git a/app/assets/javascripts/discourse/models/badge.js b/app/assets/javascripts/discourse/models/badge.js
index 8d017ee8504..17198074bd6 100644
--- a/app/assets/javascripts/discourse/models/badge.js
+++ b/app/assets/javascripts/discourse/models/badge.js
@@ -165,6 +165,13 @@ Discourse.Badge.reopenClass({
});
}
+ var badgeGroupings = {};
+ if ('badge_groupings' in json) {
+ json.badge_groupings.forEach(function(badgeGroupingJson) {
+ badgeGroupings[badgeGroupingJson.id] = Discourse.BadgeGrouping.create(badgeGroupingJson);
+ });
+ }
+
// Create Badge objects.
var badges = [];
if ("badge" in json) {
@@ -175,8 +182,10 @@ Discourse.Badge.reopenClass({
badges = badges.map(function(badgeJson) {
var badge = Discourse.Badge.create(badgeJson);
badge.set('badge_type', badgeTypes[badge.get('badge_type_id')]);
+ badge.set('badge_grouping', badgeGroupings[badge.get('badge_grouping_id')]);
return badge;
});
+
if ("badge" in json) {
return badges[0];
} else {
diff --git a/app/assets/javascripts/discourse/models/badge_grouping.js b/app/assets/javascripts/discourse/models/badge_grouping.js
new file mode 100644
index 00000000000..dd59d078fab
--- /dev/null
+++ b/app/assets/javascripts/discourse/models/badge_grouping.js
@@ -0,0 +1,10 @@
+Discourse.BadgeGrouping= Discourse.Model.extend({
+ i18nNameKey: function() {
+ return this.get('name').toLowerCase().replace(/\s/g, '_');
+ }.property('name'),
+
+ displayName: function(){
+ var i18nKey = "badges.badge_grouping." + this.get('i18nNameKey') + ".name";
+ return I18n.t(i18nKey, {defaultValue: this.get('name')});
+ }.property()
+});
diff --git a/app/assets/javascripts/discourse/models/user_badge.js b/app/assets/javascripts/discourse/models/user_badge.js
index 85c05cc6a33..7d594e7a2cb 100644
--- a/app/assets/javascripts/discourse/models/user_badge.js
+++ b/app/assets/javascripts/discourse/models/user_badge.js
@@ -111,11 +111,11 @@ Discourse.UserBadge.reopenClass({
**/
findByBadgeId: function(badgeId, options) {
if (!options) { options = {}; }
- var url = "/user_badges.json?badge_id=" + badgeId;
- if (options.granted_before) {
- url = url + "&granted_before=" + encodeURIComponent(options.granted_before);
- }
- return Discourse.ajax(url).then(function(json) {
+ options.badge_id = badgeId;
+
+ return Discourse.ajax("/user_badges.json", {
+ data: options
+ }).then(function(json) {
return Discourse.UserBadge.createFromJson(json);
});
},
diff --git a/app/assets/javascripts/discourse/routes/badges_show_route.js b/app/assets/javascripts/discourse/routes/badges_show_route.js
index 842bf36e324..4da70063b44 100644
--- a/app/assets/javascripts/discourse/routes/badges_show_route.js
+++ b/app/assets/javascripts/discourse/routes/badges_show_route.js
@@ -28,16 +28,5 @@ Discourse.BadgesShowRoute = Ember.Route.extend({
});
controller.set('model', model);
Discourse.set('title', model.get('displayName'));
- },
-
- actions: {
- loadMore: function() {
- var self = this;
- Discourse.UserBadge.findByBadgeId(this.currentModel.get('id'), {
- granted_before: this.get('controller.minGrantedAt') / 1000
- }).then(function(userBadges) {
- self.get('controller.userBadges').pushObjects(userBadges);
- });
- }
}
});
diff --git a/app/assets/javascripts/discourse/templates/badges/index.js.handlebars b/app/assets/javascripts/discourse/templates/badges/index.js.handlebars
index 91dc57a9dc9..a03d45b9a13 100644
--- a/app/assets/javascripts/discourse/templates/badges/index.js.handlebars
+++ b/app/assets/javascripts/discourse/templates/badges/index.js.handlebars
@@ -3,13 +3,18 @@
- {{#each}}
-
- {{#if this.has_badge}}{{/if}} |
- {{user-badge badge=this}} |
- {{{displayDescriptionHtml}}} |
- {{i18n badges.granted count=grant_count}} |
+ {{#each badgeGroups}}
+
+ {{this.badgeGrouping.displayName}} |
+ {{#each this.badges}}
+
+ {{#if this.has_badge}}{{/if}} |
+ {{user-badge badge=this}} |
+ {{{displayDescriptionHtml}}} |
+ {{i18n badges.granted count=grant_count}} |
+
+ {{/each}}
{{/each}}
diff --git a/app/assets/stylesheets/common/base/user-badges.scss b/app/assets/stylesheets/common/base/user-badges.scss
index 07503b54e93..97a30e58844 100644
--- a/app/assets/stylesheets/common/base/user-badges.scss
+++ b/app/assets/stylesheets/common/base/user-badges.scss
@@ -75,6 +75,15 @@ table.badges-listing {
font-size: $base-font-size;
}
+ tr.title td {
+ padding-top: 30px;
+ padding-bottom: 15px;
+ }
+
+ tr.title {
+ border-top: 0px solid;
+ }
+
td {
padding: 10px 0px;
}
diff --git a/app/controllers/badges_controller.rb b/app/controllers/badges_controller.rb
index 6f57c2b175f..77e4a164d09 100644
--- a/app/controllers/badges_controller.rb
+++ b/app/controllers/badges_controller.rb
@@ -3,13 +3,21 @@ class BadgesController < ApplicationController
def index
badges = Badge.all
- badges = badges.where(enabled: true, listable: true) if(params[:only_listable] == "true") || !request.xhr?
- badges = badges.includes(:badge_grouping).to_a
+
+ if (params[:only_listable] == "true") || !request.xhr?
+ # NOTE: this is sorted client side if needed
+ badges = badges.includes(:badge_grouping)
+ .where(enabled: true, listable: true)
+
+ end
+
+ badges = badges.to_a
+
user_badges = nil
if current_user
user_badges = Set.new(current_user.user_badges.select('distinct badge_id').pluck(:badge_id))
end
- serialized = MultiJson.dump(serialize_data(badges, BadgeSerializer, root: "badges", user_badges: user_badges, include_grouping: true))
+ serialized = MultiJson.dump(serialize_data(badges, BadgeIndexSerializer, root: "badges", user_badges: user_badges))
respond_to do |format|
format.html do
store_preloaded "badges", serialized
diff --git a/app/controllers/user_badges_controller.rb b/app/controllers/user_badges_controller.rb
index 946289a006b..797ea8f7448 100644
--- a/app/controllers/user_badges_controller.rb
+++ b/app/controllers/user_badges_controller.rb
@@ -7,11 +7,11 @@ class UserBadgesController < ApplicationController
user_badges = user.user_badges
else
badge = fetch_badge_from_params
- user_badges = badge.user_badges.order('granted_at DESC').limit(96)
+ user_badges = badge.user_badges.order('granted_at DESC, id DESC').limit(96)
end
- if params[:granted_before]
- user_badges = user_badges.where('granted_at < ?', Time.at(params[:granted_before].to_f))
+ if offset = params[:offset]
+ user_badges = user_badges.offset(offset.to_i)
end
user_badges = user_badges.includes(:user, :granted_by, badge: :badge_type, post: :topic)
diff --git a/app/models/badge.rb b/app/models/badge.rb
index 5936e2858f3..71aa1d27437 100644
--- a/app/models/badge.rb
+++ b/app/models/badge.rb
@@ -1,6 +1,4 @@
class Badge < ActiveRecord::Base
- belongs_to :badge_grouping
-
# badge ids
Welcome = 5
NicePost = 6
@@ -145,6 +143,8 @@ SQL
end
belongs_to :badge_type
+ belongs_to :badge_grouping
+
has_many :user_badges, dependent: :destroy
validates :name, presence: true, uniqueness: true
diff --git a/app/models/badge_grouping.rb b/app/models/badge_grouping.rb
index 27d1694beea..066bd79331a 100644
--- a/app/models/badge_grouping.rb
+++ b/app/models/badge_grouping.rb
@@ -1,12 +1,10 @@
class BadgeGrouping < ActiveRecord::Base
- module Position
- GettingStarted = 10
- Community = 11
- Posting = 12
- TrustLevel = 13
- Other = 14
- end
+ GettingStarted = 1
+ Community = 2
+ Posting = 3
+ TrustLevel = 4
+ Other = 5
has_many :badges
end
diff --git a/app/serializers/badge_grouping_serializer.rb b/app/serializers/badge_grouping_serializer.rb
index 694b3efe47d..7331a610cfa 100644
--- a/app/serializers/badge_grouping_serializer.rb
+++ b/app/serializers/badge_grouping_serializer.rb
@@ -1,3 +1,3 @@
class BadgeGroupingSerializer < ApplicationSerializer
- attributes :id, :name, :description
+ attributes :id, :name, :description, :position
end
diff --git a/app/serializers/badge_index_serializer.rb b/app/serializers/badge_index_serializer.rb
new file mode 100644
index 00000000000..533c71133e5
--- /dev/null
+++ b/app/serializers/badge_index_serializer.rb
@@ -0,0 +1,12 @@
+class BadgeIndexSerializer < BadgeSerializer
+ attributes :has_badge
+ has_one :badge_grouping
+
+ def include_has_badge?
+ @options[:user_badges]
+ end
+
+ def has_badge
+ @options[:user_badges].include?(object.id)
+ end
+end
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 1c594bb774d..26c0613d9c7 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -1962,6 +1962,17 @@ en:
other: "%{count} granted"
select_badge_for_title: Select a badge to use as your title
no_title: ""
+ badge_grouping:
+ getting_started:
+ name: Getting Started
+ community:
+ name: Community
+ trust_level:
+ name: Trust Level
+ other:
+ name: Other
+ posting:
+ name: Posting
badge:
editor:
name: Editor
diff --git a/db/fixtures/006_badges.rb b/db/fixtures/006_badges.rb
index 59fc5aa7742..eebda42753d 100644
--- a/db/fixtures/006_badges.rb
+++ b/db/fixtures/006_badges.rb
@@ -1,34 +1,42 @@
BadgeGrouping.seed do |g|
- g.id = 1
+ g.id = BadgeGrouping::GettingStarted
g.name = "Getting Started"
- g.position = BadgeGrouping::Position::GettingStarted
+ g.position = 10
end
BadgeGrouping.seed do |g|
- g.id = 2
+ g.id = BadgeGrouping::Community
g.name = "Community"
- g.position = BadgeGrouping::Position::Community
+ g.position = 11
end
BadgeGrouping.seed do |g|
- g.id = 3
+ g.id = BadgeGrouping::Posting
g.name = "Posting"
- g.position = BadgeGrouping::Position::Posting
+ g.position = 12
end
BadgeGrouping.seed do |g|
- g.id = 4
+ g.id = BadgeGrouping::TrustLevel
g.name = "Trust Level"
- g.position = BadgeGrouping::Position::TrustLevel
+ g.position = 13
end
BadgeGrouping.seed do |g|
- g.id = 5
+ g.id = BadgeGrouping::Other
g.name = "Other"
- g.position = BadgeGrouping::Position::Other
+ g.position = 14
end
+# BUGFIX
+Badge.exec_sql 'UPDATE badges
+ SET badge_grouping_id = NULL
+ WHERE NOT EXISTS (
+ SELECT 1 FROM badge_groupings g
+ WHERE g.id = badge_grouping_id
+ )'
+
# Trust level system badges.
trust_level_badges = [
{id: 1, name: "Basic User", type: BadgeType::Bronze},
@@ -43,7 +51,7 @@ trust_level_badges.each do |spec|
b.default_name = spec[:name]
b.badge_type_id = spec[:type]
b.query = Badge::Queries.trust_level(spec[:id])
- b.default_badge_grouping_id = BadgeGrouping::Position::TrustLevel
+ b.default_badge_grouping_id = BadgeGrouping::TrustLevel
# allow title for leader and elder
b.allow_title = spec[:id] > 2
@@ -57,7 +65,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = false
b.query = Badge::Queries::Reader
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
b.auto_revoke = false
end
@@ -68,7 +76,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = false
b.query = Badge::Queries::ReadGuidelines
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
end
Badge.seed do |b|
@@ -78,7 +86,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = true
b.query = Badge::Queries::FirstLink
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
end
Badge.seed do |b|
@@ -88,7 +96,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = true
b.query = Badge::Queries::FirstQuote
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
end
Badge.seed do |b|
@@ -98,7 +106,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = true
b.query = Badge::Queries::FirstLike
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
end
Badge.seed do |b|
@@ -108,7 +116,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = false
b.query = Badge::Queries::FirstFlag
- b.default_badge_grouping_id = BadgeGrouping::Position::Community
+ b.default_badge_grouping_id = BadgeGrouping::Community
end
Badge.seed do |b|
@@ -118,7 +126,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = true
b.query = Badge::Queries::FirstShare
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
end
Badge.seed do |b|
@@ -128,7 +136,7 @@ Badge.seed do |b|
b.multiple_grant = false
b.target_posts = true
b.query = Badge::Queries::Welcome
- b.default_badge_grouping_id = BadgeGrouping::Position::Community
+ b.default_badge_grouping_id = BadgeGrouping::Community
end
Badge.seed do |b|
@@ -137,7 +145,7 @@ Badge.seed do |b|
b.badge_type_id = BadgeType::Bronze
b.multiple_grant = false
b.query = Badge::Queries::Autobiographer
- b.default_badge_grouping_id = BadgeGrouping::Position::GettingStarted
+ b.default_badge_grouping_id = BadgeGrouping::GettingStarted
end
Badge.seed do |b|
@@ -146,7 +154,7 @@ Badge.seed do |b|
b.badge_type_id = BadgeType::Bronze
b.multiple_grant = false
b.query = Badge::Queries::Editor
- b.default_badge_grouping_id = BadgeGrouping::Position::Community
+ b.default_badge_grouping_id = BadgeGrouping::Community
end
#
@@ -165,6 +173,6 @@ like_badges.each do |spec|
b.multiple_grant = spec[:multiple]
b.target_posts = true
b.query = Badge::Queries.like_badge(Badge.like_badge_counts[spec[:id]])
- b.default_badge_grouping_id = BadgeGrouping::Position::Posting
+ b.default_badge_grouping_id = BadgeGrouping::Posting
end
end
diff --git a/db/migrate/20140718041445_set_default_badge_grouping.rb b/db/migrate/20140718041445_set_default_badge_grouping.rb
new file mode 100644
index 00000000000..6a02fcbae21
--- /dev/null
+++ b/db/migrate/20140718041445_set_default_badge_grouping.rb
@@ -0,0 +1,5 @@
+class SetDefaultBadgeGrouping < ActiveRecord::Migration
+ def change
+ change_column :badges, :badge_grouping_id, :integer, null: false, default: 5
+ end
+end