Debugging Tool for Hot Topics
This commit is contained in:
parent
161fdcb364
commit
ee76f1926d
|
@ -7,7 +7,8 @@
|
||||||
@module Discourse
|
@module Discourse
|
||||||
**/
|
**/
|
||||||
Discourse.ListTopicsController = Discourse.ObjectController.extend({
|
Discourse.ListTopicsController = Discourse.ObjectController.extend({
|
||||||
needs: ['list', 'composer'],
|
needs: ['list', 'composer', 'modal'],
|
||||||
|
|
||||||
// If we're changing our channel
|
// If we're changing our channel
|
||||||
previousChannel: null,
|
previousChannel: null,
|
||||||
|
|
||||||
|
@ -50,6 +51,14 @@ Discourse.ListTopicsController = Discourse.ObjectController.extend({
|
||||||
topic.toggleStar();
|
topic.toggleStar();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Show rank details
|
||||||
|
showRankDetails: function(topic) {
|
||||||
|
var modalController = this.get('controllers.modal');
|
||||||
|
if (modalController) {
|
||||||
|
modalController.show(Discourse.TopicRankDetailsView.create({ topic: topic }));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
createTopic: function() {
|
createTopic: function() {
|
||||||
this.get('controllers.list').createTopic();
|
this.get('controllers.list').createTopic();
|
||||||
},
|
},
|
||||||
|
|
|
@ -180,6 +180,30 @@ Handlebars.registerHelper('editDate', function(property, options) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
Displays a percentile based on a `percent_rank` field
|
||||||
|
|
||||||
|
@method percentile
|
||||||
|
@for Ember.Handlebars
|
||||||
|
**/
|
||||||
|
Ember.Handlebars.registerHelper('percentile', function(property, options) {
|
||||||
|
var percentile = Ember.Handlebars.get(this, property, options);
|
||||||
|
return Math.round((1.0 - percentile) * 100)
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
Displays a float nicely
|
||||||
|
|
||||||
|
@method float
|
||||||
|
@for Ember.Handlebars
|
||||||
|
**/
|
||||||
|
Ember.Handlebars.registerHelper('float', function(property, options) {
|
||||||
|
var x = Ember.Handlebars.get(this, property, options);
|
||||||
|
if (!x) return "0";
|
||||||
|
if (Math.round(x) === x) return x;
|
||||||
|
return x.toFixed(3)
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Display logic for numbers.
|
Display logic for numbers.
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,12 @@
|
||||||
{{#if unseen}}
|
{{#if unseen}}
|
||||||
<a href="{{lastReadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new}}'><i class='icon icon-asterisk'></i></a>
|
<a href="{{lastReadUrl}}" class='badge new-posts badge-notification' title='{{i18n topic.new}}'><i class='icon icon-asterisk'></i></a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if rank_details}}
|
||||||
|
<i class='icon icon-beaker score' {{action showRankDetails this}} title='{{i18n rank_details.show}}'></i>
|
||||||
|
{{/if}}
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td class='category'>
|
<td class='category'>
|
||||||
{{categoryLink category}}
|
{{categoryLink category}}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
{{#with view.topic.rank_details}}
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<!-- Note this isn't translated because it's a debugging tool for a feature
|
||||||
|
that is not complete yet. We will probably rip this out altogether -->
|
||||||
|
|
||||||
|
<table class='table'>
|
||||||
|
<tr>
|
||||||
|
<td>hot topic type</td>
|
||||||
|
<td>
|
||||||
|
{{hot_topic_type}}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>random bias</td>
|
||||||
|
<td>{{float random_bias}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>random multiplier</td>
|
||||||
|
<td>{{float random_multiplier}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>days ago bias</td>
|
||||||
|
<td>{{float days_ago_bias}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>days ago multiplier</td>
|
||||||
|
<td>{{float days_ago_multiplier}}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ranking formula</td>
|
||||||
|
<td>
|
||||||
|
<p>= (random_bias * random_multiplier) +<br/>
|
||||||
|
(days_ago_bias * days_ago_multiplier)</p>
|
||||||
|
<p>= ({{float random_bias}} * {{float random_multiplier}}) + ({{float days_ago_bias}} * {{float days_ago_multiplier}})</p>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>ranking score</td>
|
||||||
|
<td><b>{{float ranking_score}}</b></td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
|
</table>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
{{/with}}
|
|
@ -0,0 +1,13 @@
|
||||||
|
/**
|
||||||
|
A modal view for displaying the ranking details of a topic
|
||||||
|
|
||||||
|
@class TopicRankDetailsView
|
||||||
|
@extends Discourse.ModalBodyView
|
||||||
|
@namespace Discourse
|
||||||
|
@module Discourse
|
||||||
|
**/
|
||||||
|
Discourse.TopicRankDetailsView = Discourse.ModalBodyView.extend({
|
||||||
|
templateName: 'modal/topic_rank_details',
|
||||||
|
title: Em.String.i18n('rank_details.title')
|
||||||
|
|
||||||
|
});
|
|
@ -151,6 +151,8 @@
|
||||||
.archetype-option {
|
.archetype-option {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
.password-confirmation {
|
.password-confirmation {
|
||||||
display: none;
|
display: none;
|
||||||
|
|
|
@ -97,7 +97,20 @@
|
||||||
.main-link {
|
.main-link {
|
||||||
width: 515px;
|
width: 515px;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
|
|
||||||
|
&:hover i.score {
|
||||||
|
display: inline-block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i.score {
|
||||||
|
color: green;
|
||||||
|
cursor: pointer;
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@include medium-width {
|
@include medium-width {
|
||||||
.main-link {
|
.main-link {
|
||||||
width: 400px;
|
width: 400px;
|
||||||
|
|
|
@ -28,7 +28,6 @@ class ListController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def category
|
def category
|
||||||
|
|
||||||
query = TopicQuery.new(current_user, page: params[:page])
|
query = TopicQuery.new(current_user, page: params[:page])
|
||||||
list = nil
|
list = nil
|
||||||
|
|
||||||
|
|
|
@ -18,9 +18,23 @@ class HotTopic < ActiveRecord::Base
|
||||||
no_old_in_first_x_rows = 8 # don't show old results in the first x rows
|
no_old_in_first_x_rows = 8 # don't show old results in the first x rows
|
||||||
|
|
||||||
# Include all sticky uncategorized on Hot
|
# Include all sticky uncategorized on Hot
|
||||||
exec_sql("INSERT INTO hot_topics (topic_id, score)
|
exec_sql("INSERT INTO hot_topics (topic_id,
|
||||||
SELECT t.id, RANDOM()
|
random_bias,
|
||||||
|
random_multiplier,
|
||||||
|
days_ago_bias,
|
||||||
|
days_ago_multiplier,
|
||||||
|
score,
|
||||||
|
hot_topic_type)
|
||||||
|
SELECT t.id,
|
||||||
|
calc.random_bias,
|
||||||
|
1.0,
|
||||||
|
0,
|
||||||
|
1.0,
|
||||||
|
calc.random_bias,
|
||||||
|
1
|
||||||
FROM topics AS t
|
FROM topics AS t
|
||||||
|
INNER JOIN (SELECT id, RANDOM() as random_bias
|
||||||
|
FROM topics) AS calc ON calc.id = t.id
|
||||||
WHERE t.deleted_at IS NULL
|
WHERE t.deleted_at IS NULL
|
||||||
AND t.visible
|
AND t.visible
|
||||||
AND (NOT t.archived)
|
AND (NOT t.archived)
|
||||||
|
@ -28,12 +42,27 @@ class HotTopic < ActiveRecord::Base
|
||||||
AND t.category_id IS NULL")
|
AND t.category_id IS NULL")
|
||||||
|
|
||||||
# Include high percentile recent topics
|
# Include high percentile recent topics
|
||||||
inserted_count = exec_sql("INSERT INTO hot_topics (topic_id, category_id, score)
|
inserted_count = exec_sql("INSERT INTO hot_topics (topic_id,
|
||||||
|
category_id,
|
||||||
|
random_bias,
|
||||||
|
random_multiplier,
|
||||||
|
days_ago_bias,
|
||||||
|
days_ago_multiplier,
|
||||||
|
score,
|
||||||
|
hot_topic_type)
|
||||||
SELECT t.id,
|
SELECT t.id,
|
||||||
t.category_id,
|
t.category_id,
|
||||||
((1.0 - (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP-t.created_at)/86400) / :days_ago) * 0.95) +
|
calc.random_bias,
|
||||||
(RANDOM() * 0.05)
|
0.05,
|
||||||
|
calc.days_ago_bias,
|
||||||
|
0.95,
|
||||||
|
(calc.random_bias * 0.05) + (days_ago_bias * 0.95),
|
||||||
|
2
|
||||||
FROM topics AS t
|
FROM topics AS t
|
||||||
|
INNER JOIN (SELECT id,
|
||||||
|
RANDOM() as random_bias,
|
||||||
|
((1.0 - (EXTRACT(EPOCH FROM CURRENT_TIMESTAMP-created_at)/86400) / :days_ago) * 0.95) AS days_ago_bias
|
||||||
|
FROM topics) AS calc ON calc.id = t.id
|
||||||
WHERE t.deleted_at IS NULL
|
WHERE t.deleted_at IS NULL
|
||||||
AND t.visible
|
AND t.visible
|
||||||
AND (NOT t.closed)
|
AND (NOT t.closed)
|
||||||
|
@ -56,16 +85,26 @@ class HotTopic < ActiveRecord::Base
|
||||||
max_old_score = HotTopic.order('score desc').limit(no_old_in_first_x_rows).last.score
|
max_old_score = HotTopic.order('score desc').limit(no_old_in_first_x_rows).last.score
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Add a sprinkling of random older topics
|
# Add a sprinkling of random older topics
|
||||||
exec_sql("INSERT INTO hot_topics (topic_id, category_id, score)
|
exec_sql("INSERT INTO hot_topics (topic_id,
|
||||||
|
category_id,
|
||||||
|
random_bias,
|
||||||
|
random_multiplier,
|
||||||
|
days_ago_bias,
|
||||||
|
days_ago_multiplier,
|
||||||
|
score,
|
||||||
|
hot_topic_type)
|
||||||
SELECT t.id,
|
SELECT t.id,
|
||||||
t.category_id,
|
t.category_id,
|
||||||
RANDOM() * :max_old_score
|
calc.random_bias,
|
||||||
|
:max_old_score,
|
||||||
|
0,
|
||||||
|
1.0,
|
||||||
|
calc.random_bias * :max_old_score,
|
||||||
|
3
|
||||||
FROM topics AS t
|
FROM topics AS t
|
||||||
|
INNER JOIN (SELECT id, RANDOM() as random_bias
|
||||||
|
FROM topics) AS calc ON calc.id = t.id
|
||||||
WHERE t.deleted_at IS NULL
|
WHERE t.deleted_at IS NULL
|
||||||
AND t.visible
|
AND t.visible
|
||||||
AND (NOT t.closed)
|
AND (NOT t.closed)
|
||||||
|
|
|
@ -55,6 +55,7 @@ class Topic < ActiveRecord::Base
|
||||||
# When we want to temporarily attach some data to a forum topic (usually before serialization)
|
# When we want to temporarily attach some data to a forum topic (usually before serialization)
|
||||||
attr_accessor :user_data
|
attr_accessor :user_data
|
||||||
attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
|
attr_accessor :posters # TODO: can replace with posters_summary once we remove old list code
|
||||||
|
attr_accessor :topic_list
|
||||||
|
|
||||||
|
|
||||||
# The regular order
|
# The regular order
|
||||||
|
|
|
@ -3,9 +3,14 @@ require_dependency 'avatar_lookup'
|
||||||
class TopicList
|
class TopicList
|
||||||
include ActiveModel::Serialization
|
include ActiveModel::Serialization
|
||||||
|
|
||||||
attr_accessor :more_topics_url, :draft, :draft_key, :draft_sequence
|
attr_accessor :more_topics_url,
|
||||||
|
:draft,
|
||||||
|
:draft_key,
|
||||||
|
:draft_sequence,
|
||||||
|
:filter
|
||||||
|
|
||||||
def initialize(current_user, topics)
|
def initialize(filter, current_user, topics)
|
||||||
|
@filter = filter
|
||||||
@current_user = current_user
|
@current_user = current_user
|
||||||
@topics_input = topics
|
@topics_input = topics
|
||||||
end
|
end
|
||||||
|
@ -30,6 +35,7 @@ class TopicList
|
||||||
@topics.each do |ft|
|
@topics.each do |ft|
|
||||||
ft.user_data = @topic_lookup[ft.id] if @topic_lookup.present?
|
ft.user_data = @topic_lookup[ft.id] if @topic_lookup.present?
|
||||||
ft.posters = ft.posters_summary(ft.user_data, @current_user, avatar_lookup: avatar_lookup)
|
ft.posters = ft.posters_summary(ft.user_data, @current_user, avatar_lookup: avatar_lookup)
|
||||||
|
ft.topic_list = self
|
||||||
end
|
end
|
||||||
|
|
||||||
return @topics
|
return @topics
|
||||||
|
|
|
@ -10,7 +10,8 @@ class TopicListItemSerializer < ListableTopicSerializer
|
||||||
:archived,
|
:archived,
|
||||||
:starred,
|
:starred,
|
||||||
:has_best_of,
|
:has_best_of,
|
||||||
:archetype
|
:archetype,
|
||||||
|
:rank_details
|
||||||
|
|
||||||
has_one :category
|
has_one :category
|
||||||
has_many :posters, serializer: TopicPosterSerializer, embed: :objects
|
has_many :posters, serializer: TopicPosterSerializer, embed: :objects
|
||||||
|
@ -20,6 +21,35 @@ class TopicListItemSerializer < ListableTopicSerializer
|
||||||
end
|
end
|
||||||
alias :include_starred? :seen
|
alias :include_starred? :seen
|
||||||
|
|
||||||
|
|
||||||
|
# This is for debugging / tweaking the hot topic rankings.
|
||||||
|
# We will likely remove it after we are happier with things.
|
||||||
|
def rank_details
|
||||||
|
|
||||||
|
hot_topic_type = case object.hot_topic.hot_topic_type
|
||||||
|
when 1 then 'sticky'
|
||||||
|
when 2 then 'recent high scoring'
|
||||||
|
when 3 then 'old high scoring'
|
||||||
|
end
|
||||||
|
|
||||||
|
{topic_score: object.score,
|
||||||
|
percent_rank: object.percent_rank,
|
||||||
|
random_bias: object.hot_topic.random_bias,
|
||||||
|
random_multiplier: object.hot_topic.random_multiplier,
|
||||||
|
days_ago_bias: object.hot_topic.days_ago_bias,
|
||||||
|
days_ago_multiplier: object.hot_topic.days_ago_multiplier,
|
||||||
|
ranking_score: object.hot_topic.score,
|
||||||
|
hot_topic_type: hot_topic_type}
|
||||||
|
end
|
||||||
|
|
||||||
|
def include_rank_details?
|
||||||
|
return false unless object.topic_list.present?
|
||||||
|
return false unless scope.user.present?
|
||||||
|
return false unless scope.user.admin?
|
||||||
|
|
||||||
|
object.topic_list.filter == :hot
|
||||||
|
end
|
||||||
|
|
||||||
def posters
|
def posters
|
||||||
object.posters || []
|
object.posters || []
|
||||||
end
|
end
|
||||||
|
@ -28,4 +58,5 @@ class TopicListItemSerializer < ListableTopicSerializer
|
||||||
PinnedCheck.new(object, object.user_data).pinned?
|
PinnedCheck.new(object, object.user_data).pinned?
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
class TopicListSerializer < ApplicationSerializer
|
class TopicListSerializer < ApplicationSerializer
|
||||||
|
|
||||||
attributes :can_create_topic, :more_topics_url, :filter_summary, :draft, :draft_key, :draft_sequence
|
attributes :can_create_topic,
|
||||||
|
:more_topics_url,
|
||||||
|
:filter_summary,
|
||||||
|
:draft,
|
||||||
|
:draft_key,
|
||||||
|
:draft_sequence
|
||||||
|
|
||||||
has_many :topics, serializer: TopicListItemSerializer, embed: :objects
|
has_many :topics, serializer: TopicListItemSerializer, embed: :objects
|
||||||
|
|
||||||
|
|
|
@ -386,6 +386,10 @@ en:
|
||||||
favorited: "There are no more favorited topics to read."
|
favorited: "There are no more favorited topics to read."
|
||||||
category: "There are no more {{category}} topics."
|
category: "There are no more {{category}} topics."
|
||||||
|
|
||||||
|
rank_details:
|
||||||
|
show: show topic rank details
|
||||||
|
title: Topic Rank Details
|
||||||
|
|
||||||
topic:
|
topic:
|
||||||
create_in: 'Create {{categoryName}} Topic'
|
create_in: 'Create {{categoryName}} Topic'
|
||||||
create: 'Create Topic'
|
create: 'Create Topic'
|
||||||
|
@ -407,6 +411,7 @@ en:
|
||||||
description: "Sorry, we couldn't find that topic. Perhaps it was removed by a moderator?"
|
description: "Sorry, we couldn't find that topic. Perhaps it was removed by a moderator?"
|
||||||
unread_posts: "you have {{unread}} unread old posts in this topic"
|
unread_posts: "you have {{unread}} unread old posts in this topic"
|
||||||
new_posts: "there are {{new_posts}} new posts in this topic since you last read it"
|
new_posts: "there are {{new_posts}} new posts in this topic since you last read it"
|
||||||
|
|
||||||
likes:
|
likes:
|
||||||
one: "there is 1 like in this topic"
|
one: "there is 1 like in this topic"
|
||||||
other: "there are {{count}} likes in this topic"
|
other: "there are {{count}} likes in this topic"
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class AddValuesToHotTopics < ActiveRecord::Migration
|
||||||
|
def change
|
||||||
|
add_column :hot_topics, :random_bias, :float
|
||||||
|
add_column :hot_topics, :random_multiplier, :float
|
||||||
|
add_column :hot_topics, :days_ago_bias, :float
|
||||||
|
add_column :hot_topics, :days_ago_multiplier, :float
|
||||||
|
add_column :hot_topics, :hot_topic_type, :integer
|
||||||
|
end
|
||||||
|
end
|
|
@ -81,7 +81,7 @@ class TopicQuery
|
||||||
|
|
||||||
# If not logged in, return some random results, preferably in this category
|
# If not logged in, return some random results, preferably in this category
|
||||||
if @user.blank?
|
if @user.blank?
|
||||||
return TopicList.new(@user, random_suggested_results_for(topic, SiteSetting.suggested_topics, exclude_topic_ids))
|
return TopicList.new(:suggested, @user, random_suggested_results_for(topic, SiteSetting.suggested_topics, exclude_topic_ids))
|
||||||
end
|
end
|
||||||
|
|
||||||
results = unread_results(per_page: SiteSetting.suggested_topics)
|
results = unread_results(per_page: SiteSetting.suggested_topics)
|
||||||
|
@ -118,49 +118,45 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
TopicList.new(@user, results)
|
TopicList.new(:suggested, @user, results)
|
||||||
end
|
end
|
||||||
|
|
||||||
# The latest view of topics
|
# The latest view of topics
|
||||||
def list_latest
|
def list_latest
|
||||||
TopicList.new(@user, default_list)
|
create_list(:latest)
|
||||||
end
|
end
|
||||||
|
|
||||||
# The favorited topics
|
# The favorited topics
|
||||||
def list_favorited
|
def list_favorited
|
||||||
return_list do |list|
|
create_list(:favorited) {|topics| topics.where('tu.starred') }
|
||||||
list.where('tu.starred')
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_read
|
def list_read
|
||||||
return_list(unordered: true) do |list|
|
create_list(:read, unordered: true) do |topics|
|
||||||
list.order('COALESCE(tu.last_visited_at, topics.bumped_at) DESC')
|
topics.order('COALESCE(tu.last_visited_at, topics.bumped_at) DESC')
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_hot
|
def list_hot
|
||||||
return_list(unordered: true) do |list|
|
create_list(:hot, unordered: true) do |topics|
|
||||||
# Find hot topics
|
topics.joins(:hot_topic).order(TopicQuery.order_hotness)
|
||||||
list = list.joins(:hot_topic)
|
|
||||||
.order(TopicQuery.order_hotness)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_new
|
def list_new
|
||||||
TopicList.new(@user, new_results)
|
TopicList.new(:new, @user, new_results)
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_unread
|
def list_unread
|
||||||
TopicList.new(@user, unread_results)
|
TopicList.new(:unread, @user, unread_results)
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_posted
|
def list_posted
|
||||||
return_list {|l| l.where('tu.user_id IS NOT NULL') }
|
create_list(:posted) {|l| l.where('tu.user_id IS NOT NULL') }
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_uncategorized
|
def list_uncategorized
|
||||||
return_list(unordered: true) do |list|
|
create_list(:uncategorized, unordered: true) do |list|
|
||||||
list = list.where(category_id: nil)
|
list = list.where(category_id: nil)
|
||||||
|
|
||||||
if @user_id.present?
|
if @user_id.present?
|
||||||
|
@ -172,7 +168,7 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_category(category)
|
def list_category(category)
|
||||||
return_list(unordered: true) do |list|
|
create_list(:category, unordered: true) do |list|
|
||||||
list = list.where(category_id: category.id)
|
list = list.where(category_id: category.id)
|
||||||
if @user_id.present?
|
if @user_id.present?
|
||||||
list.order(TopicQuery.order_with_pinned_sql)
|
list.order(TopicQuery.order_with_pinned_sql)
|
||||||
|
@ -191,13 +187,15 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def list_new_in_category(category)
|
def list_new_in_category(category)
|
||||||
return_list {|l| l.where(category_id: category.id).by_newest.first(25)}
|
create_list(:new_in_category) {|l| l.where(category_id: category.id).by_newest.first(25)}
|
||||||
end
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def return_list(list_opts={})
|
def create_list(filter, list_opts={})
|
||||||
TopicList.new(@user, yield(default_list(list_opts)))
|
topics = default_list(list_opts)
|
||||||
|
topics = yield(topics) if block_given?
|
||||||
|
TopicList.new(filter, @user, topics)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Create a list based on a bunch of detault options
|
# Create a list based on a bunch of detault options
|
||||||
|
@ -233,7 +231,6 @@ class TopicQuery
|
||||||
end
|
end
|
||||||
|
|
||||||
def new_results(list_opts={})
|
def new_results(list_opts={})
|
||||||
|
|
||||||
default_list(list_opts)
|
default_list(list_opts)
|
||||||
.where("topics.created_at >= :created_at", created_at: @user.treat_as_new_topic_start_date)
|
.where("topics.created_at >= :created_at", created_at: @user.treat_as_new_topic_start_date)
|
||||||
.where("tu.last_read_post_number IS NULL")
|
.where("tu.last_read_post_number IS NULL")
|
||||||
|
@ -252,12 +249,10 @@ class TopicQuery
|
||||||
.where(closed: false, archived: false, visible: true)
|
.where(closed: false, archived: false, visible: true)
|
||||||
|
|
||||||
if topic.category_id.present?
|
if topic.category_id.present?
|
||||||
results = results.order("CASE WHEN topics.category_id = #{topic.category_id.to_i} THEN 0 ELSE 1 END, RANDOM()")
|
return results.order("CASE WHEN topics.category_id = #{topic.category_id.to_i} THEN 0 ELSE 1 END, RANDOM()")
|
||||||
else
|
|
||||||
results = results.order("RANDOM()")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
results
|
results.order("RANDOM()")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue