UX: Make user info rendering more consistent

This commit is contained in:
Robin Ward 2016-03-24 13:05:09 -04:00
parent 476a5fd43c
commit db15772ab1
19 changed files with 98 additions and 128 deletions

View File

@ -0,0 +1,23 @@
import { url } from 'discourse/lib/computed';
import computed from 'ember-addons/ember-computed-decorators';
function normalize(name) {
return name.replace(/[\-\_ \.]/g, '').toLowerCase();
}
export default Ember.Component.extend({
classNameBindings: [':user-info', 'size'],
size: 'small',
userPath: url('user.username', '/users/%@'),
// TODO: In later ember releases `hasBlock` works without this
hasBlock: Ember.computed.alias('template'),
@computed('user.name', 'user.username')
name(name, username) {
if (name && normalize(username) !== normalize(name)) {
return name;
}
}
});

View File

@ -1,15 +0,0 @@
import { url } from 'discourse/lib/computed';
export default Ember.Component.extend({
classNames: ['user-small'],
userPath: url('user.username', '/users/%@'),
name: function() {
const name = this.get('user.name');
if (name && this.get('user.username') !== name) {
return name;
}
}.property('user.name')
});

View File

@ -6,7 +6,7 @@ export default Ember.Controller.extend({
userBadges: null,
needs: ["application"],
user: function(){
user: function() {
if (this.get("username")) {
return this.get('userBadges')[0].get('user');
}
@ -37,16 +37,6 @@ export default Ember.Controller.extend({
}
},
layoutClass: function(){
var user = this.get("user") ? " single-user" : "";
var ub = this.get("userBadges");
if(ub && ub[0] && ub[0].post_id){
return "user-badge-with-posts" + user;
} else {
return "user-badge-no-posts" + user;
}
}.property("userBadges"),
canLoadMore: function() {
if (this.get('noMoreBadges')) { return false; }

View File

@ -25,3 +25,5 @@ registerUnbound('format-date', function(val, params) {
return new Handlebars.SafeString(autoUpdatingRelativeAge(date, {format: format, title: title, leaveAgo: leaveAgo}));
}
});

View File

@ -0,0 +1,6 @@
import { relativeAge } from 'discourse/lib/formatter';
export default function(dt, params) {
dt = params.data.view.getStream(dt).value();
return relativeAge(new Date(dt));
}

View File

@ -6,13 +6,8 @@ const UserBadge = Discourse.Model.extend({
return "/t/-/" + this.get('topic_id') + "/" + this.get('post_number');
}
}.property(), // avoid the extra bindings for now
/**
Revoke this badge.
@method revoke
@returns {Promise} a promise that resolves when the badge has been revoked.
**/
revoke: function() {
revoke() {
return Discourse.ajax("/user_badges/" + this.get('id'), {
type: "DELETE"
});

View File

@ -15,10 +15,7 @@ export default Discourse.Route.extend({
},
serialize(model) {
return {
id: model.get("id"),
slug: model.get("slug")
};
return model.getProperties('id', 'slug');
},
model(params) {
@ -29,13 +26,12 @@ export default Discourse.Route.extend({
}
},
afterModel(model,transition) {
afterModel(model, transition) {
const username = transition.queryParams && transition.queryParams.username;
return UserBadge.findByBadgeId(model.get("id"), {username}).then(userBadges => {
this.userBadges = userBadges;
});
},
titleToken() {

View File

@ -22,8 +22,8 @@
<section class='about admins'>
<h3>{{i18n 'about.our_admins'}}</h3>
{{#each a in model.admins}}
{{user-small user=a}}
{{#each model.admins as |a|}}
{{user-info user=a}}
{{/each}}
<div class='clearfix'></div>
@ -35,8 +35,8 @@
<h3>{{i18n 'about.our_moderators'}}</h3>
<div class='users'>
{{#each m in model.moderators}}
{{user-small user=m}}
{{#each model.moderators as |m|}}
{{user-info user=m}}
{{/each}}
</div>
<div class='clearfix'></div>

View File

@ -14,57 +14,38 @@
<div class='badges-listing'>
<div class='row'>
{{#unless user}}
<div class='grant-count'>{{i18n 'badges.granted' count=grantCount}}</div>
<div class='grant-count'>{{i18n 'badges.granted' count=grantCount}}</div>
{{/unless}}
<div class='info'>{{i18n 'badges.allow_title'}} {{{view.allowTitle}}}<br>{{i18n 'badges.multiple_grant'}} {{{view.multipleGrant}}}
</div>
</div>
</div>
{{#if user}}
<div class='badge-user-info'>
{{#link-to 'user' user}}
{{avatar user imageSize="extra_large"}}
<div class="details clearfix">
<div class='username'>{{user.username}}</div>
</div>
{{/link-to}}
<div class='earned'>
{{i18n 'badges.earned_n_times' count=grantCount}}
{{i18n 'badges.earned_n_times' count=grantCount}}
</div>
</div>
{{/if}}
{{#if userBadges}}
<div class={{unbound layoutClass}}>
{{#each ub in userBadges}}
<div class="badge-user">
{{#if user}}
{{format-date ub.granted_at}}
{{else}}
{{#link-to 'user' ub.user classNames="badge-info"}}
{{avatar ub.user imageSize="large"}}
<div class="details">
<span class="username">{{ub.user.username}}</span>
{{format-date ub.granted_at}}
</div>
{{/link-to}}
{{/if}}
<div class="user-badges">
{{#each userBadges as |ub|}}
{{#user-info user=ub.user size="medium" class="badge-info" date=ub.granted_at}}
<div class="granted-on">{{i18n 'badges.granted_on' date=(inline-date ub.granted_at)}}</div>
{{#if ub.post_number}}
<a class="post-link" href="{{unbound ub.topic.url}}/{{unbound ub.post_number}}">{{{ub.topic.fancyTitle}}}</a>
{{/if}}
</div>
{{/user-info}}
{{/each}}
{{#unless canLoadMore}}
{{#if user}}
<a class='load-more' href='{{model.url}}'>{{i18n 'badges.more_with_badge'}}</a>
{{log model}}
<a class='btn' href='{{model.url}}'>{{i18n 'badges.others_count' count=model.grant_count}}</a>
{{/if}}
{{/unless}}
</div>
{{conditional-loading-spinner condition=canLoadMore}}

View File

@ -8,4 +8,11 @@
<span class="name">{{unbound name}}</span>
</div>
<div class="title">{{unbound user.title}}</div>
{{#if hasBlock}}
<div class='details'>
{{yield}}
</div>
{{/if}}
</div>

View File

@ -18,7 +18,7 @@
{{#each model.members as |m|}}
<tr>
<td class='avatar'>
{{user-small user=m}}
{{user-info user=m}}
{{#if m.owner}}<span class='is-owner'>{{i18n "groups.owner"}}</span>{{/if}}
</td>
<td>

View File

@ -13,7 +13,7 @@
{{#each ic in model itemController="directory-item"}}
<div class="user {{if ic.me 'me'}}">
{{#with ic.model as |it|}}
{{user-small user=it.user}}
{{user-info user=it.user}}
{{user-stat value=it.likes_received label="directory.likes_received" icon="heart"}}
{{user-stat value=it.likes_given label="directory.likes_given" icon="heart"}}
{{user-stat value=it.topic_count label="directory.topic_count"}}

View File

@ -28,7 +28,7 @@
{{#each ic in model itemController="directory-item"}}
<tr class="{{if ic.me 'me'}}">
{{#with ic.model as |it|}}
<td>{{user-small user=it.user}}</td>
<td>{{user-info user=it.user}}</td>
<td>{{number it.likes_received}}</td>
<td>{{number it.likes_given}}</td>
<td>{{number it.topic_count}}</td>

View File

@ -1,6 +1,10 @@
.directory {
margin-bottom: 100px;
.user-info {
margin-bottom: 0;
}
.period-chooser {
float: left;
}

View File

@ -135,66 +135,23 @@
}
}
}
.user-info.medium.badge-info {
min-height: 80px;
/* /badges/:id/:slug page styling. */
.show-badge {
.badge-user {
text-align: center;
width: 100px;
padding: 5px 10px;
margin-bottom: 10px;
display: inline-block;
vertical-align: top;
.details {
margin: 0 10px;
padding-top: 3px;
color: $primary;
}
.username {
word-wrap: break-word;
}
.date {
display: block;
color: lighten($primary, 40%);
font-size: 0.714em;
}
}
}
.show-badge .user-badge-with-posts .badge-user {
width: 45%;
padding: 0 0 0 4%;
margin-bottom: 20px;
.badge-info {
width: 100px;
display: block;
float: left;
.granted-on {
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
}
.post-link {
width: 250px;
display: block;
float: left;
margin-left: 18px;
text-align: left;
margin-top: 0.2em;
}
}
.show-badge .badge-user-info {
margin-left: 2%;
.earned {
margin-top: 15px;
font-size: 1.3em;
}
.username {
margin-top: 5px;
display: block;
color: dark-light-choose(scale-color($primary, $lightness: 30%), scale-color($secondary, $lightness: 70%));
margin-bottom: 1em;
}
}

View File

@ -92,10 +92,10 @@
margin-bottom: 15px;
}
.user-small {
.user-info {
display: inline-block;
width: 333px;
clear: both;
margin-bottom: 1em;
.user-image {
float: left;
@ -128,7 +128,30 @@
margin-top: 3px;
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 50%));
}
}
}
.user-info.small {
width: 333px;
}
.user-info.medium {
width: 550px;
min-height: 60px;
.user-image {
width: 55px;
}
.user-detail {
width: 450px;
}
.username, .name {
display: block;
}
.name {
margin-left: 0;
}
}

View File

@ -169,7 +169,7 @@
color: $primary;
}
}
.user-small {
.user-info {
width: 245px;
}
}

View File

@ -2855,7 +2855,8 @@ en:
earned_n_times:
one: "Earned this badge 1 time"
other: "Earned this badge %{count} times"
more_with_badge: "Others with this badge"
granted_on: "Granted %{date}"
others_count: "Others with this badge (%{count})"
title: Badges
allow_title: "can be used as a title"
multiple_grant: "can be awarded multiple times"

View File

@ -4,8 +4,8 @@ acceptance("About");
test("viewing", () => {
visit("/about");
andThen(() => {
ok(exists('.about.admins .user-small'), 'has admins');
ok(exists('.about.moderators .user-small'), 'has moderators');
ok(exists('.about.admins .user-info'), 'has admins');
ok(exists('.about.moderators .user-info'), 'has moderators');
ok(exists('.about.stats tr td'), 'has stats');
});
});