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'; 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' // should be kept in sync with 'UserSummary::MAX_BADGES'
const MAX_BADGES = 6; const MAX_BADGES = 6;
@ -9,12 +7,6 @@ export default Ember.Controller.extend({
userController: Ember.inject.controller('user'), userController: Ember.inject.controller('user'),
user: Ember.computed.alias('userController.model'), 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") @computed("model.badges.length")
moreBadges(badgesLength) { return badgesLength >= MAX_BADGES; }, 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 UserActionStat from 'discourse/models/user-action-stat';
import UserAction from 'discourse/models/user-action'; import UserAction from 'discourse/models/user-action';
import Group from 'discourse/models/group'; import Group from 'discourse/models/group';
import Topic from 'discourse/models/topic';
import { emojiUnescape } from 'discourse/lib/text'; import { emojiUnescape } from 'discourse/lib/text';
import PreloadStore from 'preload-store'; import PreloadStore from 'preload-store';
import { defaultHomepage } from 'discourse/lib/utilities'; import { defaultHomepage } from 'discourse/lib/utilities';
@ -492,13 +491,14 @@ const User = RestModel.extend({
}, },
summary() { summary() {
return ajax(userPath(`${this.get("username_lower")}/summary.json`)) let { store } = this;
.then(json => {
const summary = json["user_summary"]; return ajax(userPath(`${this.get("username_lower")}/summary.json`)).then(json => {
const summary = json.user_summary;
const topicMap = {}; const topicMap = {};
const badgeMap = {}; const badgeMap = {};
json.topics.forEach(t => topicMap[t.id] = Topic.create(t)); json.topics.forEach(t => topicMap[t.id] = store.createRecord('topic', t));
Badge.createFromJson(json).forEach(b => badgeMap[b.id] = b ); Badge.createFromJson(json).forEach(b => badgeMap[b.id] = b );
summary.topics = summary.topic_ids.map(id => topicMap[id]); summary.topics = summary.topic_ids.map(id => topicMap[id]);

View File

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

View File

@ -397,6 +397,12 @@
} }
.label { .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%); color: blend-primary-secondary(50%);
} }
} }
@ -439,7 +445,7 @@
} }
} }
.likes-section { .summary-user-list {
li { li {
height: 40px; height: 40px;
} }

View File

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

View File

@ -31,3 +31,16 @@ QUnit.test("Root URL - Viewing Self", assert => {
assert.ok(exists('.container.viewing-self'), "has the viewing-self class"); 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', () => { this.get('/u/eviltrout/summary.json', () => {
return response({ return response({
user_summary: { user_summary: {
topics: [], topic_ids: [1234],
topic_ids: [], replies: [{ topic_id: 1234 }],
replies: [], links: [{ topic_id: 1234, url: 'https://eviltrout.com' }],
links: [] 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' }
],
}); });
}); });