FEATURE: allow moderators to globally pin topics
This commit is contained in:
parent
ae3b2a6e02
commit
0372b81d11
10 changed files with 31 additions and 7 deletions
app
assets/javascripts/discourse
controllers
models
config/locales
db/migrate
lib
spec/components
|
@ -167,6 +167,11 @@ Discourse.TopicController = Discourse.ObjectController.extend(Discourse.Selected
|
||||||
this.get('content').setStatus('pinned', this.get('pinned_at') ? false : true);
|
this.get('content').setStatus('pinned', this.get('pinned_at') ? false : true);
|
||||||
},
|
},
|
||||||
|
|
||||||
|
togglePinnedGlobally: function() {
|
||||||
|
// Note that this is different than clearPin
|
||||||
|
this.get('content').setStatus('pinned_globally', this.get('pinned_at') ? false : true);
|
||||||
|
},
|
||||||
|
|
||||||
toggleArchived: function() {
|
toggleArchived: function() {
|
||||||
this.get('content').toggleStatus('archived');
|
this.get('content').toggleStatus('archived');
|
||||||
},
|
},
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
<button {{action togglePinned}} class='btn btn-admin'><i class='fa fa-thumb-tack'></i> {{i18n topic.actions.unpin}}</button>
|
<button {{action togglePinned}} class='btn btn-admin'><i class='fa fa-thumb-tack'></i> {{i18n topic.actions.unpin}}</button>
|
||||||
{{else}}
|
{{else}}
|
||||||
<button {{action togglePinned}} class='btn btn-admin'><i class='fa fa-thumb-tack'></i> {{i18n topic.actions.pin}}</button>
|
<button {{action togglePinned}} class='btn btn-admin'><i class='fa fa-thumb-tack'></i> {{i18n topic.actions.pin}}</button>
|
||||||
|
<button {{action togglePinnedGlobally}} class='btn btn-admin'><i class='fa fa-thumb-tack'></i> {{i18n topic.actions.pin_globally}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
|
@ -365,7 +365,7 @@ class TopicsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def check_for_status_presence(key, attr)
|
def check_for_status_presence(key, attr)
|
||||||
invalid_param(key) unless %w(visible closed pinned archived).include?(attr)
|
invalid_param(key) unless %w(pinned_globally visible closed pinned archived).include?(attr)
|
||||||
end
|
end
|
||||||
|
|
||||||
def invalid_param(key)
|
def invalid_param(key)
|
||||||
|
|
|
@ -618,8 +618,9 @@ class Topic < ActiveRecord::Base
|
||||||
TopicUser.change(user.id, id, cleared_pinned_at: Time.now)
|
TopicUser.change(user.id, id, cleared_pinned_at: Time.now)
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_pinned(status)
|
def update_pinned(status, global=false)
|
||||||
update_column(:pinned_at, status ? Time.now : nil)
|
update_column(:pinned_at, status ? Time.now : nil)
|
||||||
|
update_column(:pinned_globally, global)
|
||||||
end
|
end
|
||||||
|
|
||||||
def draft_key
|
def draft_key
|
||||||
|
|
|
@ -14,8 +14,8 @@ TopicStatusUpdate = Struct.new(:topic, :user) do
|
||||||
private
|
private
|
||||||
|
|
||||||
def change(status)
|
def change(status)
|
||||||
if status.pinned?
|
if status.pinned? || status.pinned_globally?
|
||||||
topic.update_pinned status.enabled?
|
topic.update_pinned status.enabled?, status.pinned_globally?
|
||||||
elsif status.autoclosed?
|
elsif status.autoclosed?
|
||||||
topic.update_column 'closed', status.enabled?
|
topic.update_column 'closed', status.enabled?
|
||||||
else
|
else
|
||||||
|
@ -67,7 +67,7 @@ TopicStatusUpdate = Struct.new(:topic, :user) do
|
||||||
end
|
end
|
||||||
|
|
||||||
Status = Struct.new(:name, :enabled) do
|
Status = Struct.new(:name, :enabled) do
|
||||||
%w(pinned autoclosed closed).each do |status|
|
%w(pinned_globally pinned autoclosed closed).each do |status|
|
||||||
define_method("#{status}?") { name == status }
|
define_method("#{status}?") { name == status }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -796,6 +796,7 @@ en:
|
||||||
auto_close: "Auto Close"
|
auto_close: "Auto Close"
|
||||||
unpin: "Un-Pin Topic"
|
unpin: "Un-Pin Topic"
|
||||||
pin: "Pin Topic"
|
pin: "Pin Topic"
|
||||||
|
pin_globally: "Pin Topic Globally"
|
||||||
unarchive: "Unarchive Topic"
|
unarchive: "Unarchive Topic"
|
||||||
archive: "Archive Topic"
|
archive: "Archive Topic"
|
||||||
invisible: "Make Invisible"
|
invisible: "Make Invisible"
|
||||||
|
|
|
@ -930,6 +930,9 @@ en:
|
||||||
autoclosed_disabled: "This topic is now opened. New replies are allowed."
|
autoclosed_disabled: "This topic is now opened. New replies are allowed."
|
||||||
pinned_enabled: "This topic is now pinned. It will appear at the top of its category until it is either unpinned by a moderator, or the Clear Pin button is pressed."
|
pinned_enabled: "This topic is now pinned. It will appear at the top of its category until it is either unpinned by a moderator, or the Clear Pin button is pressed."
|
||||||
pinned_disabled: "This topic is now unpinned. It will no longer appear at the top of its category."
|
pinned_disabled: "This topic is now unpinned. It will no longer appear at the top of its category."
|
||||||
|
|
||||||
|
pinned_globally_enabled: "This topic is now pinned globally. It will appear at the top of its category and all topic lists until it is either unpinned by a moderator, or the Clear Pin button is pressed."
|
||||||
|
pinned_globally_disabled: "This topic is now unpinned. It will no longer appear at the top of its category."
|
||||||
visible_enabled: "This topic is now visible. It will be displayed in topic lists."
|
visible_enabled: "This topic is now visible. It will be displayed in topic lists."
|
||||||
visible_disabled: "This topic is now invisible. It will no longer be displayed in any topic lists. The only way to access this topic is via direct link."
|
visible_disabled: "This topic is now invisible. It will no longer be displayed in any topic lists. The only way to access this topic is via direct link."
|
||||||
|
|
||||||
|
|
12
db/migrate/20140407055830_add_pinned_globally_to_topics.rb
Normal file
12
db/migrate/20140407055830_add_pinned_globally_to_topics.rb
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
class AddPinnedGloballyToTopics < ActiveRecord::Migration
|
||||||
|
def up
|
||||||
|
add_column :topics, :pinned_globally, :boolean, null: false, default: false
|
||||||
|
execute "UPDATE topics set pinned_globally = 't' where category_id = (
|
||||||
|
SELECT value::int FROM site_settings WHERE name = 'uncategorized_category_id') AND pinned_at IS NOT NULL
|
||||||
|
"
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_column :topics, :pinned_globally
|
||||||
|
end
|
||||||
|
end
|
|
@ -31,7 +31,7 @@ module TopicQuerySQL
|
||||||
# If you've clearned the pin, use bumped_at, otherwise put it at the top
|
# If you've clearned the pin, use bumped_at, otherwise put it at the top
|
||||||
def order_nocategory_with_pinned_sql
|
def order_nocategory_with_pinned_sql
|
||||||
"CASE
|
"CASE
|
||||||
WHEN topics.category_id = #{SiteSetting.uncategorized_category_id.to_i} and (COALESCE(topics.pinned_at, '#{lowest_date}') > COALESCE(tu.cleared_pinned_at, '#{lowest_date}'))
|
WHEN topics.pinned_globally and (COALESCE(topics.pinned_at, '#{lowest_date}') > COALESCE(tu.cleared_pinned_at, '#{lowest_date}'))
|
||||||
THEN '#{highest_date}'
|
THEN '#{highest_date}'
|
||||||
ELSE topics.bumped_at
|
ELSE topics.bumped_at
|
||||||
END DESC"
|
END DESC"
|
||||||
|
@ -42,7 +42,7 @@ module TopicQuerySQL
|
||||||
end
|
end
|
||||||
|
|
||||||
def order_nocategory_basic_bumped
|
def order_nocategory_basic_bumped
|
||||||
"CASE WHEN topics.category_id = #{SiteSetting.uncategorized_category_id.to_i} and (topics.pinned_at IS NOT NULL) THEN 0 ELSE 1 END, topics.bumped_at DESC"
|
"CASE WHEN topics.pinned_globally and (topics.pinned_at IS NOT NULL) THEN 0 ELSE 1 END, topics.bumped_at DESC"
|
||||||
end
|
end
|
||||||
|
|
||||||
def order_top_for(score)
|
def order_top_for(score)
|
||||||
|
|
|
@ -101,6 +101,7 @@ describe TopicQuery do
|
||||||
posts_count: 5,
|
posts_count: 5,
|
||||||
participant_count: 12,
|
participant_count: 12,
|
||||||
pinned_at: 10.minutes.ago,
|
pinned_at: 10.minutes.ago,
|
||||||
|
pinned_globally: true,
|
||||||
bumped_at: 10.minutes.ago)
|
bumped_at: 10.minutes.ago)
|
||||||
end
|
end
|
||||||
let!(:archived_topic) do
|
let!(:archived_topic) do
|
||||||
|
|
Reference in a new issue