PERF: unify topic lists, remove star from lists, move to raw rendering

This commit is contained in:
Sam 2015-01-05 09:01:35 +11:00
parent fe57ebcd33
commit fa9bbd554e
20 changed files with 158 additions and 117 deletions

View File

@ -30,12 +30,6 @@ export default Ember.Component.extend({
// Without a topic list, we assume it's loaded always.
this.set('loaded', true);
}
},
actions: {
clickedPosts: function(data) {
this.sendAction('postsAction', data);
}
}
});

View File

@ -3,7 +3,10 @@ import StringBuffer from 'discourse/mixins/string-buffer';
export default Ember.Component.extend(StringBuffer, {
tagName: 'tr',
rerenderTriggers: ['order', 'ascending'],
rerenderTriggers: ['order', 'ascending', 'bulkSelectEnabled'],
toggleInTitle: function(){
return !this.get('bulkSelectEnabled') && this.get('canBulkSelect');
}.property('bulkSelectEnabled'),
rawTemplate: 'components/topic-list-header.raw',

View File

@ -3,7 +3,6 @@ import StringBuffer from 'discourse/mixins/string-buffer';
export default Ember.Component.extend(StringBuffer, {
classNames: ['topic-statuses'],
hasDisplayableStatus: Em.computed.or('topic.archived','topic.closed', 'topic.pinned', 'topic.unpinned', 'topic.invisible', 'topic.archetypeObject.notDefault', 'topic.is_warning'),
rerenderTriggers: ['topic.archived', 'topic.closed', 'topic.pinned', 'topic.visible', 'topic.unpinned', 'topic.is_warning'],
click: function() {
@ -24,7 +23,6 @@ export default Ember.Component.extend(StringBuffer, {
}.property('disableActions'),
renderString: function(buffer) {
if (!this.get('hasDisplayableStatus')) { return; }
var self = this;
@ -37,9 +35,6 @@ export default Ember.Component.extend(StringBuffer, {
buffer.push("<" + startTag + " title='" + title + "' class='topic-status'><i class='fa fa-" + name + "'></i></" + endTag + ">");
};
// Allow a plugin to add a custom icon to a topic
this.trigger('addCustomIcon', buffer);
renderIconIf('topic.is_warning', 'envelope', 'warning');
renderIconIf('topic.closed', 'lock', 'locked');
renderIconIf('topic.archived', 'lock', 'archived');

View File

@ -6,6 +6,10 @@ var controllerOpts = {
bulkSelectEnabled: false,
selected: [],
period: null,
showPosters: true,
canStar: Em.computed.alias('controllers.discovery/topics.currentUser.id'),
showTopicPostBadges: Em.computed.not('controllers.discovery/topics.new'),
redirectedReason: Em.computed.alias('currentUser.redirected_to_top_reason'),

View File

@ -330,7 +330,7 @@ Discourse.Topic = Discourse.Model.extend({
}.property('excerpt'),
readLastPost: Discourse.computed.propertyEqual('last_read_post_number', 'highest_post_number'),
canCleanPin: Em.computed.and('pinned', 'readLastPost')
canClearPin: Em.computed.and('pinned', 'readLastPost')
});

View File

@ -17,36 +17,7 @@
</thead>
<tbody>
{{#each t in topics}}
<tr {{bind-attr class="t.archived"}}>
<td class='main-link'>
{{topic-status topic=t}}
<a class='title' href="{{unbound t.lastUnreadUrl}}">{{{unbound t.fancy_title}}}</a>
{{topic-post-badges unread=t.unread
newPosts=t.new_posts
unseen=t.unseen
url=t.lastUnreadUrl}}
</td>
{{raw "list/category-column" hideCategory=controller.hideCategory category=t.category}}
{{posts-count-column topic=t class="num" action="clickedPosts"}}
{{#if controller.showParticipants}}
<td class='participants'>
{{#each p in t.participants}}
<a href="{{unbound p.user.path}}" data-user-card="{{unbound p.user.username}}" class="{{unbound p.extras}}">{{avatar p usernamePath="user.username" imageSize="small"}}</a>
{{/each}}
</td>
{{/if}}
<td {{bind-attr class=":num :views t.viewsHeat"}}>
{{number t.views numberKey="views_long"}}
</td>
{{raw "list/activity-column" topic=t class="num" tagName="td"}}
</tr>
{{/each}}
{{each t in topics itemViewClass='topic-list-item'}}
</tbody>
</table>

View File

@ -1,4 +1,8 @@
<th data-sort-order='{{order}}' class='{{view.className}}'>{{view.localizedName}}
<th data-sort-order='{{order}}' class='{{view.className}}'>
{{~#if showBulkToggle}}
<button class='btn bulk-select' title='{{i18n "topics.bulk.toggle"}}'><i class='fa fa-list'></i></button>
{{/if ~}}
{{view.localizedName}}
{{~#if view.isSorting}}
<i class='{{view.sortClass}}'></i>
{{/if ~}}

View File

@ -1,11 +1,9 @@
{{#if currentUser}}
<th class='star'>
{{#if canBulkSelect}}
<button class='btn bulk-select' title='{{i18n "topics.bulk.toggle"}}'><i class='fa fa-list'></i></button>
{{/if}}
</th>
{{#if bulkSelectEnabled}}
<th class='star'>
<button class='btn bulk-select' title='{{i18n "topics.bulk.toggle"}}'><i class='fa fa-list'></i></button>
</th>
{{/if}}
{{raw "components/topic-list-header-column" order='default' name='topic.title'}}
{{raw "components/topic-list-header-column" order='default' name='topic.title' showBulkToggle=toggleInTitle}}
{{#unless hideCategory}}
{{raw "components/topic-list-header-column" sortable='true' order='category' name='category_title'}}
{{/unless}}

View File

@ -37,10 +37,10 @@
{{#if hasTopics}}
<table class='topic-list'>
<thead>
{{topic-list-header currentUser=currentUser canBulkSelect=canBulkSelect changeSort="changeSort" toggleBulkSelect="toggleBulkSelect" hideCategory=hideCategory order=order ascending=ascending}}
{{topic-list-header currentUser=currentUser canBulkSelect=canBulkSelect changeSort="changeSort" toggleBulkSelect="toggleBulkSelect" hideCategory=hideCategory order=order ascending=ascending bulkSelectEnabled=bulkSelectEnabled}}
</thead>
<tbody>
{{each content in topics itemController="topic-list-item" itemView="topic-list-item"}}
{{each content in topics itemView="topic-list-item"}}
</tbody>
</table>
{{/if}}

View File

@ -1,3 +1 @@
{{#unless hideCategory}}
<td class='category'>{{category-link category showParent="true"}}</td>
{{/unless}}

View File

@ -0,0 +1,3 @@
<{{view.tagName}} class='num posts-map posts {{view.likesHeat}}' title='{{view.title}}'>
<a href class='posts-map badge-posts'>{{topic.posts_count}}</a>
</{{view.tagName}}>

View File

@ -1,29 +0,0 @@
{{#if bulkSelectEnabled}}
<td class='star'>
{{input type="checkbox" checked=checked}}
</td>
{{else}}
{{#if canStar}}
<td class='star'>
<a {{bind-attr class=":star :fa :fa-star starred:starred"}} {{action "toggleStar"}} href='#' {{bind-attr title="starTooltip"}}></a>
</td>
{{/if}}
{{/if}}
<td class='main-link clearfix' colspan="{{unbound titleColSpan}}">
{{topic-status topic=this.model}}
{{topic-link this}}
{{#if showTopicPostBadges}}
{{topic-post-badges unread=unread newPosts=displayNewPosts unseen=unseen url=lastUnreadUrl}}
{{/if}}
{{raw "list/topic-excerpt" topic=model}}
</td>
{{raw "list/category-column" hideCategory=hideCategory category=category}}
{{raw "list/posters-column" posters=posters}}
{{posts-count-column topic=model class="num" action="showTopicEntrance"}}
<td class="num views {{unbound viewsHeat}}">{{number views numberKey="views_long"}}</td>
{{raw "list/activity-column" topic=model class="num" tagName="td"}}

View File

@ -0,0 +1,33 @@
{{#if controller.bulkSelectEnabled}}
<td class='star'>
<input type="checkbox" class="bulk-select">
</td>
{{/if}}
<td class='main-link clearfix' colspan="{{titleColSpan}}">
{{raw "topic-status" topic=content}}
{{topic-link content}}
{{#if controller.showTopicPostBadges}}
{{raw "topic-post-badges" unread=content.unread newPosts=content.displayNewPosts unseen=content.unseen url=content.lastUnreadUrl}}
{{/if}}
{{raw "list/topic-excerpt" topic=content}}
</td>
{{#unless controller.hideCategory}}
{{#unless content.isPinnedUncategorized}}
{{raw "list/category-column" category=content.category}}
{{/unless}}
{{/unless}}
{{#if controller.showPosters}}
{{raw "list/posters-column" posters=content.posters}}
{{/if}}
{{#if controller.showParticipants}}
{{raw "list/posters-column" posters=content.participants}}
{{/if}}
{{raw "list/posts-count-column" topic=content}}
<td class="num views {{content.viewsHeat}}">{{number content.views numberKey="views_long"}}</td>
{{raw "list/activity-column" topic=content class="num" tagName="td"}}

View File

@ -27,7 +27,7 @@
</div>
<div class="topic-item-stats clearfix">
<div class="pull-right">
{{posts-count-column topic=t tagName="div" class="num posts" action="clickedPosts"}}
{{raw "list/posts-count-column" topic=t tagName="div"}}
{{raw "list/activity-column" topic=t tagName="div" class="num activity last"}}
</div>
{{#unless controller.hideCategory}}

View File

@ -28,7 +28,7 @@
{{/unless}}
<div class="pull-right">
{{posts-count-column topic=this tagName="div" class="num posts" action="showTopicEntrance"}}
{{raw "list/posts-count-column" topic=this tagName="div"}}
<div class='num activity last'>
<a href="{{unbound lastPostUrl}}" title='{{i18n 'last_post'}}: {{{raw-date bumped_at}}}'>{{last_poster_username}}</a>
{{raw "list/activity-column" topic=this tagName="span" class="age"}}

View File

@ -0,0 +1,11 @@
<span class='topic-post-badges'>
{{#if unread ~}}
<a href='{{url}}' class='badge badge-notification unread' title='{{view.unreadTitle}}'>{{unread}}</a>
{{/if }}
{{#if newPosts ~}}
<a href='{{url}}' class='badge badge-notification new-posts' title='{{view.newTitle}}'>{{newPosts}}</a>
{{/if}}
{{#if unseen ~}}
<a href='{{url}}' class='badge badge-notification new-topic' title='{{view.unseenTitle}}'>{{i18n 'filters.new.lower_title'}}</a>
{{/if}}
</span>

View File

@ -0,0 +1,9 @@
{{~#if view.renderDiv ~}}
<div class='topic-statuses'>
{{/if ~}}
{{~#each view.statuses ~}}
<{{openTag}} title='{{title}}' class='topic-status'><i class='fa fa-{{icon}}'></i></{{closeTag}}>
{{~/each}}
{{~#if view.renderDiv ~}}
</div>
{{/if ~}}

View File

@ -1,8 +1,5 @@
export default Ember.Component.extend({
tagName: 'td',
classNameBindings: [':posts', 'likesHeat'],
attributeBindings: ['title'],
export default Ember.Object.extend({
tagName: "td",
ratio: function() {
var likes = parseFloat(this.get('topic.like_count')),
posts = parseFloat(this.get('topic.posts_count'));
@ -10,44 +7,25 @@ export default Ember.Component.extend({
if (posts < 10) { return 0; }
return (likes || 0) / posts;
}.property('topic.like_count', 'topic.posts_count'),
}.property(),
title: function() {
return I18n.messageFormat('posts_likes_MF', {
count: this.get('topic.posts_count'),
ratio: this.get('ratioText')
}).trim();
}.property('topic.posts_count', 'likesHeat'),
}.property(),
ratioText: function() {
var ratio = this.get('ratio');
var settings = this.siteSettings;
var settings = Discourse.SiteSettings;
if (ratio > settings.topic_post_like_heat_high) { return 'high'; }
if (ratio > settings.topic_post_like_heat_medium) { return 'med'; }
if (ratio > settings.topic_post_like_heat_low) { return 'low'; }
return '';
}.property('ratio'),
}.property(),
likesHeat: Discourse.computed.fmt('ratioText', 'heatmap-%@'),
render: function(buffer) {
var postsCount = this.get('topic.posts_count');
buffer.push("<a href class='badge-posts " + this.get('likesHeat') + "'>");
buffer.push(Discourse.Formatter.number(postsCount));
buffer.push("</a>");
},
click: function() {
var topic = this.get('topic');
this.sendAction('action', {
topic: topic,
position: this.$('a').offset()
});
return false;
}
});

View File

@ -1,9 +1,28 @@
export default Discourse.GroupedView.extend({
import StringBuffer from 'discourse/mixins/string-buffer';
export default Discourse.View.extend(StringBuffer, {
rerenderTriggers: ['controller.bulkSelectEnabled'],
tagName: 'tr',
templateName: 'list/topic_list_item',
rawTemplate: 'list/topic_list_item.raw',
classNameBindings: ['controller.checked', 'content.archived', ':topic-list-item', 'content.hasExcerpt:has-excerpt'],
attributeBindings: ['data-topic-id'],
'data-topic-id': Em.computed.alias('content.id'),
titleColSpan: function(){
return (!this.get('controller.hideCategory') &&
this.get('content.isPinnedUncategorized') ? 2 : 1);
}.property(),
click: function(e){
var target = $(e.target);
if(target.hasClass('posts-map')){
if(target.prop('tagName') !== 'A'){
target = target.find('a');
}
this.container.lookup('controller:application').send("showTopicEntrance", {topic: this.get('content'), position: target.offset()});
return false;
}
},
highlight: function() {
var $topic = this.$();

View File

@ -0,0 +1,50 @@
export default Ember.Object.extend({
renderDiv: function(){
return this.get('statuses').length > 0 && !this.noDiv;
}.property(),
statuses: function(){
var topic = this.get("topic");
var results = [];
var self = this;
// TODO, custom statuses? via override?
if(topic.get('is_warning')){
results.push({icon: 'envelope', key: 'warning'});
}
if(topic.get('closed')){
results.push({icon: 'lock', key: 'locked'});
}
if(topic.get('archived')){
results.push({icon: 'lock', key: 'archived'});
}
if(topic.get('pinned')){
results.push({icon: 'thumb-tack', key: 'pinned'});
}
if(topic.get('unpinnned')){
results.push({icon: 'thumb-tack unpinned', key: 'unpinned'});
}
if(topic.get('invisible')){
results.push({icon: 'eye-slash', key: 'invisible'});
}
_.each(results, function(result){
result.title = I18n.t("topic_statuses." + result.key + ".help");
if(!self.disableActions && (result.key === "pinned" ||result.key === "unpinned")){
result.openTag = 'a href';
result.closeTag = 'a';
} else {
result.openTag = 'span';
result.closeTag = 'span';
}
});
return results;
}.property()
});