FEATURE: badge grouping UI
FIX: not loading more badges on badge show page
This commit is contained in:
parent
c47a70e390
commit
c8284170ad
|
@ -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')
|
||||
});
|
||||
|
|
|
@ -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')
|
||||
});
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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()
|
||||
});
|
|
@ -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);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -3,7 +3,11 @@
|
|||
|
||||
<table class='badges-listing'>
|
||||
<tbody>
|
||||
{{#each}}
|
||||
{{#each badgeGroups}}
|
||||
<tr class='title'>
|
||||
<td colspan=4><h3>{{this.badgeGrouping.displayName}}</h3></td>
|
||||
</tr>
|
||||
{{#each this.badges}}
|
||||
<tr>
|
||||
<td class='granted'>{{#if this.has_badge}}<i class='fa fa-check'></i>{{/if}}</td>
|
||||
<td class='badge'>{{user-badge badge=this}}</td>
|
||||
|
@ -11,6 +15,7 @@
|
|||
<td class='grant-count'>{{i18n badges.granted count=grant_count}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
class BadgeGroupingSerializer < ApplicationSerializer
|
||||
attributes :id, :name, :description
|
||||
attributes :id, :name, :description, :position
|
||||
end
|
||||
|
|
|
@ -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
|
|
@ -1962,6 +1962,17 @@ en:
|
|||
other: "%{count} granted"
|
||||
select_badge_for_title: Select a badge to use as your title
|
||||
no_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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
class SetDefaultBadgeGrouping < ActiveRecord::Migration
|
||||
def change
|
||||
change_column :badges, :badge_grouping_id, :integer, null: false, default: 5
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue