diff --git a/app/assets/javascripts/discourse/controllers/discovery/categories.js.es6 b/app/assets/javascripts/discourse/controllers/discovery/categories.js.es6
index 83b493076..9f9b26876 100644
--- a/app/assets/javascripts/discourse/controllers/discovery/categories.js.es6
+++ b/app/assets/javascripts/discourse/controllers/discovery/categories.js.es6
@@ -1,3 +1,4 @@
+import computed from 'ember-addons/ember-computed-decorators';
import DiscoveryController from 'discourse/controllers/discovery';
export default DiscoveryController.extend({
@@ -9,36 +10,14 @@ export default DiscoveryController.extend({
// this makes sure the composer isn't scoping to a specific category
category: null,
- actions: {
-
- refresh() {
- // Don't refresh if we're still loading
- if (this.get('controllers.discovery.loading')) { return; }
-
- // If we `send('loading')` here, due to returning true it bubbles up to the
- // router and ember throws an error due to missing `handlerInfos`.
- // Lesson learned: Don't call `loading` yourself.
- this.set('controllers.discovery.loading', true);
-
- const CategoryList = require('discourse/models/category-list').default;
- const parentCategory = this.get('model.parentCategory');
- const promise = parentCategory ? CategoryList.listForParent(this.store, parentCategory) :
- CategoryList.list(this.store);
-
- const self = this;
- promise.then(function(list) {
- self.set('model', list);
- self.send('loadingComplete');
- });
- }
+ @computed
+ canEdit() {
+ return Discourse.User.currentProp('staff');
},
- canEdit: function() {
- return Discourse.User.currentProp('staff');
- }.property(),
-
- latestTopicOnly: function() {
- return this.get('model.categories').find(c => c.get('featuredTopics.length') > 1) === undefined;
- }.property('model.categories.@each.featuredTopics.length')
+ @computed("model.categories.@each.featuredTopics.length")
+ latestTopicOnly() {
+ return this.get("model.categories").find(c => c.get('featuredTopics.length') > 1) === undefined;
+ }
});
diff --git a/app/assets/javascripts/discourse/lib/url.js.es6 b/app/assets/javascripts/discourse/lib/url.js.es6
index 4b72cc26e..a645022f1 100644
--- a/app/assets/javascripts/discourse/lib/url.js.es6
+++ b/app/assets/javascripts/discourse/lib/url.js.es6
@@ -154,15 +154,15 @@ const DiscourseURL = Ember.Object.extend({
// Schedule a DOM cleanup event
Em.run.scheduleOnce('afterRender', Discourse.Route, 'cleanDOM');
- // TODO: Extract into rules we can inject into the URL handler
- if (this.navigatedToHome(oldPath, path, opts)) { return; }
-
if (oldPath === path) {
// If navigating to the same path send an app event. Views can watch it
// and tell their controllers to refresh
this.appEvents.trigger('url:refresh');
}
+ // TODO: Extract into rules we can inject into the URL handler
+ if (this.navigatedToHome(oldPath, path, opts)) { return; }
+
return this.handleURL(path, opts);
},
diff --git a/app/assets/javascripts/discourse/models/topic.js.es6 b/app/assets/javascripts/discourse/models/topic.js.es6
index a6184e368..712a1b369 100644
--- a/app/assets/javascripts/discourse/models/topic.js.es6
+++ b/app/assets/javascripts/discourse/models/topic.js.es6
@@ -71,11 +71,6 @@ const Topic = RestModel.extend({
I18n.t('last_post') + ": " + longDate(this.get('bumpedAt'));
}.property('bumpedAt'),
- @computed('replyCount')
- replyTitle(count) {
- return I18n.t("posts_likes", { count });
- },
-
createdAt: function() {
return new Date(this.get('created_at'));
}.property('created_at'),
diff --git a/app/assets/javascripts/discourse/routes/discovery-categories.js.es6 b/app/assets/javascripts/discourse/routes/discovery-categories.js.es6
index d33919cbb..37be18bc3 100644
--- a/app/assets/javascripts/discourse/routes/discovery-categories.js.es6
+++ b/app/assets/javascripts/discourse/routes/discovery-categories.js.es6
@@ -31,7 +31,11 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
},
setupController(controller, model) {
- TopicList.find("latest").then(result => model.set("topicList", result));
+ model.set("loadingTopics", true);
+
+ TopicList.find("latest")
+ .then(result => model.set("topicList", result))
+ .finally(() => model.set("loadingTopics", false));
controller.set("model", model);
@@ -44,6 +48,28 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
},
actions: {
+
+ refresh() {
+ const controller = this.controllerFor("discovery/categories");
+
+ // Don't refresh if we're still loading
+ if (!controller || controller.get("loading")) { return; }
+
+ // If we `send('loading')` here, due to returning true it bubbles up to the
+ // router and ember throws an error due to missing `handlerInfos`.
+ // Lesson learned: Don't call `loading` yourself.
+ controller.set("loading", true);
+
+ const parentCategory = this.get("model.parentCategory");
+ const promise = parentCategory ? CategoryList.listForParent(this.store, parentCategory) :
+ CategoryList.list(this.store);
+
+ promise.then(list => {
+ this.setupController(controller, list);
+ controller.send("loadingComplete");
+ });
+ },
+
createCategory() {
const groups = this.site.groups,
everyoneName = groups.findBy("id", 0).name;
diff --git a/app/assets/javascripts/discourse/templates/discovery/categories.hbs b/app/assets/javascripts/discourse/templates/discovery/categories.hbs
index 00dcd4973..60297813e 100644
--- a/app/assets/javascripts/discourse/templates/discovery/categories.hbs
+++ b/app/assets/javascripts/discourse/templates/discovery/categories.hbs
@@ -47,50 +47,61 @@
- {{#each model.topicList.topics as |t|}}
-
-
-
-
-
- {{#with t.posters.lastObject.user as |lastPoster|}}
- {{#user-link user=lastPoster}}
- {{avatar lastPoster imageSize="large"}}
- {{/user-link}}
- {{/with}}
- |
-
- |
- {{topic-status topic=t}}
- {{topic-link t}}
- {{#if t.unseen}}
-
- {{/if}}
-
-
- {{category-link t.category}}
- {{#if t.tags}}
- {{#each t.visibleListTags as |tag|}}
- {{discourse-tag tag}}
- {{/each}}
- {{/if}}
-
-
-
-
-
- |
+ {{#if model.loadingTopics}}
+ {{loading-spinner}}
+ {{else}}
+ {{#if model.topicList.topics}}
+ {{#each model.topicList.topics as |t|}}
+
+
+
+
+
+ {{#with t.posters.firstObject.user as |originalPoster|}}
+ {{#user-link user=originalPoster}}
+ {{avatar originalPoster imageSize="large"}}
+ {{/user-link}}
+ {{/with}}
+ |
+
+ |
+ {{topic-status topic=t}}
+ {{topic-link t}}
+ {{topic-post-badges newPosts=t.totalUnread unseen=t.unseen url=t.lastUnreadUrl}}
+
+
+ {{category-link t.category}}
+ {{#if t.tags}}
+ {{#each t.visibleListTags as |tag|}}
+ {{discourse-tag tag}}
+ {{/each}}
+ {{/if}}
+
+
+
+ {{raw "list/posts-count-column" topic=t tagName="div"}}
+
+ |
+
+
+
-
-
-
- {{else}}
- {{loading-spinner}}
- {{/each}}
+ {{/each}}
+
+
+ {{i18n "more"}}
+ |
+
+ {{else}}
+
+
+ {{i18n "topics.none.latest"}}
+ |
+
+ {{/if}}
+ {{/if}}
diff --git a/app/assets/javascripts/discourse/templates/list/posts-count-column.raw.hbs b/app/assets/javascripts/discourse/templates/list/posts-count-column.raw.hbs
index 052bb4777..599d695ab 100644
--- a/app/assets/javascripts/discourse/templates/list/posts-count-column.raw.hbs
+++ b/app/assets/javascripts/discourse/templates/list/posts-count-column.raw.hbs
@@ -1,3 +1,3 @@
<{{view.tagName}} class='num posts-map posts {{view.likesHeat}}' title='{{view.title}}'>
- {{number topic.replyCount}}
+ {{number topic.replyCount noTitle="true"}}
{{view.tagName}}>
diff --git a/app/assets/javascripts/discourse/views/list/posts-count-column.js.es6 b/app/assets/javascripts/discourse/views/list/posts-count-column.js.es6
index d60263667..e61e1b9c0 100644
--- a/app/assets/javascripts/discourse/views/list/posts-count-column.js.es6
+++ b/app/assets/javascripts/discourse/views/list/posts-count-column.js.es6
@@ -1,32 +1,32 @@
+import computed from 'ember-addons/ember-computed-decorators';
import { fmt } from 'discourse/lib/computed';
export default Ember.Object.extend({
tagName: "td",
- ratio: function() {
- var likes = parseFloat(this.get('topic.like_count')),
- posts = parseFloat(this.get('topic.posts_count'));
+
+ @computed("topic.like_count", "topic.posts_count")
+ ratio(likeCount, postCount) {
+ const likes = parseFloat(likeCount);
+ const posts = parseFloat(postCount);
if (posts < 10) { return 0; }
return (likes || 0) / posts;
- }.property(),
+ },
- title: function() {
- return I18n.messageFormat('posts_likes_MF', {
- count: this.get('topic.replyCount'),
- ratio: this.get('ratioText')
- }).trim();
- }.property(),
+ @computed("topic.replyCount", "ratioText")
+ title(count, ratio) {
+ return I18n.messageFormat('posts_likes_MF', { count, ratio }).trim();
+ },
- ratioText: function() {
- var ratio = this.get('ratio');
-
- var settings = Discourse.SiteSettings;
- if (ratio > settings.topic_post_like_heat_high) { return 'high'; }
+ @computed("ratio")
+ ratioText(ratio) {
+ const settings = this.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'; }
+ if (ratio > settings.topic_post_like_heat_low) { return 'low'; }
return '';
- }.property(),
+ },
likesHeat: fmt('ratioText', 'heatmap-%@'),
});
diff --git a/app/assets/stylesheets/common/base/_topic-list.scss b/app/assets/stylesheets/common/base/_topic-list.scss
index 20d6a8d16..0dec7467d 100644
--- a/app/assets/stylesheets/common/base/_topic-list.scss
+++ b/app/assets/stylesheets/common/base/_topic-list.scss
@@ -124,12 +124,24 @@ html.anon .topic-list a.title:visited:not(.badge-notification) {color: dark-ligh
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
}
}
- .topic-replies {
- font-weight: bold;
+ .num.posts {
+ text-align: right;
+ a {
+ padding: 0;
+ }
+ }
+ .posts-map.posts {
margin-bottom: 10px;
+ width: 100%;
+ .badge-posts {
+ font-weight: bold;
+ }
}
.topic-list-latest {
margin-left: 4%;
+ .new-posts {
+ margin-left: 5px;
+ }
}
.topic-list.categories {
th.stats {
@@ -138,6 +150,16 @@ html.anon .topic-list a.title:visited:not(.badge-notification) {color: dark-ligh
.stats {
vertical-align: top;
text-align: center;
+ .value {
+ font-size: 1.2em;
+ }
+ }
+ }
+ .no-topics, .more-topics {
+ border-bottom: none;
+ td {
+ padding-right: 0 !important;
+ color: $primary;
}
}
}
diff --git a/config/locales/client.en.yml b/config/locales/client.en.yml
index 32904cd8c..dfbf39005 100644
--- a/config/locales/client.en.yml
+++ b/config/locales/client.en.yml
@@ -1936,10 +1936,6 @@ en:
posts: "Posts"
posts_long: "there are {{number}} posts in this topic"
- posts_likes:
- one: "This topic has 1 reply."
- other: "This topic has {{count}} replies."
-
# keys ending with _MF use message format, see https://meta.discourse.org/t/message-format-support-for-localization/7035 for details
posts_likes_MF: |
This topic has {count, plural, one {1 reply} other {# replies}} {ratio, select,