Merge pull request #2212 from vikhyat/badge-system
Show badges in the poster expansion card
This commit is contained in:
commit
d3810ba3bc
|
@ -57,7 +57,10 @@ Discourse.AdminUserBadgesController = Ember.ArrayController.extend({
|
|||
self.pushObject(userBadge);
|
||||
Ember.run.next(function() {
|
||||
// Update the selected badge ID after the combobox has re-rendered.
|
||||
self.set('selectedBadgeId', self.get('grantableBadges')[0].get('id'));
|
||||
var newSelectedBadge = self.get('grantableBadges')[0];
|
||||
if (newSelectedBadge) {
|
||||
self.set('selectedBadgeId', newSelectedBadge.get('id'));
|
||||
}
|
||||
});
|
||||
}, function() {
|
||||
// Failure
|
||||
|
|
|
@ -20,6 +20,16 @@ Discourse.PosterExpansionController = Discourse.ObjectController.extend({
|
|||
|
||||
hasUserFilters: Em.computed.gt('postStream.userFilters.length', 0),
|
||||
|
||||
showBadges: function() {
|
||||
return Discourse.SiteSettings.enable_badges;
|
||||
}.property(),
|
||||
|
||||
moreBadgesCount: function() {
|
||||
return this.get('user.badge_count') - this.get('user.featured_user_badges.length');
|
||||
}.property('user.badge_count', 'user.featured_user_badges.@each'),
|
||||
|
||||
showMoreBadges: Em.computed.gt('moreBadgesCount', 0),
|
||||
|
||||
show: function(post) {
|
||||
|
||||
// Don't show on mobile
|
||||
|
|
|
@ -312,10 +312,21 @@ Discourse.User = Discourse.Model.extend({
|
|||
return Discourse.Group.create(g);
|
||||
});
|
||||
}
|
||||
|
||||
if (json.user.invited_by) {
|
||||
json.user.invited_by = Discourse.User.create(json.user.invited_by);
|
||||
}
|
||||
|
||||
if (!Em.isEmpty(json.user.featured_user_badge_ids)) {
|
||||
var userBadgesMap = {};
|
||||
Discourse.UserBadge.createFromJson(json).forEach(function(userBadge) {
|
||||
userBadgesMap[ userBadge.get('id') ] = userBadge;
|
||||
});
|
||||
json.user.featured_user_badges = json.user.featured_user_badge_ids.map(function(id) {
|
||||
return userBadgesMap[id];
|
||||
});
|
||||
}
|
||||
|
||||
user.setProperties(json.user);
|
||||
return user;
|
||||
});
|
||||
|
|
|
@ -1,16 +1,31 @@
|
|||
{{#if model}}
|
||||
{{#link-to 'user' user}}{{boundAvatar model imageSize="huge"}}{{/link-to}}
|
||||
|
||||
<h1 {{bind-attr class="staff new_user"}}><a {{bind-attr href="usernameUrl"}}>{{username}}</a></h1>
|
||||
{{#if showName}}
|
||||
<h2><a {{bind-attr href="usernameUrl"}}>{{name}}</a></h2>
|
||||
{{/if}}
|
||||
<div class="names">
|
||||
<h1 {{bind-attr class="staff new_user"}}><a {{bind-attr href="usernameUrl"}}>{{username}}</a></h1>
|
||||
{{#if showName}}
|
||||
<h2><a {{bind-attr href="usernameUrl"}}>{{name}}</a></h2>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if user}}
|
||||
<h3>{{i18n last_post}} {{unboundDate path="user.last_posted_at" leaveAgo="true"}}</h3>
|
||||
<h3>{{i18n joined}} {{unboundDate path="user.created_at" leaveAgo="true"}}</h3>
|
||||
<div class="metadata">
|
||||
<h3>{{i18n last_post}} {{unboundDate path="user.last_posted_at" leaveAgo="true"}}</h3>
|
||||
<h3>{{i18n joined}} {{unboundDate path="user.created_at" leaveAgo="true"}}</h3>
|
||||
{{groups-list groups=user.custom_groups}}
|
||||
</div>
|
||||
|
||||
{{groups-list groups=user.custom_groups}}
|
||||
{{#if showBadges}}
|
||||
<div class="badge-section">
|
||||
<h3>{{i18n badges.badge_count count=user.badge_count}}</h3>
|
||||
{{#each user.featured_user_badges}}
|
||||
<span class="badge">{{badge.name}}</span>
|
||||
{{/each}}
|
||||
{{#if showMoreBadges}}
|
||||
<span class="btn more-badges">{{i18n badges.more_badges count=moreBadgesCount}}</span>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='bottom'>
|
||||
{{#if user.bio_cooked}}<div class='bio'>{{{user.bio_cooked}}}</div>{{/if}}
|
||||
|
|
|
@ -10,7 +10,7 @@ var clickOutsideEventName = "mousedown.outside-poster-expansion";
|
|||
|
||||
Discourse.PosterExpansionView = Discourse.View.extend({
|
||||
elementId: 'poster-expansion',
|
||||
classNameBindings: ['controller.visible::hidden'],
|
||||
classNameBindings: ['controller.visible::hidden', 'controller.showBadges'],
|
||||
|
||||
// Position the expansion when the post changes
|
||||
_visibleChanged: function() {
|
||||
|
|
|
@ -65,7 +65,7 @@
|
|||
}
|
||||
|
||||
p.loading {
|
||||
margin-top: 30px;
|
||||
margin-top: 45px;
|
||||
color: $secondary_text_color;
|
||||
}
|
||||
|
||||
|
@ -76,4 +76,47 @@
|
|||
.new-user a {
|
||||
color: $secondary_text_color;
|
||||
}
|
||||
|
||||
&.show-badges {
|
||||
width: 560px;
|
||||
|
||||
.names {
|
||||
width: 250px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.metadata {
|
||||
float: right;
|
||||
max-width: 180px;
|
||||
}
|
||||
|
||||
h2 {
|
||||
line-height: 15px;
|
||||
}
|
||||
|
||||
.badge-section {
|
||||
h3 {
|
||||
line-height: 43px;
|
||||
color: $primary_text_color;
|
||||
font-size: 14px;
|
||||
margin-bottom: -8px;
|
||||
}
|
||||
|
||||
.badge, .more-badges {
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
line-height: 16px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.badge {
|
||||
padding: 3px 8px;
|
||||
border: 1px solid $secondary-border-color;
|
||||
}
|
||||
|
||||
.more-badges {
|
||||
padding: 4px 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,12 @@ class UserSerializer < BasicUserSerializer
|
|||
:admin,
|
||||
:title,
|
||||
:suspend_reason,
|
||||
:suspended_till
|
||||
:suspended_till,
|
||||
:badge_count
|
||||
|
||||
has_one :invited_by, embed: :object, serializer: BasicUserSerializer
|
||||
has_many :custom_groups, embed: :object, serializer: BasicGroupSerializer
|
||||
has_many :featured_user_badges, embed: :ids, serializer: UserBadgeSerializer, root: :user_badges
|
||||
|
||||
def self.private_attributes(*attrs)
|
||||
attributes(*attrs)
|
||||
|
@ -128,4 +130,13 @@ class UserSerializer < BasicUserSerializer
|
|||
def watched_category_ids
|
||||
CategoryUser.lookup(object, :watching).pluck(:category_id)
|
||||
end
|
||||
|
||||
def badge_count
|
||||
object.user_badges.count
|
||||
end
|
||||
|
||||
def featured_user_badges
|
||||
# The three rarest badges this user has received should be featured.
|
||||
object.user_badges.joins(:badge).order('badges.grant_count ASC').includes(:granted_by, badge: :badge_type).limit(3)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1765,6 +1765,12 @@ en:
|
|||
mark_watching: '<b>m</b> then <b>w</b> Mark topic as watching'
|
||||
|
||||
badges:
|
||||
badge_count:
|
||||
one: "1 Badge"
|
||||
other: "%{count} Badges"
|
||||
more_badges:
|
||||
one: "+1 More"
|
||||
other: "+%{count} More"
|
||||
example_badge:
|
||||
name: Example Badge
|
||||
description: This is a generic example badge.
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
# Just ignore included associations that are to be embedded in the root instead of
|
||||
# throwing an exception in AMS 0.8.x.
|
||||
#
|
||||
# The 0.9.0 branch does exactly this, see:
|
||||
# https://github.com/rails-api/active_model_serializers/issues/377
|
||||
module ActiveModel
|
||||
class Serializer
|
||||
# This method is copied over verbatim from the AMS version, except for silently
|
||||
# ignoring associations that cannot be embedded without a root instead of
|
||||
# raising an exception.
|
||||
def include!(name, options={})
|
||||
unique_values =
|
||||
if hash = options[:hash]
|
||||
if @options[:hash] == hash
|
||||
@options[:unique_values] ||= {}
|
||||
else
|
||||
{}
|
||||
end
|
||||
else
|
||||
hash = @options[:hash]
|
||||
@options[:unique_values] ||= {}
|
||||
end
|
||||
|
||||
node = options[:node] ||= @node
|
||||
value = options[:value]
|
||||
|
||||
if options[:include] == nil
|
||||
if @options.key?(:include)
|
||||
options[:include] = @options[:include].include?(name)
|
||||
elsif @options.include?(:exclude)
|
||||
options[:include] = !@options[:exclude].include?(name)
|
||||
end
|
||||
end
|
||||
|
||||
association_class =
|
||||
if klass = _associations[name]
|
||||
klass
|
||||
elsif value.respond_to?(:to_ary)
|
||||
Associations::HasMany
|
||||
else
|
||||
Associations::HasOne
|
||||
end
|
||||
|
||||
association = association_class.new(name, self, options)
|
||||
|
||||
if association.embed_ids?
|
||||
node[association.key] = association.serialize_ids
|
||||
|
||||
if association.embed_in_root? && hash.nil?
|
||||
# Don't raise an error!
|
||||
elsif association.embed_in_root? && association.embeddable?
|
||||
merge_association hash, association.root, association.serializables, unique_values
|
||||
end
|
||||
elsif association.embed_objects?
|
||||
node[association.key] = association.serialize
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue