UX: improved user summary page
This commit is contained in:
parent
b55d3b240b
commit
bf579174c1
|
@ -1,13 +1,20 @@
|
|||
import computed from 'ember-addons/ember-computed-decorators';
|
||||
|
||||
// should be kept in sync with 'UserSummary::MAX_TOPICS'
|
||||
const MAX_TOPICS = 6;
|
||||
// should be kept in sync with 'UserSummary::MAX_BADGES'
|
||||
const MAX_BADGES = 6;
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
needs: ['user'],
|
||||
user: Em.computed.alias('controllers.user.model'),
|
||||
moreTopics: function(){
|
||||
return this.get('model.topics').length > 5;
|
||||
}.property('model'),
|
||||
moreReplies: function(){
|
||||
return this.get('model.replies').length > 5;
|
||||
}.property('model'),
|
||||
moreBadges: function(){
|
||||
return this.get('model.badges').length > 5;
|
||||
}.property('model')
|
||||
user: Ember.computed.alias('controllers.user.model'),
|
||||
|
||||
@computed("model.topics.length")
|
||||
moreTopics(topicsLength) { return topicsLength >= MAX_TOPICS; },
|
||||
|
||||
@computed("model.replies.length")
|
||||
moreReplies(repliesLength) { return repliesLength >= MAX_TOPICS; },
|
||||
|
||||
@computed("model.badges.length")
|
||||
moreBadges(badgesLength) { return badgesLength >= MAX_BADGES; },
|
||||
});
|
||||
|
|
|
@ -2,4 +2,4 @@
|
|||
{{#if icon}}{{fa-icon icon}}{{/if}}
|
||||
{{number value}}
|
||||
</span>
|
||||
<span class='label'>{{i18n label}}</span>
|
||||
<span class='label'>{{{i18n label count=value}}}</span>
|
||||
|
|
|
@ -1,62 +1,84 @@
|
|||
{{#if model.replies.length}}
|
||||
<div class='top-section'>
|
||||
<h3>{{i18n "user.summary.top_replies"}}</h3>
|
||||
{{#each reply in model.replies}}
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{reply.url}}">{{reply.topic.title}}</a> {{#if reply.like_count}}<span class='like-count'>{{reply.like_count}}<i class='fa fa-heart'></i></span>{{/if}} {{format-date reply.createdAt format="tiny" noTitle="true"}}
|
||||
</li>
|
||||
</ul>
|
||||
{{/each}}
|
||||
{{#if moreReplies}}
|
||||
{{#link-to "userActivity.replies" user class="more"}}{{i18n "user.summary.more_replies"}}{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.topics.length}}
|
||||
<div class='top-section'>
|
||||
<h3>{{i18n "user.summary.top_topics"}}</h3>
|
||||
{{#each topic in model.topics}}
|
||||
<ul>
|
||||
<li>
|
||||
<a href="{{topic.url}}">{{topic.title}}</a> {{#if topic.like_count}}<span class='like-count'>{{topic.like_count}}<i class='fa fa-heart'></i></span>{{/if}} {{format-date topic.createdAt format="tiny" noTitle="true"}}
|
||||
</li>
|
||||
</ul>
|
||||
{{/each}}
|
||||
{{#if moreTopics}}
|
||||
{{#link-to "userActivity.topics" user class="more"}}{{i18n "user.summary.more_topics"}}{{/link-to}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class='top-section stats-section'>
|
||||
<h3>{{i18n "user.summary.stats"}}</h3>
|
||||
<dl>
|
||||
<dt>{{i18n "user.summary.topic_count"}}</dt>
|
||||
<dd>{{model.topic_count}}</dd>
|
||||
<dt>{{i18n "user.summary.post_count"}}</dt>
|
||||
<dd>{{model.post_count}}</dd>
|
||||
<dt>{{i18n "user.summary.likes_given"}}</dt>
|
||||
<dd>{{model.likes_given}}</dd>
|
||||
<dt>{{i18n "user.summary.likes_received"}}</dt>
|
||||
<dd>{{model.likes_received}}</dd>
|
||||
<dt>{{i18n "user.summary.days_visited"}}</dt>
|
||||
<dd>{{model.days_visited}}</dd>
|
||||
<dt>{{i18n "user.summary.posts_read_count"}}</dt>
|
||||
<dd>{{model.posts_read_count}}</dd>
|
||||
</dl>
|
||||
<h3 class='stats-title'>{{i18n "user.summary.stats"}}</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<span class='value'>{{model.time_read}}</span>
|
||||
<span class='label'>{{{i18n "user.summary.time_read"}}}</span>
|
||||
</li>
|
||||
<li>{{user-stat value=model.topic_count label="user.summary.topic_count"}}</li>
|
||||
<li>{{user-stat value=model.post_count label="user.summary.post_count"}}</li>
|
||||
<li>{{user-stat value=model.likes_received label="user.summary.likes_received"}}</li>
|
||||
<li>{{user-stat value=model.likes_given label="user.summary.likes_given"}}</li>
|
||||
<li>{{user-stat value=model.days_visited label="user.summary.days_visited"}}</li>
|
||||
<li>{{user-stat value=model.posts_read_count label="user.summary.posts_read"}}</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class='top-section'>
|
||||
<div class='replies-section'>
|
||||
<h3 class='stats-title'>{{i18n "user.summary.top_replies"}}</h3>
|
||||
{{#if model.replies.length}}
|
||||
<ul>
|
||||
{{#each reply in model.replies}}
|
||||
<li>
|
||||
<span class='topic-info'>
|
||||
{{format-date reply.createdAt format="tiny" noTitle="true"}}
|
||||
{{#if reply.like_count}}
|
||||
·
|
||||
<span class='like-count'>{{number reply.like_count}} {{fa-icon 'heart'}}</span>
|
||||
{{/if}}
|
||||
</span>
|
||||
<br>
|
||||
<span>
|
||||
<a href="{{reply.url}}">{{{reply.topic.fancyTitle}}}</a>
|
||||
</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#if moreReplies}}
|
||||
<p>{{#link-to "userActivity.replies" user class="more"}}{{i18n "user.summary.more_replies"}}{{/link-to}}</p>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<p>{{i18n "user.summary.no_replies"}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class='topics-section'>
|
||||
<h3 class='stats-title'>{{i18n "user.summary.top_topics"}}</h3>
|
||||
{{#if model.topics.length}}
|
||||
<ul>
|
||||
{{#each topic in model.topics}}
|
||||
<li>
|
||||
<span class='topic-info'>
|
||||
{{format-date topic.createdAt format="tiny" noTitle="true"}}
|
||||
{{#if topic.like_count}}
|
||||
·
|
||||
<span class='like-count'>{{number topic.like_count}} {{fa-icon 'heart'}}</span>
|
||||
{{/if}}
|
||||
</span>
|
||||
<br>
|
||||
<span>
|
||||
<a href="{{topic.url}}">{{{topic.fancyTitle}}}</a>
|
||||
</span>
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{#if moreTopics}}
|
||||
<p>{{#link-to "userActivity.topics" user class="more"}}{{i18n "user.summary.more_topics"}}{{/link-to}}</p>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<p>{{i18n "user.summary.no_topics"}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if model.badges.length}}
|
||||
<div class='top-section badges-section'>
|
||||
<h3>{{i18n "user.summary.top_badges"}}</h3>
|
||||
{{#each badge in model.badges}}
|
||||
{{user-badge badge=badge count=badge.count user=user}}
|
||||
{{/each}}
|
||||
{{#if moreBadges}}
|
||||
{{#link-to "user.badges" user class="more"}}{{i18n "user.summary.more_badges"}}{{/link-to}}
|
||||
{{/if}}
|
||||
<h3 class='stats-title'>{{i18n "user.summary.top_badges"}}</h3>
|
||||
{{#each badge in model.badges}}
|
||||
{{badge-card badge=badge count=badge.count navigateOnClick="true" username=user.username_lower}}
|
||||
{{else}}
|
||||
<p>{{i18n "user.summary.no_badges"}}</p>
|
||||
{{/each}}
|
||||
{{#if moreBadges}}
|
||||
<p>{{#link-to "user.badges" user class="more"}}{{i18n "user.summary.more_badges"}}{{/link-to}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -57,6 +57,7 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-info.medium.badge-info {
|
||||
min-height: 80px;
|
||||
|
||||
|
@ -194,6 +195,12 @@
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
@media all and (max-width: 320px) {
|
||||
.badge-card.medium {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.badge-card.large {
|
||||
width: 750px;
|
||||
}
|
||||
|
|
|
@ -190,59 +190,82 @@
|
|||
}
|
||||
|
||||
.top-section {
|
||||
display: inline-block;
|
||||
width: 45%;
|
||||
max-width: 500px;
|
||||
padding-right: 20px;
|
||||
vertical-align: top;
|
||||
margin-bottom: 30px;
|
||||
.more {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 60%));
|
||||
}
|
||||
h3 {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.relative-date {
|
||||
color: lighten($primary, 40%);
|
||||
font-size: 0.8em;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.like-count {
|
||||
margin-left: 5px;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
li {
|
||||
margin: 0;
|
||||
padding: 8px 0;
|
||||
.fa-heart {
|
||||
margin-left: 3px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.top-section,
|
||||
.replies-section,
|
||||
.topics-section {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.stats-title {
|
||||
text-transform: uppercase;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.stats-section {
|
||||
ul {
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
dt,dd {
|
||||
float:left;
|
||||
li {
|
||||
display: inline-block;
|
||||
padding: 10px 14px;
|
||||
margin: 0 5px 10px 0;
|
||||
background: dark-light-diff($primary, $secondary, 90%, -65%);
|
||||
}
|
||||
dd {
|
||||
min-width: 80px;
|
||||
text-align: right;
|
||||
|
||||
li:last-of-type {
|
||||
margin: 0;
|
||||
}
|
||||
dt {
|
||||
clear: left;
|
||||
min-width: 100px;
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 25%), scale-color($secondary, $lightness: 75%));
|
||||
|
||||
.value {
|
||||
font-weight: bold;
|
||||
font-size: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
.replies-section,
|
||||
.topics-section {
|
||||
width: 50%;
|
||||
|
||||
ul {
|
||||
max-width: 95%;
|
||||
}
|
||||
|
||||
li {
|
||||
border-left: dark-light-diff($primary, $secondary, 90%, -65%) solid 2px;
|
||||
padding: 5px 8px;
|
||||
margin: 10px 0;
|
||||
}
|
||||
|
||||
.topic-info {
|
||||
color: dark-light-choose(scale-color($primary, $lightness: 40%), scale-color($secondary, $lightness: 40%));
|
||||
}
|
||||
}
|
||||
|
||||
.replies-section {
|
||||
float: left;
|
||||
}
|
||||
|
||||
.topics-section {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.badges-section {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
@media all
|
||||
and (max-width : 600px) {
|
||||
.top-section {
|
||||
width: 90%;
|
||||
.replies-section,
|
||||
.topics-section {
|
||||
float: none;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@
|
|||
}
|
||||
&:hover {
|
||||
background: dark-light-diff($primary, $secondary, 65%, -75%);
|
||||
color: #fff;
|
||||
color: $secondary;
|
||||
}
|
||||
&[disabled], &.disabled {
|
||||
background: dark-light-diff($primary, $secondary, 90%, -60%);
|
||||
|
@ -80,7 +80,7 @@
|
|||
}
|
||||
&:active {
|
||||
@include linear-gradient(scale-color($tertiary, $lightness: -20%), scale-color($tertiary, $lightness: -10%));
|
||||
color: #fff;
|
||||
color: $secondary;
|
||||
}
|
||||
&[disabled], &.disabled {
|
||||
background: $tertiary;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
class UserSummary
|
||||
|
||||
MAX_FEATURED_BADGES = 10
|
||||
MAX_BADGES = 6
|
||||
MAX_TOPICS = 6
|
||||
|
||||
alias :read_attribute_for_serialization :send
|
||||
|
@ -18,7 +18,7 @@ class UserSummary
|
|||
.listable_topics
|
||||
.visible
|
||||
.where(user: @user)
|
||||
.order('like_count desc, created_at asc')
|
||||
.order('like_count DESC, created_at ASC')
|
||||
.includes(:user, :category)
|
||||
.limit(MAX_TOPICS)
|
||||
end
|
||||
|
@ -26,26 +26,31 @@ class UserSummary
|
|||
def replies
|
||||
Post
|
||||
.secured(@guardian)
|
||||
.includes(:user, {topic: :category})
|
||||
.includes(:user, topic: :category)
|
||||
.references(:topic)
|
||||
.merge(Topic.listable_topics.visible.secured(@guardian))
|
||||
.where(user: @user)
|
||||
.where('post_number > 1')
|
||||
.where('topics.archetype <> ?', Archetype.private_message)
|
||||
.order('posts.like_count desc, posts.created_at asc')
|
||||
.order('posts.like_count DESC, posts.created_at ASC')
|
||||
.limit(MAX_TOPICS)
|
||||
end
|
||||
|
||||
def badges
|
||||
@user.featured_user_badges(MAX_FEATURED_BADGES)
|
||||
@user.featured_user_badges(MAX_BADGES)
|
||||
end
|
||||
|
||||
def user_stat
|
||||
@user.user_stat
|
||||
end
|
||||
|
||||
delegate :likes_given, :likes_received, :days_visited,
|
||||
:posts_read_count, :topic_count, :post_count,
|
||||
delegate :likes_given,
|
||||
:likes_received,
|
||||
:days_visited,
|
||||
:posts_read_count,
|
||||
:topic_count,
|
||||
:post_count,
|
||||
:time_read,
|
||||
to: :user_stat
|
||||
|
||||
end
|
||||
|
|
|
@ -12,11 +12,19 @@ class UserSummarySerializer < ApplicationSerializer
|
|||
has_many :replies, serializer: ReplySerializer, embed: :object
|
||||
has_many :badges, serializer: UserBadgeSerializer, embed: :object
|
||||
|
||||
attributes :likes_given, :likes_received, :posts_read_count,
|
||||
:days_visited, :topic_count, :post_count
|
||||
|
||||
attributes :likes_given,
|
||||
:likes_received,
|
||||
:posts_read_count,
|
||||
:days_visited,
|
||||
:topic_count,
|
||||
:post_count,
|
||||
:time_read
|
||||
|
||||
def include_badges?
|
||||
SiteSetting.enable_badges
|
||||
end
|
||||
|
||||
def time_read
|
||||
AgeWords.age_words(object.time_read)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -734,17 +734,33 @@ en:
|
|||
summary:
|
||||
title: "Summary"
|
||||
stats: "Stats"
|
||||
topic_count: "Topics Created"
|
||||
post_count: "Posts Created"
|
||||
likes_given: "Likes Given"
|
||||
likes_received: "Likes Received"
|
||||
days_visited: "Days Visited"
|
||||
posts_read_count: "Posts Read"
|
||||
time_read: "read time"
|
||||
topic_count:
|
||||
one: "topic created"
|
||||
other: "topics created"
|
||||
post_count:
|
||||
one: "post created"
|
||||
other: "posts created"
|
||||
likes_given:
|
||||
one: "like given"
|
||||
other: "likes given"
|
||||
likes_received:
|
||||
one: "like received"
|
||||
other: "likes received"
|
||||
days_visited:
|
||||
one: "day visited"
|
||||
other: "days visited"
|
||||
posts_read:
|
||||
one: "post read"
|
||||
other: "posts read"
|
||||
top_replies: "Top Replies"
|
||||
top_topics: "Top Topics"
|
||||
top_badges: "Top Badges"
|
||||
more_topics: "More Topics"
|
||||
no_replies: "No replies yet."
|
||||
more_replies: "More Replies"
|
||||
top_topics: "Top Topics"
|
||||
no_topics: "No topics yet."
|
||||
more_topics: "More Topics"
|
||||
top_badges: "Top Badges"
|
||||
no_badges: "No badges yet."
|
||||
more_badges: "More Badges"
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue