diff --git a/app/assets/javascripts/discourse/components/user-summary-section.js.es6 b/app/assets/javascripts/discourse/components/user-summary-section.js.es6 new file mode 100644 index 00000000000..bc13ab36443 --- /dev/null +++ b/app/assets/javascripts/discourse/components/user-summary-section.js.es6 @@ -0,0 +1,3 @@ +export default Ember.Component.extend({ + classNames: ['top-sub-section'] +}); diff --git a/app/assets/javascripts/discourse/components/user-summary-topic.js.es6 b/app/assets/javascripts/discourse/components/user-summary-topic.js.es6 new file mode 100644 index 00000000000..d100e27e252 --- /dev/null +++ b/app/assets/javascripts/discourse/components/user-summary-topic.js.es6 @@ -0,0 +1,3 @@ +export default Ember.Component.extend({ + tagName: 'li' +}); diff --git a/app/assets/javascripts/discourse/components/user-summary-topics-list.js.es6 b/app/assets/javascripts/discourse/components/user-summary-topics-list.js.es6 new file mode 100644 index 00000000000..ccdf6ef0f9e --- /dev/null +++ b/app/assets/javascripts/discourse/components/user-summary-topics-list.js.es6 @@ -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; + } +}); diff --git a/app/assets/javascripts/discourse/components/user-summary-user.js.es6 b/app/assets/javascripts/discourse/components/user-summary-user.js.es6 new file mode 100644 index 00000000000..d100e27e252 --- /dev/null +++ b/app/assets/javascripts/discourse/components/user-summary-user.js.es6 @@ -0,0 +1,3 @@ +export default Ember.Component.extend({ + tagName: 'li' +}); diff --git a/app/assets/javascripts/discourse/controllers/user-summary.js.es6 b/app/assets/javascripts/discourse/controllers/user-summary.js.es6 index c40014854cb..bb4bec20775 100644 --- a/app/assets/javascripts/discourse/controllers/user-summary.js.es6 +++ b/app/assets/javascripts/discourse/controllers/user-summary.js.es6 @@ -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; }, }); diff --git a/app/assets/javascripts/discourse/models/user.js.es6 b/app/assets/javascripts/discourse/models/user.js.es6 index 10a822a4e99..b8adf073d89 100644 --- a/app/assets/javascripts/discourse/models/user.js.es6 +++ b/app/assets/javascripts/discourse/models/user.js.es6 @@ -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) { diff --git a/app/assets/javascripts/discourse/templates/components/user-stat.hbs b/app/assets/javascripts/discourse/templates/components/user-stat.hbs index 72bfaedac6e..d4ec14677c5 100644 --- a/app/assets/javascripts/discourse/templates/components/user-stat.hbs +++ b/app/assets/javascripts/discourse/templates/components/user-stat.hbs @@ -1,5 +1,7 @@ - {{#if icon}}{{d-icon icon}}{{/if}} {{number value}} -{{{i18n label count=value}}} + + {{#if icon}}{{d-icon icon}}{{/if}} + {{{i18n label count=value}}} + diff --git a/app/assets/javascripts/discourse/templates/components/user-summary-section.hbs b/app/assets/javascripts/discourse/templates/components/user-summary-section.hbs new file mode 100644 index 00000000000..28bdf9d7b8f --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/user-summary-section.hbs @@ -0,0 +1,2 @@ +

{{i18n (concat "user.summary." title)}}

+{{yield}} diff --git a/app/assets/javascripts/discourse/templates/components/user-summary-topic.hbs b/app/assets/javascripts/discourse/templates/components/user-summary-topic.hbs new file mode 100644 index 00000000000..056b9cf0888 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/user-summary-topic.hbs @@ -0,0 +1,9 @@ + + {{format-date createdAt format="tiny" noTitle="true"}} + {{#if likes}} + · + {{d-icon 'heart'}} {{number likes}} + {{/if}} + +
+{{{topic.fancyTitle}}} diff --git a/app/assets/javascripts/discourse/templates/components/user-summary-topics-list.hbs b/app/assets/javascripts/discourse/templates/components/user-summary-topics-list.hbs new file mode 100644 index 00000000000..a74e5d6a230 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/user-summary-topics-list.hbs @@ -0,0 +1,16 @@ +{{#if items}} + + {{#if hasMore}} +

+ {{#link-to (concat "userActivity." type) user class="more"}} + {{i18n (concat "user.summary.more_" type)}} + {{/link-to}} +

+ {{/if}} +{{else}} +

{{i18n (concat "user.summary.no_" type)}}

+{{/if}} diff --git a/app/assets/javascripts/discourse/templates/components/user-summary-user.hbs b/app/assets/javascripts/discourse/templates/components/user-summary-user.hbs new file mode 100644 index 00000000000..876702f1957 --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/user-summary-user.hbs @@ -0,0 +1,4 @@ +{{#user-info user=user}} + {{d-icon icon}} + {{number user.count}} +{{/user-info}} diff --git a/app/assets/javascripts/discourse/templates/components/user-summary-users-list.hbs b/app/assets/javascripts/discourse/templates/components/user-summary-users-list.hbs new file mode 100644 index 00000000000..1b291b638af --- /dev/null +++ b/app/assets/javascripts/discourse/templates/components/user-summary-users-list.hbs @@ -0,0 +1,9 @@ +{{#if users}} + +{{else}} +

{{i18n (concat "user.summary." none)}}

+{{/if}} diff --git a/app/assets/javascripts/discourse/templates/user/summary.hbs b/app/assets/javascripts/discourse/templates/user/summary.hbs index d28eef4a30a..5ee7df597f5 100644 --- a/app/assets/javascripts/discourse/templates/user/summary.hbs +++ b/app/assets/javascripts/discourse/templates/user/summary.hbs @@ -14,7 +14,7 @@
  • {{#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}}
  • {{#if model.bookmark_count}} @@ -35,70 +35,36 @@ {{/link-to}}
  • - {{user-stat value=model.likes_received label="user.summary.likes_received"}} + {{user-stat value=model.likes_received icon="heart" label="user.summary.likes_received"}}
  • - {{plugin-outlet name="user-summary-stat" - connectorTagName="li" - args=(hash model=model)}} + {{plugin-outlet name="user-summary-stat" connectorTagName="li" args=(hash model=model)}}
    -
    -

    {{i18n "user.summary.top_replies"}}

    - {{#if model.replies.length}} - - {{#if moreReplies}} -

    {{#link-to "userActivity.replies" user class="more"}}{{i18n "user.summary.more_replies"}}{{/link-to}}

    - {{/if}} - {{else}} -

    {{i18n "user.summary.no_replies"}}

    - {{/if}} -
    -
    -

    {{i18n "user.summary.top_topics"}}

    - {{#if model.topics.length}} - - {{#if moreTopics}} -

    {{#link-to "userActivity.topics" user class="more"}}{{i18n "user.summary.more_topics"}}{{/link-to}}

    - {{/if}} - {{else}} -

    {{i18n "user.summary.no_topics"}}

    - {{/if}} -
    + {{#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}}
    - -
    -

    {{i18n "user.summary.most_replied_to_users"}}

    - {{#if model.most_replied_to_users.length}} - - {{else}} -

    {{i18n "user.summary.no_replies"}}

    - {{/if}} -
    + {{/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}}
    -
    -

    {{i18n "user.summary.most_liked_by"}}

    - {{#if model.most_liked_by_users.length}} - - {{else}} -

    {{i18n "user.summary.no_likes"}}

    - {{/if}} -
    -
    -

    {{i18n "user.summary.most_liked_users"}}

    - {{#if model.most_liked_users.length}} - - {{else}} -

    {{i18n "user.summary.no_likes"}}

    - {{/if}} -
    + {{#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}}
    {{#if siteSettings.enable_badges}} diff --git a/app/assets/stylesheets/common/base/user.scss b/app/assets/stylesheets/common/base/user.scss index f397d38508e..4719c6c4468 100644 --- a/app/assets/stylesheets/common/base/user.scss +++ b/app/assets/stylesheets/common/base/user.scss @@ -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; } diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml index eb1fadc9931..548dd602802 100644 --- a/config/locales/client.en.yml +++ b/config/locales/client.en.yml @@ -895,11 +895,11 @@ en: one: "post created" other: "posts created" likes_given: - one: " given" - other: " given" + one: "given" + other: "given" likes_received: - one: " received" - other: " received" + one: "received" + other: "received" days_visited: one: "day visited" other: "days visited" diff --git a/test/javascripts/acceptance/user-test.js.es6 b/test/javascripts/acceptance/user-test.js.es6 index 22759a7ee7e..261a9b66327 100644 --- a/test/javascripts/acceptance/user-test.js.es6 +++ b/test/javascripts/acceptance/user-test.js.es6 @@ -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"); }); -}); \ No newline at end of file +}); + +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'); + }); +}); diff --git a/test/javascripts/helpers/create-pretender.js.es6 b/test/javascripts/helpers/create-pretender.js.es6 index a466f632ccc..60c57629055 100644 --- a/test/javascripts/helpers/create-pretender.js.es6 +++ b/test/javascripts/helpers/create-pretender.js.es6 @@ -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' } + ], }); });