mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-30 10:58:31 -05:00
FIX: /categories page issues
FIX: endless spinner when /categories is set to homepage and you click the home logo FIX: latest column should respect topic state for the current user (new, unread, etc.) FIX: post count should have heat colors applied based on like ratios FIX: Add "More" button at the bottom of the latest column UX: The topic count number in the categories panel should be slightly larger
This commit is contained in:
parent
78e8aa823d
commit
96b6d342cc
9 changed files with 134 additions and 105 deletions
|
@ -1,3 +1,4 @@
|
||||||
|
import computed from 'ember-addons/ember-computed-decorators';
|
||||||
import DiscoveryController from 'discourse/controllers/discovery';
|
import DiscoveryController from 'discourse/controllers/discovery';
|
||||||
|
|
||||||
export default DiscoveryController.extend({
|
export default DiscoveryController.extend({
|
||||||
|
@ -9,36 +10,14 @@ export default DiscoveryController.extend({
|
||||||
// this makes sure the composer isn't scoping to a specific category
|
// this makes sure the composer isn't scoping to a specific category
|
||||||
category: null,
|
category: null,
|
||||||
|
|
||||||
actions: {
|
@computed
|
||||||
|
canEdit() {
|
||||||
refresh() {
|
return Discourse.User.currentProp('staff');
|
||||||
// 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');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
canEdit: function() {
|
@computed("model.categories.@each.featuredTopics.length")
|
||||||
return Discourse.User.currentProp('staff');
|
latestTopicOnly() {
|
||||||
}.property(),
|
return this.get("model.categories").find(c => c.get('featuredTopics.length') > 1) === undefined;
|
||||||
|
}
|
||||||
latestTopicOnly: function() {
|
|
||||||
return this.get('model.categories').find(c => c.get('featuredTopics.length') > 1) === undefined;
|
|
||||||
}.property('model.categories.@each.featuredTopics.length')
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -154,15 +154,15 @@ const DiscourseURL = Ember.Object.extend({
|
||||||
// Schedule a DOM cleanup event
|
// Schedule a DOM cleanup event
|
||||||
Em.run.scheduleOnce('afterRender', Discourse.Route, 'cleanDOM');
|
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 (oldPath === path) {
|
||||||
// If navigating to the same path send an app event. Views can watch it
|
// If navigating to the same path send an app event. Views can watch it
|
||||||
// and tell their controllers to refresh
|
// and tell their controllers to refresh
|
||||||
this.appEvents.trigger('url: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);
|
return this.handleURL(path, opts);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
|
@ -71,11 +71,6 @@ const Topic = RestModel.extend({
|
||||||
I18n.t('last_post') + ": " + longDate(this.get('bumpedAt'));
|
I18n.t('last_post') + ": " + longDate(this.get('bumpedAt'));
|
||||||
}.property('bumpedAt'),
|
}.property('bumpedAt'),
|
||||||
|
|
||||||
@computed('replyCount')
|
|
||||||
replyTitle(count) {
|
|
||||||
return I18n.t("posts_likes", { count });
|
|
||||||
},
|
|
||||||
|
|
||||||
createdAt: function() {
|
createdAt: function() {
|
||||||
return new Date(this.get('created_at'));
|
return new Date(this.get('created_at'));
|
||||||
}.property('created_at'),
|
}.property('created_at'),
|
||||||
|
|
|
@ -31,7 +31,11 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
|
||||||
},
|
},
|
||||||
|
|
||||||
setupController(controller, model) {
|
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);
|
controller.set("model", model);
|
||||||
|
|
||||||
|
@ -44,6 +48,28 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
|
||||||
},
|
},
|
||||||
|
|
||||||
actions: {
|
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() {
|
createCategory() {
|
||||||
const groups = this.site.groups,
|
const groups = this.site.groups,
|
||||||
everyoneName = groups.findBy("id", 0).name;
|
everyoneName = groups.findBy("id", 0).name;
|
||||||
|
|
|
@ -47,50 +47,61 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{#each model.topicList.topics as |t|}}
|
{{#if model.loadingTopics}}
|
||||||
<tr>
|
{{loading-spinner}}
|
||||||
<table>
|
{{else}}
|
||||||
<tbody>
|
{{#if model.topicList.topics}}
|
||||||
<tr class="{{if t.archived 'archived'}}" data-topic-id={{unbound t.id}}>
|
{{#each model.topicList.topics as |t|}}
|
||||||
<td class="topic-poster">
|
<tr>
|
||||||
{{#with t.posters.lastObject.user as |lastPoster|}}
|
<table>
|
||||||
{{#user-link user=lastPoster}}
|
<tbody>
|
||||||
{{avatar lastPoster imageSize="large"}}
|
<tr class="{{if t.archived 'archived'}}" data-topic-id={{unbound t.id}}>
|
||||||
{{/user-link}}
|
<td class="topic-poster">
|
||||||
{{/with}}
|
{{#with t.posters.firstObject.user as |originalPoster|}}
|
||||||
</td>
|
{{#user-link user=originalPoster}}
|
||||||
<td class="main-link">
|
{{avatar originalPoster imageSize="large"}}
|
||||||
<tr>
|
{{/user-link}}
|
||||||
{{topic-status topic=t}}
|
{{/with}}
|
||||||
{{topic-link t}}
|
</td>
|
||||||
{{#if t.unseen}}
|
<td class="main-link">
|
||||||
<span class="badge-notification new-topic"></span>
|
<tr>
|
||||||
{{/if}}
|
{{topic-status topic=t}}
|
||||||
</tr>
|
{{topic-link t}}
|
||||||
<tr>
|
{{topic-post-badges newPosts=t.totalUnread unseen=t.unseen url=t.lastUnreadUrl}}
|
||||||
{{category-link t.category}}
|
</tr>
|
||||||
{{#if t.tags}}
|
<tr>
|
||||||
{{#each t.visibleListTags as |tag|}}
|
{{category-link t.category}}
|
||||||
{{discourse-tag tag}}
|
{{#if t.tags}}
|
||||||
{{/each}}
|
{{#each t.visibleListTags as |tag|}}
|
||||||
{{/if}}
|
{{discourse-tag tag}}
|
||||||
</tr>
|
{{/each}}
|
||||||
</td>
|
{{/if}}
|
||||||
<td class="topic-stats">
|
</tr>
|
||||||
<div class="topic-replies">
|
</td>
|
||||||
<a href="{{t.lastPostUrl}}" title="{{t.replyTitle}}">{{number t.replyCount noTitle="true"}}</a>
|
<td class="topic-stats">
|
||||||
</div>
|
{{raw "list/posts-count-column" topic=t tagName="div"}}
|
||||||
<div class="topic-last-activity">
|
<div class="topic-last-activity">
|
||||||
<a href="{{t.lastPostUrl}}" title="{{t.bumpedAtTitle}}">{{format-date t.bumpedAt format="tiny" noTitle="true"}}</a>
|
<a href="{{t.lastPostUrl}}" title="{{t.bumpedAtTitle}}">{{format-date t.bumpedAt format="tiny" noTitle="true"}}</a>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
{{/each}}
|
||||||
</table>
|
<tr class="more-topics">
|
||||||
</tr>
|
<td>
|
||||||
{{else}}
|
<a href="/latest" class="btn pull-right">{{i18n "more"}}</a>
|
||||||
{{loading-spinner}}
|
</td>
|
||||||
{{/each}}
|
</tr>
|
||||||
|
{{else}}
|
||||||
|
<tr class="no-topics">
|
||||||
|
<td>
|
||||||
|
<h3>{{i18n "topics.none.latest"}}</h3>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
|
|
|
@ -1,3 +1,3 @@
|
||||||
<{{view.tagName}} class='num posts-map posts {{view.likesHeat}}' title='{{view.title}}'>
|
<{{view.tagName}} class='num posts-map posts {{view.likesHeat}}' title='{{view.title}}'>
|
||||||
<a href class='posts-map badge-posts {{view.likesHeat}}'>{{number topic.replyCount}}</a>
|
<a href class='posts-map badge-posts {{view.likesHeat}}'>{{number topic.replyCount noTitle="true"}}</a>
|
||||||
</{{view.tagName}}>
|
</{{view.tagName}}>
|
||||||
|
|
|
@ -1,32 +1,32 @@
|
||||||
|
import computed from 'ember-addons/ember-computed-decorators';
|
||||||
import { fmt } from 'discourse/lib/computed';
|
import { fmt } from 'discourse/lib/computed';
|
||||||
|
|
||||||
export default Ember.Object.extend({
|
export default Ember.Object.extend({
|
||||||
tagName: "td",
|
tagName: "td",
|
||||||
ratio: function() {
|
|
||||||
var likes = parseFloat(this.get('topic.like_count')),
|
@computed("topic.like_count", "topic.posts_count")
|
||||||
posts = parseFloat(this.get('topic.posts_count'));
|
ratio(likeCount, postCount) {
|
||||||
|
const likes = parseFloat(likeCount);
|
||||||
|
const posts = parseFloat(postCount);
|
||||||
|
|
||||||
if (posts < 10) { return 0; }
|
if (posts < 10) { return 0; }
|
||||||
|
|
||||||
return (likes || 0) / posts;
|
return (likes || 0) / posts;
|
||||||
}.property(),
|
},
|
||||||
|
|
||||||
title: function() {
|
@computed("topic.replyCount", "ratioText")
|
||||||
return I18n.messageFormat('posts_likes_MF', {
|
title(count, ratio) {
|
||||||
count: this.get('topic.replyCount'),
|
return I18n.messageFormat('posts_likes_MF', { count, ratio }).trim();
|
||||||
ratio: this.get('ratioText')
|
},
|
||||||
}).trim();
|
|
||||||
}.property(),
|
|
||||||
|
|
||||||
ratioText: function() {
|
@computed("ratio")
|
||||||
var ratio = this.get('ratio');
|
ratioText(ratio) {
|
||||||
|
const settings = this.siteSettings;
|
||||||
var settings = Discourse.SiteSettings;
|
if (ratio > settings.topic_post_like_heat_high) { return 'high'; }
|
||||||
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_medium) { return 'med'; }
|
||||||
if (ratio > settings.topic_post_like_heat_low) { return 'low'; }
|
if (ratio > settings.topic_post_like_heat_low) { return 'low'; }
|
||||||
return '';
|
return '';
|
||||||
}.property(),
|
},
|
||||||
|
|
||||||
likesHeat: fmt('ratioText', 'heatmap-%@'),
|
likesHeat: fmt('ratioText', 'heatmap-%@'),
|
||||||
});
|
});
|
||||||
|
|
|
@ -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%));
|
color: dark-light-choose(scale-color($primary, $lightness: 50%), scale-color($secondary, $lightness: 40%));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.topic-replies {
|
.num.posts {
|
||||||
font-weight: bold;
|
text-align: right;
|
||||||
|
a {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.posts-map.posts {
|
||||||
margin-bottom: 10px;
|
margin-bottom: 10px;
|
||||||
|
width: 100%;
|
||||||
|
.badge-posts {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.topic-list-latest {
|
.topic-list-latest {
|
||||||
margin-left: 4%;
|
margin-left: 4%;
|
||||||
|
.new-posts {
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.topic-list.categories {
|
.topic-list.categories {
|
||||||
th.stats {
|
th.stats {
|
||||||
|
@ -138,6 +150,16 @@ html.anon .topic-list a.title:visited:not(.badge-notification) {color: dark-ligh
|
||||||
.stats {
|
.stats {
|
||||||
vertical-align: top;
|
vertical-align: top;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
.value {
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.no-topics, .more-topics {
|
||||||
|
border-bottom: none;
|
||||||
|
td {
|
||||||
|
padding-right: 0 !important;
|
||||||
|
color: $primary;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1936,10 +1936,6 @@ en:
|
||||||
posts: "Posts"
|
posts: "Posts"
|
||||||
posts_long: "there are {{number}} posts in this topic"
|
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
|
# keys ending with _MF use message format, see https://meta.discourse.org/t/message-format-support-for-localization/7035 for details
|
||||||
posts_likes_MF: |
|
posts_likes_MF: |
|
||||||
This topic has {count, plural, one {1 reply} other {# replies}} {ratio, select,
|
This topic has {count, plural, one {1 reply} other {# replies}} {ratio, select,
|
||||||
|
|
Loading…
Reference in a new issue