Refactor user summary page to use more components

This commit is contained in:
Robin Ward 2017-10-13 15:20:42 -04:00
parent f73a3cc0d4
commit 5572d1d5f7
17 changed files with 172 additions and 157 deletions

View File

@ -0,0 +1,3 @@
export default Ember.Component.extend({
classNames: ['top-sub-section']
});

View File

@ -0,0 +1,3 @@
export default Ember.Component.extend({
tagName: 'li'
});

View File

@ -0,0 +1,13 @@
import computed from 'ember-addons/ember-computed-decorators';
// should be kept in sync with 'UserSummary::MAX_SUMMARY_RESULTS'
const MAX_SUMMARY_RESULTS = 6;
export default Ember.Component.extend({
tagName: '',
@computed('items.length')
hasMore(length) {
return length >= MAX_SUMMARY_RESULTS;
}
});

View File

@ -0,0 +1,3 @@
export default Ember.Component.extend({
tagName: 'li'
});

View File

@ -1,7 +1,5 @@
import computed from 'ember-addons/ember-computed-decorators';
// should be kept in sync with 'UserSummary::MAX_SUMMARY_RESULTS'
const MAX_SUMMARY_RESULTS = 6;
// should be kept in sync with 'UserSummary::MAX_BADGES'
const MAX_BADGES = 6;
@ -9,12 +7,6 @@ export default Ember.Controller.extend({
userController: Ember.inject.controller('user'),
user: Ember.computed.alias('userController.model'),
@computed("model.topics.length")
moreTopics(topicsLength) { return topicsLength >= MAX_SUMMARY_RESULTS; },
@computed("model.replies.length")
moreReplies(repliesLength) { return repliesLength >= MAX_SUMMARY_RESULTS; },
@computed("model.badges.length")
moreBadges(badgesLength) { return badgesLength >= MAX_BADGES; },
});

View File

@ -11,7 +11,6 @@ import UserBadge from 'discourse/models/user-badge';
import UserActionStat from 'discourse/models/user-action-stat';
import UserAction from 'discourse/models/user-action';
import Group from 'discourse/models/group';
import Topic from 'discourse/models/topic';
import { emojiUnescape } from 'discourse/lib/text';
import PreloadStore from 'preload-store';
import { defaultHomepage } from 'discourse/lib/utilities';
@ -492,38 +491,39 @@ const User = RestModel.extend({
},
summary() {
return ajax(userPath(`${this.get("username_lower")}/summary.json`))
.then(json => {
const summary = json["user_summary"];
const topicMap = {};
const badgeMap = {};
let { store } = this;
json.topics.forEach(t => topicMap[t.id] = Topic.create(t));
Badge.createFromJson(json).forEach(b => badgeMap[b.id] = b );
return ajax(userPath(`${this.get("username_lower")}/summary.json`)).then(json => {
const summary = json.user_summary;
const topicMap = {};
const badgeMap = {};
summary.topics = summary.topic_ids.map(id => topicMap[id]);
json.topics.forEach(t => topicMap[t.id] = store.createRecord('topic', t));
Badge.createFromJson(json).forEach(b => badgeMap[b.id] = b );
summary.replies.forEach(r => {
r.topic = topicMap[r.topic_id];
r.url = r.topic.urlForPostNumber(r.post_number);
r.createdAt = new Date(r.created_at);
});
summary.topics = summary.topic_ids.map(id => topicMap[id]);
summary.links.forEach(l => {
l.topic = topicMap[l.topic_id];
l.post_url = l.topic.urlForPostNumber(l.post_number);
});
summary.replies.forEach(r => {
r.topic = topicMap[r.topic_id];
r.url = r.topic.urlForPostNumber(r.post_number);
r.createdAt = new Date(r.created_at);
});
if (summary.badges) {
summary.badges = summary.badges.map(ub => {
const badge = badgeMap[ub.badge_id];
badge.count = ub.count;
return badge;
});
}
summary.links.forEach(l => {
l.topic = topicMap[l.topic_id];
l.post_url = l.topic.urlForPostNumber(l.post_number);
});
return summary;
});
if (summary.badges) {
summary.badges = summary.badges.map(ub => {
const badge = badgeMap[ub.badge_id];
badge.count = ub.count;
return badge;
});
}
return summary;
});
},
canManageGroup(group) {

View File

@ -1,5 +1,7 @@
<span class='value'>
{{#if icon}}{{d-icon icon}}{{/if}}
{{number value}}
</span>
<span class='label'>{{{i18n label count=value}}}</span>
<span class='label'>
{{#if icon}}{{d-icon icon}}{{/if}}
{{{i18n label count=value}}}
</span>

View File

@ -0,0 +1,2 @@
<h3 class='stats-title'>{{i18n (concat "user.summary." title)}}</h3>
{{yield}}

View File

@ -0,0 +1,9 @@
<span class='topic-info'>
{{format-date createdAt format="tiny" noTitle="true"}}
{{#if likes}}
&middot;
{{d-icon 'heart'}}&nbsp;<span class='like-count'>{{number likes}}</span>
{{/if}}
</span>
<br>
<a href="{{unbound url}}">{{{topic.fancyTitle}}}</a>

View File

@ -0,0 +1,16 @@
{{#if items}}
<ul>
{{#each items as |item|}}
{{yield item}}
{{/each}}
</ul>
{{#if hasMore}}
<p>
{{#link-to (concat "userActivity." type) user class="more"}}
{{i18n (concat "user.summary.more_" type)}}
{{/link-to}}
</p>
{{/if}}
{{else}}
<p>{{i18n (concat "user.summary.no_" type)}}</p>
{{/if}}

View File

@ -0,0 +1,4 @@
{{#user-info user=user}}
{{d-icon icon}}
<span class={{countClass}}>{{number user.count}}</span>
{{/user-info}}

View File

@ -0,0 +1,9 @@
{{#if users}}
<ul>
{{#each users as |user|}}
{{yield user}}
{{/each}}
</ul>
{{else}}
<p>{{i18n (concat "user.summary." none)}}</p>
{{/if}}

View File

@ -14,7 +14,7 @@
</li>
<li class="linked-stat">
{{#link-to 'userActivity.likesGiven'}}
{{user-stat value=model.likes_given label="user.summary.likes_given"}}
{{user-stat value=model.likes_given icon="heart" label="user.summary.likes_given"}}
{{/link-to}}
</li>
{{#if model.bookmark_count}}
@ -35,70 +35,36 @@
{{/link-to}}
</li>
<li>
{{user-stat value=model.likes_received label="user.summary.likes_received"}}
{{user-stat value=model.likes_received icon="heart" label="user.summary.likes_received"}}
</li>
{{plugin-outlet name="user-summary-stat"
connectorTagName="li"
args=(hash model=model)}}
{{plugin-outlet name="user-summary-stat" connectorTagName="li" args=(hash model=model)}}
</ul>
</div>
<div class='top-section'>
<div class='top-sub-section replies-section pull-left'>
<h3 class='stats-title'>{{i18n "user.summary.top_replies"}}</h3>
{{#if model.replies.length}}
<ul>
{{#each model.replies as |reply|}}
<li>
<span class='topic-info'>
{{format-date reply.createdAt format="tiny" noTitle="true"}}
{{#if reply.like_count}}
&middot;
{{d-icon 'heart'}}&nbsp;<span class='like-count'>{{number reply.like_count}}</span>
{{/if}}
</span>
<br>
<a href="{{unbound reply.url}}">{{{reply.topic.fancyTitle}}}</a>
</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='top-sub-section topics-section pull-right'>
<h3 class='stats-title'>{{i18n "user.summary.top_topics"}}</h3>
{{#if model.topics.length}}
<ul>
{{#each model.topics as |topic|}}
<li>
<span class='topic-info'>
{{format-date topic.createdAt format="tiny" noTitle="true"}}
{{#if topic.like_count}}
&middot;
{{d-icon 'heart'}}&nbsp;<span class='like-count'>{{number topic.like_count}}</span>
{{/if}}
</span>
<br>
<a href="{{unbound topic.url}}">{{{topic.fancyTitle}}}</a>
</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>
{{#user-summary-section title="top_replies" class="replies-section pull-left"}}
{{#user-summary-topics-list type="replies" items=model.replies user=user as |reply|}}
{{user-summary-topic
createdAt=reply.createdAt
topic=reply.topic
likes=reply.like_count
url=reply.url}}
{{/user-summary-topics-list}}
{{/user-summary-section}}
{{#user-summary-section title="top_topics" class="topics-section pull-right"}}
{{#user-summary-topics-list type="topics" items=model.topics user=user as |topic|}}
{{user-summary-topic
createdAt=topic.created_at
topic=topic
likes=topic.like_count
url=topic.url}}
{{/user-summary-topics-list}}
{{/user-summary-section}}
</div>
<div class='top-section'>
<div class='top-sub-section links-section pull-left'>
<h3 class='stats-title'>{{i18n "user.summary.top_links"}}</h3>
{{#user-summary-section title="top_links" class="links-section pull-left"}}
{{#if model.links.length}}
<ul>
{{#each model.links as |link|}}
@ -119,61 +85,27 @@
{{else}}
<p>{{i18n "user.summary.no_links"}}</p>
{{/if}}
</div>
<div class='top-sub-section likes-section pull-right'>
<h3 class='stats-title'>{{i18n "user.summary.most_replied_to_users"}}</h3>
{{#if model.most_replied_to_users.length}}
<ul>
{{#each model.most_replied_to_users as |user|}}
<li>
{{#user-info user=user}}
{{d-icon "reply"}}
<span class='replies'>{{number user.count}}</span>
{{/user-info}}
</li>
{{/each}}
</ul>
{{else}}
<p>{{i18n "user.summary.no_replies"}}</p>
{{/if}}
</div>
{{/user-summary-section}}
{{#user-summary-section title="most_replied_to_users" class="summary-user-list replied-section pull-right"}}
{{#user-summary-users-list none="no_replies" users=model.most_replied_to_users as |user|}}
{{user-summary-user user=user icon="reply" countClass="replies"}}
{{/user-summary-users-list}}
{{/user-summary-section}}
</div>
<div class='top-section most-liked-section'>
<div class='top-sub-section likes-section pull-left'>
<h3 class='stats-title'>{{i18n "user.summary.most_liked_by"}}</h3>
{{#if model.most_liked_by_users.length}}
<ul>
{{#each model.most_liked_by_users as |user|}}
<li>
{{#user-info user=user}}
{{d-icon "heart"}}
<span class='likes'>{{number user.count}}</span>
{{/user-info}}
</li>
{{/each}}
</ul>
{{else}}
<p>{{i18n "user.summary.no_likes"}}</p>
{{/if}}
</div>
<div class='top-sub-section likes-section pull-right'>
<h3 class='stats-title'>{{i18n "user.summary.most_liked_users"}}</h3>
{{#if model.most_liked_users.length}}
<ul>
{{#each model.most_liked_users as |user|}}
<li>
{{#user-info user=user}}
{{d-icon "heart"}}
<span class='likes'>{{number user.count}}</span>
{{/user-info}}
</li>
{{/each}}
</ul>
{{else}}
<p>{{i18n "user.summary.no_likes"}}</p>
{{/if}}
</div>
{{#user-summary-section title="most_liked_by" class="summary-user-list liked-by-section pull-left"}}
{{#user-summary-users-list none="no_likes" users=model.most_liked_by_users as |user|}}
{{user-summary-user user=user icon="heart" countClass="likes"}}
{{/user-summary-users-list}}
{{/user-summary-section}}
{{#user-summary-section title="most_liked_users" class="summary-user-list liked-section pull-right"}}
{{#user-summary-users-list none="no_likes" users=model.most_liked_users as |user|}}
{{user-summary-user user=user icon="heart" countClass="likes"}}
{{/user-summary-users-list}}
{{/user-summary-section}}
</div>
{{#if siteSettings.enable_badges}}

View File

@ -397,6 +397,12 @@
}
.label {
// TODO: Remove once all languages have been translated to remove icons from
// their user-stat labels
.fa:nth-of-type(2) {
display: none;
}
color: blend-primary-secondary(50%);
}
}
@ -439,7 +445,7 @@
}
}
.likes-section {
.summary-user-list {
li {
height: 40px;
}

View File

@ -895,11 +895,11 @@ en:
one: "post created"
other: "posts created"
likes_given:
one: "<i class='fa fa-heart'></i> given"
other: "<i class='fa fa-heart'></i> given"
one: "given"
other: "given"
likes_received:
one: "<i class='fa fa-heart'></i> received"
other: "<i class='fa fa-heart'></i> received"
one: "received"
other: "received"
days_visited:
one: "day visited"
other: "days visited"

View File

@ -30,4 +30,17 @@ QUnit.test("Root URL - Viewing Self", assert => {
assert.equal(currentPath(), 'user.userActivity.index', "it defaults to activity");
assert.ok(exists('.container.viewing-self'), "has the viewing-self class");
});
});
});
QUnit.test("Viewing Summary", assert => {
visit("/u/eviltrout/summary");
andThen(() => {
assert.ok(exists('.replies-section li a'), 'replies');
assert.ok(exists('.topics-section li a'), 'topics');
assert.ok(exists('.links-section li a'), 'links');
assert.ok(exists('.replied-section .user-info'), 'liked by');
assert.ok(exists('.liked-by-section .user-info'), 'liked by');
assert.ok(exists('.liked-section .user-info'), 'liked');
assert.ok(exists('.badges-section .badge-card'), 'badges');
});
});

View File

@ -81,12 +81,20 @@ export default function() {
this.get('/u/eviltrout/summary.json', () => {
return response({
user_summary: {
topics: [],
topic_ids: [],
replies: [],
links: []
topic_ids: [1234],
replies: [{ topic_id: 1234 }],
links: [{ topic_id: 1234, url: 'https://eviltrout.com' }],
most_replied_to_users: [ { id: 333 } ],
most_liked_by_users: [ { id: 333 } ],
most_liked_users: [ { id: 333 } ],
badges: [ { badge_id: 444 } ]
},
topics: [],
badges: [
{ id: 444, count: 1 }
],
topics: [
{ id: 1234, title: 'cool title', url: '/t/1234/cool-title' }
],
});
});