Refactor user summary page to use more components
This commit is contained in:
parent
f73a3cc0d4
commit
5572d1d5f7
|
@ -0,0 +1,3 @@
|
|||
export default Ember.Component.extend({
|
||||
classNames: ['top-sub-section']
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
export default Ember.Component.extend({
|
||||
tagName: 'li'
|
||||
});
|
|
@ -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;
|
||||
}
|
||||
});
|
|
@ -0,0 +1,3 @@
|
|||
export default Ember.Component.extend({
|
||||
tagName: 'li'
|
||||
});
|
|
@ -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; },
|
||||
});
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
<h3 class='stats-title'>{{i18n (concat "user.summary." title)}}</h3>
|
||||
{{yield}}
|
|
@ -0,0 +1,9 @@
|
|||
<span class='topic-info'>
|
||||
{{format-date createdAt format="tiny" noTitle="true"}}
|
||||
{{#if likes}}
|
||||
·
|
||||
{{d-icon 'heart'}} <span class='like-count'>{{number likes}}</span>
|
||||
{{/if}}
|
||||
</span>
|
||||
<br>
|
||||
<a href="{{unbound url}}">{{{topic.fancyTitle}}}</a>
|
|
@ -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}}
|
|
@ -0,0 +1,4 @@
|
|||
{{#user-info user=user}}
|
||||
{{d-icon icon}}
|
||||
<span class={{countClass}}>{{number user.count}}</span>
|
||||
{{/user-info}}
|
|
@ -0,0 +1,9 @@
|
|||
{{#if users}}
|
||||
<ul>
|
||||
{{#each users as |user|}}
|
||||
{{yield user}}
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{else}}
|
||||
<p>{{i18n (concat "user.summary." none)}}</p>
|
||||
{{/if}}
|
|
@ -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}}
|
||||
·
|
||||
{{d-icon 'heart'}} <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}}
|
||||
·
|
||||
{{d-icon 'heart'}} <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}}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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' }
|
||||
],
|
||||
});
|
||||
});
|
||||
|
||||
|
|
Loading…
Reference in New Issue