mirror of
https://github.com/discourse/discourse.git
synced 2024-11-22 12:12:26 +08:00
FEATURE: better top pages
This commit is contained in:
parent
069a42cde1
commit
3a6bffa05d
|
@ -88,9 +88,8 @@ window.Discourse = Ember.Application.createWithMixins(Discourse.Ajax, {
|
|||
},
|
||||
|
||||
loginRequired: function() {
|
||||
return (
|
||||
Discourse.SiteSettings.login_required && !Discourse.User.current()
|
||||
);
|
||||
return Discourse.SiteSettings.login_required &&
|
||||
!Discourse.User.current();
|
||||
}.property(),
|
||||
|
||||
redirectIfLoginRequired: function(route) {
|
||||
|
|
|
@ -22,10 +22,12 @@ Discourse.BasicTopicListComponent = Ember.Component.extend({
|
|||
}.observes('topicList'),
|
||||
|
||||
_initFromTopicList: function(topicList) {
|
||||
this.setProperties({
|
||||
topics: topicList.get('topics'),
|
||||
sortOrder: topicList.get('sortOrder')
|
||||
});
|
||||
if (topicList !== null) {
|
||||
this.setProperties({
|
||||
topics: topicList.get('topics'),
|
||||
sortOrder: topicList.get('sortOrder')
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
init: function() {
|
||||
|
|
|
@ -30,7 +30,7 @@ Discourse.ListCategoriesController = Discourse.ObjectController.extend({
|
|||
|
||||
latestTopicOnly: function() {
|
||||
return this.get('categories').find(function(c) { return c.get('featuredTopics.length') > 1; }) === undefined;
|
||||
}.property('categories.featuredTopics.length')
|
||||
}.property('categories.@each.featuredTopics.length')
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -95,12 +95,12 @@ Discourse.ListController = Discourse.Controller.extend({
|
|||
// Put in the appropriate page title based on our view
|
||||
updateTitle: function() {
|
||||
if (this.get('filterMode') === 'categories') {
|
||||
return Discourse.set('title', I18n.t('categories_list'));
|
||||
Discourse.set('title', I18n.t('categories_list'));
|
||||
} else {
|
||||
if (this.present('category')) {
|
||||
return Discourse.set('title', this.get('category.name').capitalize() + " " + I18n.t('topic.list'));
|
||||
Discourse.set('title', this.get('category.name').capitalize() + " " + I18n.t('topic.list'));
|
||||
} else {
|
||||
return Discourse.set('title', I18n.t('topic.list'));
|
||||
Discourse.set('title', I18n.t('topic.list'));
|
||||
}
|
||||
}
|
||||
}.observes('filterMode', 'category'),
|
||||
|
@ -134,5 +134,5 @@ Discourse.ListController = Discourse.Controller.extend({
|
|||
});
|
||||
|
||||
Discourse.ListController.reopenClass({
|
||||
filters: <%= Discourse.filters.map(&:to_s) %>
|
||||
FILTERS: <%= Discourse.filters.map(&:to_s) %>
|
||||
});
|
||||
|
|
|
@ -23,12 +23,18 @@ Discourse.ListTopController = Discourse.ObjectController.extend({
|
|||
return null;
|
||||
}.property(),
|
||||
|
||||
showThisYear: function() {
|
||||
if (Discourse.User.current()) {
|
||||
return !Discourse.User.currentProp("hasBeenSeenInTheLastMonth");
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}.property()
|
||||
hasDisplayedAllTopLists: Em.computed.and('content.yearly', 'content.monthly', 'content.weekly', 'content.daily'),
|
||||
|
||||
showMoreUrl: function(period) {
|
||||
var url = "", category = this.get("category");
|
||||
if (category) { url += category.get("url") + "/l"; }
|
||||
url += "/top/" + period;
|
||||
return url;
|
||||
},
|
||||
|
||||
showMoreDailyUrl: function() { return this.showMoreUrl("daily"); }.property("category.url"),
|
||||
showMoreWeeklyUrl: function() { return this.showMoreUrl("weekly"); }.property("category.url"),
|
||||
showMoreMonthlyUrl: function() { return this.showMoreUrl("monthly"); }.property("category.url"),
|
||||
showMoreYearlyUrl: function() { return this.showMoreUrl("yearly"); }.property("category.url"),
|
||||
|
||||
});
|
||||
|
|
|
@ -37,12 +37,10 @@ Discourse.StaticController = Discourse.Controller.extend({
|
|||
});
|
||||
|
||||
Discourse.StaticController.reopenClass({
|
||||
pages: ['faq', 'tos', 'privacy', 'login'],
|
||||
configs: {
|
||||
PAGES: ['faq', 'tos', 'privacy', 'login'],
|
||||
CONFIGS: {
|
||||
'faq': 'faq_url',
|
||||
'tos': 'tos_url',
|
||||
'privacy': 'privacy_policy_url'
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -165,7 +165,7 @@ Discourse.URL = Em.Object.createWithMixins({
|
|||
@param {String} path the path we're navigating to
|
||||
**/
|
||||
navigatedToHome: function(oldPath, path) {
|
||||
var defaultFilter = "/" + Discourse.ListController.filters[0];
|
||||
var defaultFilter = "/" + Discourse.ListController.FILTERS[0];
|
||||
|
||||
if (path === "/" && (oldPath === "/" || oldPath === defaultFilter)) {
|
||||
// Refresh our list
|
||||
|
|
|
@ -44,7 +44,7 @@ Discourse.Category = Discourse.Model.extend({
|
|||
}.property('url'),
|
||||
|
||||
style: function() {
|
||||
return "background-color: #" + this.get('category.color') + "; color: #" + (this.get('category.text_color')) + ";";
|
||||
return "background-color: #" + this.get('category.color') + "; color: #" + this.get('category.text_color') + ";";
|
||||
}.property('color', 'text_color'),
|
||||
|
||||
moreTopics: function() {
|
||||
|
@ -54,7 +54,7 @@ Discourse.Category = Discourse.Model.extend({
|
|||
save: function() {
|
||||
var url = "/categories";
|
||||
if (this.get('id')) {
|
||||
url = "/categories/" + (this.get('id'));
|
||||
url = "/categories/" + this.get('id');
|
||||
}
|
||||
|
||||
return Discourse.ajax(url, {
|
||||
|
|
|
@ -16,7 +16,7 @@ Discourse.CategoryList = Ember.ArrayProxy.extend({
|
|||
moveCategory: function(categoryId, position){
|
||||
Discourse.ajax("/category/" + categoryId + "/move", {
|
||||
type: 'POST',
|
||||
data: {position: position}
|
||||
data: { position: position }
|
||||
});
|
||||
}
|
||||
});
|
||||
|
@ -55,31 +55,20 @@ Discourse.CategoryList.reopenClass({
|
|||
return categories;
|
||||
},
|
||||
|
||||
list: function(filter) {
|
||||
var self = this,
|
||||
finder = null;
|
||||
list: function() {
|
||||
var self = this;
|
||||
|
||||
if (filter === 'categories') {
|
||||
finder = PreloadStore.getAndRemove("categories_list", function() {
|
||||
return Discourse.ajax("/categories.json");
|
||||
});
|
||||
} else {
|
||||
finder = Discourse.ajax("/" + filter + ".json");
|
||||
}
|
||||
|
||||
return finder.then(function(result) {
|
||||
var categoryList = Discourse.TopicList.create();
|
||||
categoryList.setProperties({
|
||||
return PreloadStore.getAndRemove("categories_list", function() {
|
||||
return Discourse.ajax("/categories.json");
|
||||
}).then(function(result) {
|
||||
return Discourse.CategoryList.create({
|
||||
categories: self.categoriesFrom(result),
|
||||
can_create_category: result.category_list.can_create_category,
|
||||
can_create_topic: result.category_list.can_create_topic,
|
||||
categories: self.categoriesFrom(result),
|
||||
draft_key: result.category_list.draft_key,
|
||||
draft_sequence: result.category_list.draft_sequence
|
||||
draft_sequence: result.category_list.draft_sequence,
|
||||
});
|
||||
return categoryList;
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
var validNavNames = <%= Discourse.top_menu_items.map(&:to_s) %>;
|
||||
var validAnon = <%= Discourse.anonymous_top_menu_items.map(&:to_s) %>;
|
||||
|
||||
Discourse.NavItem = Discourse.Model.extend({
|
||||
|
||||
|
@ -69,26 +67,25 @@ Discourse.NavItem = Discourse.Model.extend({
|
|||
});
|
||||
|
||||
Discourse.NavItem.reopenClass({
|
||||
NAMES: <%= Discourse.top_menu_items.map(&:to_s) %>,
|
||||
ANONYMOUS_NAMES: <%= Discourse.anonymous_top_menu_items.map(&:to_s) %>,
|
||||
|
||||
// create a nav item from the text, will return null if there is not valid nav item for this particular text
|
||||
fromText: function(text, opts) {
|
||||
var countSummary = opts.countSummary,
|
||||
split = text.split(","),
|
||||
var split = text.split(","),
|
||||
name = split[0],
|
||||
testName = name.split("/")[0];
|
||||
|
||||
if (!opts.loggedOn && !validAnon.contains(testName)) return null;
|
||||
if (!opts.loggedOn && !Discourse.NavItem.ANONYMOUS_NAMES.contains(testName)) return null;
|
||||
if (!Discourse.Category.list() && testName === "categories") return null;
|
||||
if (!validNavNames.contains(testName)) return null;
|
||||
if (!Discourse.NavItem.NAMES.contains(testName)) return null;
|
||||
|
||||
opts = {
|
||||
return Discourse.NavItem.create({
|
||||
name: name,
|
||||
hasIcon: name === "unread" || name === "starred",
|
||||
filters: split.splice(1),
|
||||
category: opts.category
|
||||
};
|
||||
|
||||
return Discourse.NavItem.create(opts);
|
||||
category: opts.category,
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
/**
|
||||
A data model representing a list of top topic lists
|
||||
|
||||
@class TopList
|
||||
@extends Discourse.Model
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
|
||||
Discourse.TopList = Discourse.Model.extend({});
|
||||
|
||||
Discourse.TopList.reopenClass({
|
||||
find: function() {
|
||||
return PreloadStore.getAndRemove("top_list", function() {
|
||||
return Discourse.ajax("/top.json");
|
||||
}).then(function (result) {
|
||||
var topList = Discourse.TopList.create({
|
||||
can_create_topic: result.can_create_topic,
|
||||
yearly: Discourse.TopicList.from(result.yearly),
|
||||
monthly: Discourse.TopicList.from(result.monthly),
|
||||
weekly: Discourse.TopicList.from(result.weekly),
|
||||
daily: Discourse.TopicList.from(result.daily)
|
||||
});
|
||||
// disable sorting
|
||||
topList.setProperties({
|
||||
"yearly.sortOrder": undefined,
|
||||
"monthly.sortOrder": undefined,
|
||||
"weekly.sortOrder": undefined,
|
||||
"daily.sortOrder": undefined
|
||||
});
|
||||
return topList;
|
||||
});
|
||||
}
|
||||
});
|
37
app/assets/javascripts/discourse/models/top_list.js.erb
Normal file
37
app/assets/javascripts/discourse/models/top_list.js.erb
Normal file
|
@ -0,0 +1,37 @@
|
|||
/**
|
||||
A data model representing a list of top topic lists
|
||||
|
||||
@class TopList
|
||||
@extends Discourse.Model
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
|
||||
Discourse.TopList = Discourse.Model.extend({});
|
||||
|
||||
Discourse.TopList.reopenClass({
|
||||
PERIODS: <%= TopTopic.periods.map(&:to_s) %>,
|
||||
|
||||
find: function(period, category) {
|
||||
return PreloadStore.getAndRemove("top_lists", function() {
|
||||
var url = "";
|
||||
if (category) { url += category.get("url") + "/l"; }
|
||||
url += "/top";
|
||||
if (period) { url += "/" + period; }
|
||||
return Discourse.ajax(url + ".json");
|
||||
}).then(function (result) {
|
||||
var topList = Discourse.TopList.create({});
|
||||
|
||||
_.each(Discourse.TopList.PERIODS, function(period) {
|
||||
// if there is a list for that period
|
||||
if (result[period]) {
|
||||
// instanciate a new topic list with no sorting
|
||||
topList.set(period, Discourse.TopicList.from(result[period]));
|
||||
topList.set(period + ".sortOrder", undefined);
|
||||
}
|
||||
});
|
||||
|
||||
return topList;
|
||||
});
|
||||
}
|
||||
});
|
|
@ -65,8 +65,7 @@ Discourse.TopicList = Discourse.Model.extend({
|
|||
params.sort_descending = sortOrder.get('descending');
|
||||
|
||||
this.set('loaded', false);
|
||||
var finder = finderFor(this.get('filter'), params);
|
||||
finder().then(function (result) {
|
||||
finderFor(this.get('filter'), params).then(function (result) {
|
||||
var newTopics = Discourse.TopicList.topicsFrom(result),
|
||||
topics = self.get('topics');
|
||||
|
||||
|
|
|
@ -376,8 +376,6 @@ Discourse.User = Discourse.Model.extend({
|
|||
});
|
||||
|
||||
Discourse.User.reopenClass(Discourse.Singleton, {
|
||||
|
||||
|
||||
/**
|
||||
Find a `Discourse.User` for a given username.
|
||||
|
||||
|
|
|
@ -14,34 +14,48 @@ Discourse.Route.buildRoutes(function() {
|
|||
});
|
||||
|
||||
// Generate static page routes
|
||||
Discourse.StaticController.pages.forEach(function(p) {
|
||||
router.route(p, { path: "/" + p });
|
||||
_.each(Discourse.StaticController.PAGES, function (page) {
|
||||
router.route(page, { path: '/' + page });
|
||||
});
|
||||
|
||||
// List routes
|
||||
this.resource('list', { path: '/' }, function() {
|
||||
this.resource("list", { path: "/" }, function() {
|
||||
router = this;
|
||||
|
||||
// Generate routes for all our filters
|
||||
Discourse.ListController.filters.forEach(function(filter) {
|
||||
router.route(filter, { path: "/" + filter });
|
||||
router.route(filter, { path: "/" + filter + "/more" });
|
||||
router.route(filter + "Category", { path: "/category/:slug/l/" + filter });
|
||||
router.route(filter + "Category", { path: "/category/:slug/l/" + filter + "/more" });
|
||||
router.route(filter + "Category", { path: "/category/:parentSlug/:slug/l/" + filter });
|
||||
router.route(filter + "Category", { path: "/category/:parentSlug/:slug/l/" + filter + "/more" });
|
||||
// categories
|
||||
this.route('categories');
|
||||
|
||||
// top
|
||||
this.route('top');
|
||||
this.route('topCategory', { path: '/category/:slug/l/top' });
|
||||
this.route('topCategoryNone', { path: '/category/:slug/none/l/top' });
|
||||
this.route('topCategory', { path: '/category/:parentSlug/:slug/l/top' });
|
||||
|
||||
// top by periods
|
||||
_.each(Discourse.TopList.PERIODS, function(period) {
|
||||
var top = 'top' + period.capitalize();
|
||||
router.route(top, { path: '/top/' + period });
|
||||
router.route(top, { path: '/top/' + period + '/more' });
|
||||
router.route(top + 'Category', { path: '/category/:slug/l/top/' + period });
|
||||
router.route(top + 'Category', { path: '/category/:slug/l/top/' + period + '/more' });
|
||||
router.route(top + 'CategoryNone', { path: '/category/:slug/none/l/top/' + period });
|
||||
router.route(top + 'CategoryNone', { path: '/category/:slug/none/l/top/' + period + '/more' });
|
||||
router.route(top + 'Category', { path: '/category/:parentSlug/:slug/l/top/' + period });
|
||||
router.route(top + 'Category', { path: '/category/:parentSlug/:slug/l/top/' + period + '/more' });
|
||||
});
|
||||
|
||||
// homepage
|
||||
var homepage = Discourse.User.current() ?
|
||||
Discourse.User.currentProp("homepage") :
|
||||
Discourse.Utilities.defaultHomepage();
|
||||
this.route(homepage, { path: '/' });
|
||||
// filters
|
||||
_.each(Discourse.ListController.FILTERS, function(filter) {
|
||||
router.route(filter, { path: '/' + filter });
|
||||
router.route(filter, { path: '/' + filter + '/more' });
|
||||
router.route(filter + 'Category', { path: '/category/:slug/l/' + filter });
|
||||
router.route(filter + 'Category', { path: '/category/:slug/l/' + filter + '/more' });
|
||||
router.route(filter + 'CategoryNone', { path: '/category/:slug/none/l/' + filter });
|
||||
router.route(filter + 'CategoryNone', { path: '/category/:slug/none/l/' + filter + '/more' });
|
||||
router.route(filter + 'Category', { path: '/category/:parentSlug/:slug/l/' + filter });
|
||||
router.route(filter + 'Category', { path: '/category/:parentSlug/:slug/l/' + filter + '/more' });
|
||||
});
|
||||
|
||||
// categories page
|
||||
this.route('categories', { path: '/categories' });
|
||||
|
||||
// category
|
||||
// default filter for a category
|
||||
this.route('category', { path: '/category/:slug' });
|
||||
this.route('category', { path: '/category/:slug/more' });
|
||||
this.route('categoryNone', { path: '/category/:slug/none' });
|
||||
|
@ -49,33 +63,31 @@ Discourse.Route.buildRoutes(function() {
|
|||
this.route('category', { path: '/category/:parentSlug/:slug' });
|
||||
this.route('category', { path: '/category/:parentSlug/:slug/more' });
|
||||
|
||||
// top page
|
||||
this.route('top', { path: '/top' });
|
||||
// homepage
|
||||
var homepage = Discourse.User.current() ? Discourse.User.currentProp('homepage') : Discourse.Utilities.defaultHomepage();
|
||||
this.route(homepage, { path: '/' });
|
||||
});
|
||||
|
||||
// User routes
|
||||
this.resource('user', { path: '/users/:username' }, function() {
|
||||
this.route('index', { path: '/'} );
|
||||
|
||||
this.resource('userActivity', { path: '/activity' }, function() {
|
||||
var self = this;
|
||||
Object.keys(Discourse.UserAction.TYPES).forEach(function (userAction) {
|
||||
self.route(userAction, { path: userAction.replace("_", "-") });
|
||||
router = this;
|
||||
_.map(Discourse.UserAction.TYPES, function (id, userAction) {
|
||||
router.route(userAction, { path: userAction.replace('_', '-') });
|
||||
});
|
||||
});
|
||||
|
||||
this.resource('userPrivateMessages', { path: '/private-messages' }, function() {
|
||||
this.route('mine', { path: '/mine' });
|
||||
this.route('unread', { path: '/unread' });
|
||||
this.route('mine');
|
||||
this.route('unread');
|
||||
});
|
||||
|
||||
this.resource('preferences', { path: '/preferences' }, function() {
|
||||
this.route('username', { path: '/username' });
|
||||
this.route('email', { path: '/email' });
|
||||
this.resource('preferences', function() {
|
||||
this.route('username');
|
||||
this.route('email');
|
||||
this.route('about', { path: '/about-me' });
|
||||
this.route('avatar', { path: '/avatar' });
|
||||
});
|
||||
|
||||
this.route('invited', { path: 'invited' });
|
||||
this.route('invited');
|
||||
});
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ Discourse.Route = Em.Route.extend({
|
|||
Discourse.set('notifyCount',0);
|
||||
|
||||
var hideDropDownFunction = $('html').data('hide-dropdown');
|
||||
if (hideDropDownFunction) return hideDropDownFunction();
|
||||
if (hideDropDownFunction) { hideDropDownFunction(); }
|
||||
}
|
||||
|
||||
});
|
||||
|
|
|
@ -10,21 +10,8 @@ Discourse.FilteredListRoute = Discourse.Route.extend({
|
|||
|
||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
|
||||
this.controllerFor('list').setProperties({
|
||||
canCreateTopic: false,
|
||||
filterMode: ''
|
||||
});
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('listTopics', {
|
||||
into: 'list',
|
||||
outlet: 'listView',
|
||||
controller: 'listTopics'
|
||||
});
|
||||
this.render('listTopics', { into: 'list', outlet: 'listView', controller: 'listTopics' });
|
||||
},
|
||||
|
||||
setupController: function() {
|
||||
|
@ -44,7 +31,16 @@ Discourse.FilteredListRoute = Discourse.Route.extend({
|
|||
listTopicsController.set('model', topicList);
|
||||
Discourse.FilteredListRoute.scrollToLastPosition();
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
|
||||
this.controllerFor('list').setProperties({
|
||||
canCreateTopic: false,
|
||||
filterMode: ''
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Discourse.FilteredListRoute.reopenClass({
|
||||
|
@ -57,6 +53,10 @@ Discourse.FilteredListRoute.reopenClass({
|
|||
}
|
||||
});
|
||||
|
||||
Discourse.ListController.filters.forEach(function(filter) {
|
||||
Discourse["List" + (filter.capitalize()) + "Route"] = Discourse.FilteredListRoute.extend({ filter: filter });
|
||||
_.each(Discourse.ListController.FILTERS, function(filter) {
|
||||
Discourse["List" + filter.capitalize() + "Route"] = Discourse.FilteredListRoute.extend({ filter: filter });
|
||||
});
|
||||
|
||||
_.each(Discourse.TopList.PERIODS, function(period) {
|
||||
Discourse["ListTop" + period.capitalize() + "Route"] = Discourse.FilteredListRoute.extend({ filter: "top/" + period });
|
||||
});
|
||||
|
|
|
@ -8,34 +8,18 @@
|
|||
**/
|
||||
Discourse.ListCategoriesRoute = Discourse.Route.extend({
|
||||
|
||||
template: 'listCategories',
|
||||
|
||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||
|
||||
actions: {
|
||||
createCategory: function() {
|
||||
Discourse.Route.showModal(this, 'editCategory', Discourse.Category.create({
|
||||
color: 'AB9364', text_color: 'FFFFFF', hotness: 5, group_permissions: [{group_name: "everyone", permission_type: 1}],
|
||||
available_groups: Discourse.Site.current().group_names
|
||||
}));
|
||||
this.controllerFor('editCategory').set('selectedTab', 'general');
|
||||
}
|
||||
},
|
||||
|
||||
model: function() {
|
||||
var listTopicsController = this.controllerFor('listTopics');
|
||||
if (listTopicsController) { listTopicsController.set('content', null); }
|
||||
this.controllerFor('listTop').set('content', null);
|
||||
this.controllerFor('listTopics').set('content', null);
|
||||
return this.controllerFor('list').load('categories');
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
activate: function() {
|
||||
this._super();
|
||||
this.controllerFor('list').set('canCreateCategory', false);
|
||||
this.controllerFor('list').setProperties({ filterMode: 'categories', category: null });
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render(this.get('template'), { into: 'list', outlet: 'listView' });
|
||||
},
|
||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||
|
||||
afterModel: function(categoryList) {
|
||||
this.controllerFor('list').setProperties({
|
||||
|
@ -44,13 +28,23 @@ Discourse.ListCategoriesRoute = Discourse.Route.extend({
|
|||
});
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this.controllerFor('list').setProperties({
|
||||
filterMode: 'categories',
|
||||
category: null
|
||||
});
|
||||
}
|
||||
renderTemplate: function() {
|
||||
this.render('listCategories', { into: 'list', outlet: 'listView' });
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
this.controllerFor('list').set('canCreateCategory', false);
|
||||
},
|
||||
|
||||
actions: {
|
||||
createCategory: function() {
|
||||
Discourse.Route.showModal(this, 'editCategory', Discourse.Category.create({
|
||||
color: 'AB9364', text_color: 'FFFFFF', hotness: 5, group_permissions: [{group_name: 'everyone', permission_type: 1}],
|
||||
available_groups: Discourse.Site.current().group_names
|
||||
}));
|
||||
this.controllerFor('editCategory').set('selectedTab', 'general');
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -7,8 +7,17 @@
|
|||
@module Discourse
|
||||
**/
|
||||
Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend({
|
||||
|
||||
model: function(params) {
|
||||
return Discourse.Category.findBySlug(Em.get(params, 'slug'), Em.get(params, 'parentSlug'));
|
||||
this.controllerFor('listTop').set('content', null);
|
||||
this.controllerFor('listCategories').set('content', null);
|
||||
return Discourse.Category.findBySlug(params.slug, params.parentSlug);
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this._super();
|
||||
// Add a search context
|
||||
this.controllerFor('search').set('searchContext', this.modelFor(this.get('routeName')).get('searchContext'));
|
||||
},
|
||||
|
||||
setupController: function(controller, category) {
|
||||
|
@ -37,33 +46,29 @@ Discourse.ListCategoryRoute = Discourse.FilteredListRoute.extend({
|
|||
canCreateTopic: topicList.get('can_create_topic'),
|
||||
category: category
|
||||
});
|
||||
self.controllerFor('listTopics').set('content', topicList);
|
||||
self.controllerFor('listTopics').set('category', category);
|
||||
self.controllerFor('listTopics').setProperties({
|
||||
content: topicList,
|
||||
category: category
|
||||
});
|
||||
Discourse.FilteredListRoute.scrollToLastPosition();
|
||||
});
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this._super();
|
||||
|
||||
// Add a search context
|
||||
this.controllerFor('search').set('searchContext', this.modelFor(this.get('routeName')).get('searchContext'));
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
|
||||
// Clear the search context
|
||||
this.controllerFor('search').set('searchContext', null);
|
||||
}
|
||||
});
|
||||
|
||||
Discourse.ListCategoryNoneRoute = Discourse.ListCategoryRoute.extend({
|
||||
noSubcategories: true
|
||||
});
|
||||
Discourse.ListCategoryNoneRoute = Discourse.ListCategoryRoute.extend({ noSubcategories: true });
|
||||
|
||||
Discourse.ListController.filters.forEach(function(filter) {
|
||||
_.each(Discourse.ListController.FILTERS, function(filter) {
|
||||
Discourse["List" + filter.capitalize() + "CategoryRoute"] = Discourse.ListCategoryRoute.extend({ filter: filter });
|
||||
Discourse["List" + filter.capitalize() + "CategoryNoneRoute"] = Discourse.ListCategoryRoute.extend({ filter: filter, noSubcategories: true });
|
||||
});
|
||||
|
||||
|
||||
_.each(Discourse.TopList.PERIODS, function(period) {
|
||||
Discourse["ListTop" + period.capitalize() + "CategoryRoute"] = Discourse.ListCategoryRoute.extend({ filter: "top/" + period });
|
||||
Discourse["ListTop" + period.capitalize() + "CategoryNoneRoute"] = Discourse.ListCategoryRoute.extend({ filter: "top/" + period, noSubcategories: true });
|
||||
});
|
||||
|
|
|
@ -1,26 +1,42 @@
|
|||
Discourse.ListTopRoute = Discourse.Route.extend({
|
||||
|
||||
model: function() {
|
||||
return Discourse.TopList.find();
|
||||
model: function(params) {
|
||||
this.controllerFor('listCategories').set('content', null);
|
||||
this.controllerFor('listTopics').set('content', null);
|
||||
this.controllerFor('list').set('loading', true);
|
||||
|
||||
var category = Discourse.Category.findBySlug(params.slug, params.parentSlug);
|
||||
if (category) { this.set('category', category); }
|
||||
|
||||
return Discourse.TopList.find(this.period, category);
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
this._super();
|
||||
// will mark the "top" navigation item as selected
|
||||
this.controllerFor('list').setProperties({
|
||||
filterMode: 'top',
|
||||
category: null
|
||||
});
|
||||
this.controllerFor('list').setProperties({ filterMode: 'top', category: null });
|
||||
},
|
||||
|
||||
redirect: function() { Discourse.redirectIfLoginRequired(this); },
|
||||
|
||||
setupController: function(controller, model) {
|
||||
var category = this.get('category'),
|
||||
categorySlug = Discourse.Category.slugFor(category),
|
||||
url = category === undefined ? 'top' : 'category/' + categorySlug + '/l/top';
|
||||
|
||||
this.controllerFor('listTop').setProperties({ content: model, category: category });
|
||||
this.controllerFor('list').setProperties({ loading: false, filterMode: url });
|
||||
|
||||
if (category !== undefined) {
|
||||
this.controllerFor('list').set('category', category);
|
||||
}
|
||||
|
||||
Discourse.set('title', I18n.t('filters.top.title'));
|
||||
},
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('top', { into: 'list', outlet: 'listView' });
|
||||
},
|
||||
|
||||
deactivate: function() {
|
||||
this._super();
|
||||
// Clear any filters when we leave the route
|
||||
Discourse.URL.set('queryParams', null);
|
||||
this.render('listTop', { into: 'list', outlet: 'listView' });
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Discourse.ListTopCategoryRoute = Discourse.ListTopRoute.extend({});
|
||||
|
|
|
@ -6,16 +6,16 @@
|
|||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.StaticController.pages.forEach(function(page) {
|
||||
_.each(Discourse.StaticController.PAGES, function(page) {
|
||||
|
||||
Discourse[(page.capitalize()) + "Route"] = Discourse.Route.extend({
|
||||
Discourse[page.capitalize() + "Route"] = Discourse.Route.extend({
|
||||
|
||||
renderTemplate: function() {
|
||||
this.render('static');
|
||||
},
|
||||
|
||||
setupController: function() {
|
||||
var config_key = Discourse.StaticController.configs[page];
|
||||
var config_key = Discourse.StaticController.CONFIGS[page];
|
||||
if (config_key && Discourse.SiteSettings[config_key].length > 0) {
|
||||
Discourse.URL.redirectTo(Discourse.SiteSettings[config_key]);
|
||||
} else {
|
||||
|
@ -26,5 +26,3 @@ Discourse.StaticController.pages.forEach(function(page) {
|
|||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
|
|
@ -32,7 +32,6 @@ Discourse.UserPrivateMessagesIndexRoute = createPMRoute('index', 'private-messag
|
|||
Discourse.UserPrivateMessagesMineRoute = createPMRoute('mine', 'private-messages-sent');
|
||||
Discourse.UserPrivateMessagesUnreadRoute = createPMRoute('unread', 'private-messages-unread');
|
||||
|
||||
|
||||
Discourse.UserActivityTopicsRoute = Discourse.UserTopicListRoute.extend({
|
||||
userActionType: Discourse.UserAction.TYPES.topics,
|
||||
|
||||
|
@ -45,6 +44,6 @@ Discourse.UserActivityStarredRoute = Discourse.UserTopicListRoute.extend({
|
|||
userActionType: Discourse.UserAction.TYPES.starred,
|
||||
|
||||
model: function() {
|
||||
return Discourse.TopicList.find('starred', {user_id: this.modelFor('user').get('id') });
|
||||
return Discourse.TopicList.find('starred', { user_id: this.modelFor('user').get('id') });
|
||||
}
|
||||
});
|
||||
});
|
||||
|
|
|
@ -37,9 +37,11 @@
|
|||
<a href="{{unbound topic.lastUnreadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new}}'><i class='fa fa-asterisk'></i></a>
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
<td class="category">
|
||||
{{categoryLink topic.category}}
|
||||
</td>
|
||||
|
||||
<td class='num posts'><a href="{{unbound topic.lastUnreadUrl}}" class='badge-posts'>{{number topic.posts_count numberKey="posts_long"}}</a></td>
|
||||
|
||||
<td class='num likes'>
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<div class='contents'>
|
||||
|
||||
<table id='topic-list' class='categories'>
|
||||
<thead>
|
||||
<tr>
|
||||
<th class='category'>{{i18n categories.category}}</th>
|
||||
<th class='latest'>{{i18n categories.latest}}</th>
|
||||
<th class='stats topics'>{{i18n categories.topics}}</th>
|
||||
<th class='stats posts'>{{i18n categories.posts}}
|
||||
{{#if canEdit}}
|
||||
<button title='{{i18n categories.toggle_ordering}}' class='btn toggle-admin no-text' {{action toggleOrdering}}><i class='fa fa-wrench'></i></button>
|
||||
{{/if}}
|
||||
</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th class='category'>{{i18n categories.category}}</th>
|
||||
<th class='latest'>{{i18n categories.latest}}</th>
|
||||
<th class='stats topics'>{{i18n categories.topics}}</th>
|
||||
<th class='stats posts'>{{i18n categories.posts}}
|
||||
{{#if canEdit}}<button title='{{i18n categories.toggle_ordering}}' class='btn toggle-admin no-text' {{action toggleOrdering}}><i class='fa fa-wrench'></i></button>{{/if}}
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.categories}}
|
||||
|
@ -19,9 +16,7 @@
|
|||
<td class='category'>
|
||||
<div>
|
||||
<div class="pull-left">
|
||||
{{#if controller.ordering}}
|
||||
<i class="fa fa-bars"></i>
|
||||
{{/if}}
|
||||
{{#if controller.ordering}}<i class="fa fa-bars"></i>{{/if}}
|
||||
{{categoryLink this allowUncategorized=true}}
|
||||
{{#if unreadTopics}}
|
||||
<a href={{unbound unreadUrl}} class='badge new-posts badge-notification' title='{{i18n topic.unread_topics count="unreadTopics"}}'>{{unbound unreadTopics}}</a>
|
||||
|
@ -42,7 +37,6 @@
|
|||
{{{description_excerpt}}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if subcategories}}
|
||||
<div class='subcategories'>
|
||||
{{i18n categories.subcategories}}
|
||||
|
@ -102,10 +96,7 @@
|
|||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<footer id='topic-list-bottom'>
|
||||
</footer>
|
||||
<footer id='topic-list-bottom'></footer>
|
||||
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
<div class="top-lists">
|
||||
{{#if redirectedToTopPageReason}}
|
||||
<div class="alert alert-info">
|
||||
{{redirectedToTopPageReason}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if content.yearly}}
|
||||
<div class="clearfix">
|
||||
<h2>{{i18n filters.top.this_year}}</h2>
|
||||
{{basic-topic-list topicList=content.yearly}}
|
||||
{{#if content.yearly.topics.length}}<a href={{unbound showMoreYearlyUrl}} class='btn pull-right'>{{i18n show_more}}</a>{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if content.monthly}}
|
||||
<div class="clearfix">
|
||||
<h2>{{i18n filters.top.this_month}}</h2>
|
||||
{{basic-topic-list topicList=content.monthly}}
|
||||
{{#if content.monthly.topics.length}}<a href={{unbound showMoreMonthlyUrl}} class='btn pull-right'>{{i18n show_more}}</a>{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if content.weekly}}
|
||||
<div class="clearfix">
|
||||
<h2>{{i18n filters.top.this_week}}</h2>
|
||||
{{basic-topic-list topicList=content.weekly}}
|
||||
{{#if content.weekly.topics.length}}<a href={{unbound showMoreWeeklyUrl}} class='btn pull-right'>{{i18n show_more}}</a>{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if content.daily}}
|
||||
<div class="clearfix">
|
||||
<h2>{{i18n filters.top.today}}</h2>
|
||||
{{basic-topic-list topicList=content.daily}}
|
||||
{{#if content.daily.topics.length}}<a href={{unbound showMoreDailyUrl}} class='btn pull-right'>{{i18n show_more}}</a>{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
<footer id="topic-list-bottom">
|
||||
<h3>
|
||||
{{#if hasDisplayedAllTopLists}}
|
||||
{{#link-to "list.categories"}}{{i18n topic.browse_all_categories}}{{/link-to}} {{i18n or}} {{#link-to 'list.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}}.
|
||||
{{else}}
|
||||
{{#link-to "list.categories"}}{{i18n topic.browse_all_categories}}{{/link-to}}, {{#link-to 'list.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}} {{i18n or}} {{i18n filters.top.other_periods}}
|
||||
{{#unless content.yearly}}<a href={{unbound showMoreYearlyUrl}} class='btn'>{{i18n filters.top.this_year}}</a>{{/unless}}
|
||||
{{#unless content.monthly}}<a href={{unbound showMoreMonthlyUrl}} class='btn'>{{i18n filters.top.this_month}}</a>{{/unless}}
|
||||
{{#unless content.weekly}}<a href={{unbound showMoreWeeklyUrl}} class='btn'>{{i18n filters.top.this_week}}</a>{{/unless}}
|
||||
{{#unless content.daily}}<a href={{unbound showMoreDailyUrl}} class='btn'>{{i18n filters.top.today}}</a>{{/unless}}
|
||||
{{/if}}
|
||||
</h3>
|
||||
</footer>
|
||||
</div>
|
|
@ -1,18 +0,0 @@
|
|||
{{#if redirectedToTopPageReason}}
|
||||
<div class="alert alert-info">
|
||||
{{redirectedToTopPageReason}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if showThisYear}}
|
||||
<h2>{{i18n filters.top.this_year}}</h2>
|
||||
{{basic-topic-list topicList=content.yearly}}
|
||||
{{/if}}
|
||||
<h2>{{i18n filters.top.this_month}}</h2>
|
||||
{{basic-topic-list topicList=content.monthly}}
|
||||
<h2>{{i18n filters.top.this_week}}</h2>
|
||||
{{basic-topic-list topicList=content.weekly}}
|
||||
<h2>{{i18n filters.top.today}}</h2>
|
||||
{{basic-topic-list topicList=content.daily}}
|
||||
<footer id="topic-list-bottom">
|
||||
<h3>{{#link-to "list.categories"}}{{i18n topic.browse_all_categories}}{{/link-to}} {{i18n or}} {{#link-to 'list.latest'}}{{i18n topic.view_latest_topics}}{{/link-to}}</h3>
|
||||
</footer>
|
18
app/assets/javascripts/discourse/views/list/list_top_view.js
Normal file
18
app/assets/javascripts/discourse/views/list/list_top_view.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
This view handles the rendering of the top lists
|
||||
|
||||
@class ListTopView
|
||||
@extends Discourse.View
|
||||
@namespace Discourse
|
||||
@module Discourse
|
||||
**/
|
||||
Discourse.ListTopView = Discourse.View.extend({
|
||||
|
||||
didInsertElement: function() {
|
||||
this._super();
|
||||
Em.run.schedule('afterRender', function() {
|
||||
$('html, body').scrollTop(0);
|
||||
});
|
||||
},
|
||||
|
||||
});
|
|
@ -25,7 +25,7 @@ Discourse.NavItemView = Discourse.View.extend({
|
|||
name = "category";
|
||||
}
|
||||
return I18n.t("filters." + name + ".help", extra);
|
||||
}.property("content.filter"),
|
||||
}.property("content.name"),
|
||||
|
||||
|
||||
name: function() {
|
||||
|
|
|
@ -63,6 +63,7 @@
|
|||
width: 100%;
|
||||
border-collapse: separate;
|
||||
border-spacing: 0;
|
||||
margin: 0 0 10px;
|
||||
a.title:visited:not(.badge-notification) {color: #888;}
|
||||
|
||||
> tbody > tr {
|
||||
|
@ -230,6 +231,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
#list-area .top-lists h2 { margin: 5px 0 10px; }
|
||||
|
||||
#topic-list tbody tr.has-excerpt .star {
|
||||
vertical-align: top;
|
||||
|
|
|
@ -1,6 +1,15 @@
|
|||
class ListController < ApplicationController
|
||||
|
||||
before_filter :ensure_logged_in, except: [:latest, :hot, :category, :top, :category_feed, :latest_feed, :hot_feed, :topics_by]
|
||||
before_filter :ensure_logged_in, except: [
|
||||
:topics_by,
|
||||
# anonymous filters
|
||||
Discourse.anonymous_filters, Discourse.anonymous_filters.map { |f| "#{f}_feed".to_sym },
|
||||
# category
|
||||
:category, :category_feed,
|
||||
# top
|
||||
:top_lists, TopTopic.periods.map { |p| "top_#{p}".to_sym }
|
||||
].flatten
|
||||
|
||||
before_filter :set_category, only: [:category, :category_feed]
|
||||
skip_before_filter :check_xhr
|
||||
|
||||
|
@ -72,13 +81,15 @@ class ListController < ApplicationController
|
|||
redirect_to latest_path, :status => 301
|
||||
end
|
||||
|
||||
def top
|
||||
def top_lists
|
||||
discourse_expires_in 1.minute
|
||||
|
||||
top = generate_top_lists
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
@top = top
|
||||
store_preloaded('top_list', MultiJson.dump(TopListSerializer.new(top, scope: guardian, root: false)))
|
||||
store_preloaded('top_lists', MultiJson.dump(TopListSerializer.new(top, scope: guardian, root: false)))
|
||||
render 'top'
|
||||
end
|
||||
format.json do
|
||||
|
@ -87,6 +98,16 @@ class ListController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
define_method("top_#{period}") do
|
||||
options = build_topic_list_options
|
||||
user = list_target_user
|
||||
list = TopicQuery.new(user, options).public_send("list_top_#{period}")
|
||||
list.more_topics_url = construct_url_with(period, options, "top")
|
||||
respond(list)
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def category_response(extra_opts=nil)
|
||||
|
@ -181,19 +202,27 @@ class ListController < ApplicationController
|
|||
|
||||
def generate_top_lists
|
||||
top = {}
|
||||
topic_ids = Set.new
|
||||
options = {
|
||||
per_page: SiteSetting.topics_per_period_in_summary,
|
||||
category: params[:category]
|
||||
}
|
||||
topic_query = TopicQuery.new(current_user, options)
|
||||
periods = periods_since(current_user.try(:last_seen_at))
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
options = {
|
||||
per_page: SiteSetting.topics_per_period_in_summary,
|
||||
except_topic_ids: topic_ids.to_a
|
||||
}
|
||||
list = TopicQuery.new(current_user, options).list_top_for(period)
|
||||
topic_ids.merge(list.topic_ids)
|
||||
top[period] = list
|
||||
end
|
||||
periods.each { |period| top[period] = topic_query.list_top_for(period) }
|
||||
|
||||
top
|
||||
end
|
||||
|
||||
def periods_since(date)
|
||||
date ||= 1.year.ago
|
||||
|
||||
periods = [:daily]
|
||||
periods << :weekly if date < 8.days.ago
|
||||
periods << :monthly if date < 35.days.ago
|
||||
periods << :yearly if date < 180.days.ago
|
||||
|
||||
periods
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -1,19 +1,12 @@
|
|||
class TopListSerializer < ApplicationSerializer
|
||||
|
||||
attributes :can_create_topic,
|
||||
:yearly,
|
||||
:monthly,
|
||||
:weekly,
|
||||
:daily
|
||||
|
||||
def can_create_topic
|
||||
scope.can_create?(Topic)
|
||||
end
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
attribute period
|
||||
|
||||
define_method(period) do
|
||||
TopicListSerializer.new(object[period], scope: scope).as_json
|
||||
TopicListSerializer.new(object[period], scope: scope).as_json if object[period]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -604,6 +604,7 @@ en:
|
|||
latest: "There are no latest topics. That's sad."
|
||||
hot: "There are no hot topics."
|
||||
category: "There are no {{category}} topics."
|
||||
top: "There are no top topics."
|
||||
bottom:
|
||||
latest: "There are no more latest topics."
|
||||
hot: "There are no more hot topics."
|
||||
|
@ -613,6 +614,7 @@ en:
|
|||
unread: "There are no more unread topics."
|
||||
starred: "There are no more starred topics."
|
||||
category: "There are no more {{category}} topics."
|
||||
top: "There are no more top topics."
|
||||
|
||||
rank_details:
|
||||
toggle: toggle topic rank details
|
||||
|
@ -1122,6 +1124,7 @@ en:
|
|||
this_month: "This month"
|
||||
this_week: "This week"
|
||||
today: "Today"
|
||||
other_periods: "dig into other periods"
|
||||
redirect_reasons:
|
||||
new_user: "Welcome! As a new visitor, we thought you might like to start with this list of the top discussion topics in the last year."
|
||||
not_seen_in_a_month: "Welcome back! We haven't seen you in a while. These are the top discussion topics since you've been away."
|
||||
|
|
|
@ -106,7 +106,6 @@ Discourse::Application.routes.draw do
|
|||
get "email/unsubscribe/:key" => "email#unsubscribe", as: "email_unsubscribe"
|
||||
post "email/resubscribe/:key" => "email#resubscribe", as: "email_resubscribe"
|
||||
|
||||
|
||||
resources :session, id: USERNAME_ROUTE_FORMAT, only: [:create, :destroy] do
|
||||
collection do
|
||||
post "forgot_password"
|
||||
|
@ -195,18 +194,33 @@ Discourse::Application.routes.draw do
|
|||
end
|
||||
resources :user_actions
|
||||
|
||||
# We've renamed popular to latest. If people access it we want a permanent redirect.
|
||||
get "popular" => "list#popular_redirect"
|
||||
get "popular/more" => "list#popular_redirect"
|
||||
|
||||
resources :categories, :except => :show
|
||||
get "category/:id/show" => "categories#show"
|
||||
post "category/:category_id/move" => "categories#move", as: "category_move"
|
||||
|
||||
get "category/:category.rss" => "list#category_feed", format: :rss, as: "category_feed"
|
||||
get "category/:category" => "list#category", as: "category_list"
|
||||
get "category/:category/none" => "list#category_none", as: "category_list_none"
|
||||
get "category/:category/more" => "list#category", as: "category_list_more"
|
||||
get "category/:category" => "list#category"
|
||||
get "category/:category/more" => "list#category"
|
||||
get "category/:category/none" => "list#category_none"
|
||||
get "category/:category/none/more" => "list#category_none"
|
||||
get "category/:parent_category/:category" => "list#category"
|
||||
get "category/:parent_category/:category/more" => "list#category"
|
||||
|
||||
# We"ve renamed popular to latest. If people access it we want a permanent redirect.
|
||||
get "popular" => "list#popular_redirect"
|
||||
get "popular/more" => "list#popular_redirect"
|
||||
get "top" => "list#top_lists"
|
||||
get "category/:category/l/top" => "list#top_lists"
|
||||
get "category/:parent_category/:category/l/top" => "list#top_lists"
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
get "top/#{period}" => "list#top_#{period}"
|
||||
get "top/#{period}/more" => "list#top_#{period}"
|
||||
get "category/:category/l/top/#{period}" => "list#top_#{period}"
|
||||
get "category/:category/l/top/#{period}/more" => "list#top_#{period}"
|
||||
get "category/:parent_category/:category/l/top/#{period}" => "list#top_#{period}"
|
||||
get "category/:parent_category/:category/l/top/#{period}/more" => "list#top_#{period}"
|
||||
end
|
||||
|
||||
Discourse.anonymous_filters.each do |filter|
|
||||
get "#{filter}.rss" => "list##{filter}_feed", format: :rss
|
||||
|
@ -215,26 +229,19 @@ Discourse::Application.routes.draw do
|
|||
Discourse.filters.each do |filter|
|
||||
get "#{filter}" => "list##{filter}"
|
||||
get "#{filter}/more" => "list##{filter}"
|
||||
|
||||
get "category/:category/l/#{filter}" => "list##{filter}"
|
||||
get "category/:category/l/#{filter}/more" => "list##{filter}"
|
||||
get "category/:parent_category/:category/l/#{filter}" => "list##{filter}"
|
||||
get "category/:parent_category/:category/l/#{filter}/more" => "list##{filter}"
|
||||
end
|
||||
|
||||
get "top" => "list#top"
|
||||
get "category/:category/l/top" => "list#top"
|
||||
get "category/:parent_category/:category/l/top" => "list#top"
|
||||
|
||||
get "category/:parent_category/:category" => "list#category", as: "category_list_parent"
|
||||
|
||||
get "search" => "search#query"
|
||||
|
||||
# Topics resource
|
||||
get "t/:id" => "topics#show"
|
||||
delete "t/:id" => "topics#destroy"
|
||||
put "t/:id" => "topics#update"
|
||||
post "t" => "topics#create"
|
||||
put "t/:id" => "topics#update"
|
||||
delete "t/:id" => "topics#destroy"
|
||||
post "topics/timings"
|
||||
get "topics/similar_to"
|
||||
get "topics/created-by/:username" => "list#topics_by", as: "topics_by", constraints: {username: USERNAME_ROUTE_FORMAT}
|
||||
|
@ -277,7 +284,6 @@ Discourse::Application.routes.draw do
|
|||
|
||||
get "raw/:topic_id(/:post_number)" => "posts#markdown"
|
||||
|
||||
|
||||
resources :invites
|
||||
delete "invites" => "invites#destroy"
|
||||
|
||||
|
@ -299,6 +305,6 @@ Discourse::Application.routes.draw do
|
|||
# special case for categories
|
||||
root to: "categories#index", constraints: HomePageConstraint.new("categories"), :as => "categories_index"
|
||||
# special case for top
|
||||
root to: "list#top", constraints: HomePageConstraint.new("top"), :as => "list_top"
|
||||
root to: "list#top_lists", constraints: HomePageConstraint.new("top"), :as => "top_lists"
|
||||
|
||||
end
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
class CreateTopTopics < ActiveRecord::Migration
|
||||
PERIODS = [:yearly, :monthly, :weekly, :daily]
|
||||
SORT_ORDERS = [:posts, :views, :likes]
|
||||
|
||||
def change
|
||||
create_table :top_topics, force: true do |t|
|
||||
t.belongs_to :topic
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
TopTopic.sort_orders.each do |sort|
|
||||
PERIODS.each do |period|
|
||||
SORT_ORDERS.each do |sort|
|
||||
t.integer "#{period}_#{sort}_count".to_sym, null: false, default: 0
|
||||
end
|
||||
end
|
||||
|
@ -13,8 +16,8 @@ class CreateTopTopics < ActiveRecord::Migration
|
|||
|
||||
add_index :top_topics, :topic_id, unique: true
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
TopTopic.sort_orders.each do |sort|
|
||||
PERIODS.each do |period|
|
||||
SORT_ORDERS.each do |sort|
|
||||
add_index :top_topics, "#{period}_#{sort}_count".to_sym, order: 'desc'
|
||||
end
|
||||
end
|
||||
|
|
|
@ -89,11 +89,17 @@ class TopicQuery
|
|||
score = "#{period}_score"
|
||||
create_list(:top, unordered: true) do |topics|
|
||||
topics.joins(:top_topic)
|
||||
.where("top_topics.#{score} > 1")
|
||||
.where("top_topics.#{score} > 0")
|
||||
.order("top_topics.#{score} DESC, topics.bumped_at DESC")
|
||||
end
|
||||
end
|
||||
|
||||
TopTopic.periods.each do |period|
|
||||
define_method("list_top_#{period}") do
|
||||
list_top_for(period)
|
||||
end
|
||||
end
|
||||
|
||||
def list_topics_by(user)
|
||||
create_list(:user_topics) do |topics|
|
||||
topics.where(user_id: user.id)
|
||||
|
|
|
@ -8,7 +8,7 @@ test("navigatedToHome", function() {
|
|||
mock.expects("refresh").twice();
|
||||
ok(Discourse.URL.navigatedToHome("/", "/"));
|
||||
|
||||
var defaultFilter = "/" + Discourse.ListController.filters[0];
|
||||
var defaultFilter = "/" + Discourse.ListController.FILTERS[0];
|
||||
ok(Discourse.URL.navigatedToHome(defaultFilter, "/"));
|
||||
|
||||
ok(!Discourse.URL.navigatedToHome("/old", "/new"));
|
||||
|
|
Loading…
Reference in New Issue
Block a user