mirror of
https://github.com/codeninjasllc/discourse.git
synced 2025-04-02 10:09:51 -04:00
FEATURE: make pin expiration mandatory
This commit is contained in:
parent
9e2632badd
commit
faf4f44776
18 changed files with 192 additions and 97 deletions
app
assets
javascripts/discourse
components
controllers
models
routes
templates/modal
stylesheets/common/base
controllers
jobs
models
serializers
config/locales
db/migrate
spec/controllers
|
@ -4,7 +4,9 @@ const icons = {
|
|||
'archived.enabled': 'folder',
|
||||
'archived.disabled': 'folder-open',
|
||||
'pinned.enabled': 'thumb-tack',
|
||||
'pinned.disabled': 'thumb-tack',
|
||||
'pinned.disabled': 'thumb-tack unpinned',
|
||||
'pinned_globally.enabled': 'thumb-tack',
|
||||
'pinned_globally.disabled': 'thumb-tack unpinned',
|
||||
'visible.enabled': 'eye',
|
||||
'visible.disabled': 'eye-slash'
|
||||
};
|
||||
|
|
|
@ -10,15 +10,23 @@ export default ObjectController.extend(ModalFunctionality, {
|
|||
pinnedGloballyCount: 0,
|
||||
bannerCount: 0,
|
||||
|
||||
reset: function() {
|
||||
this.set("model.pinnedInCategoryUntil", null);
|
||||
this.set("model.pinnedGloballyUntil", null);
|
||||
},
|
||||
|
||||
categoryLink: function() {
|
||||
return categoryLinkHTML(this.get("model.category"), { allowUncategorized: true });
|
||||
}.property("model.category"),
|
||||
|
||||
unPinMessage: function() {
|
||||
return this.get("model.pinned_globally") ?
|
||||
I18n.t("topic.feature_topic.unpin_globally") :
|
||||
I18n.t("topic.feature_topic.unpin", { categoryLink: this.get("categoryLink") });
|
||||
}.property("categoryLink", "model.pinned_globally"),
|
||||
let name = "topic.feature_topic.unpin";
|
||||
if (this.get("model.pinned_globally")) name += "_globally";
|
||||
if (moment(this.get("model.pinned_until")) > moment()) name += "_until";
|
||||
const until = moment(this.get("model.pinned_until")).format("LL");
|
||||
|
||||
return I18n.t(name, { categoryLink: this.get("categoryLink"), until: until });
|
||||
}.property("categoryLink", "model.{pinned_globally,pinned_until}"),
|
||||
|
||||
pinMessage: function() {
|
||||
return I18n.t("topic.feature_topic.pin", { categoryLink: this.get("categoryLink") });
|
||||
|
@ -28,6 +36,30 @@ export default ObjectController.extend(ModalFunctionality, {
|
|||
return I18n.t("topic.feature_topic.already_pinned", { categoryLink: this.get("categoryLink"), count: this.get("pinnedInCategoryCount") });
|
||||
}.property("categoryLink", "pinnedInCategoryCount"),
|
||||
|
||||
pinDisabled: function() {
|
||||
return !this._isDateValid(this.get("parsedPinnedInCategoryUntil"));
|
||||
}.property("parsedPinnedInCategoryUntil"),
|
||||
|
||||
pinGloballyDisabled: function() {
|
||||
return !this._isDateValid(this.get("parsedPinnedGloballyUntil"));
|
||||
}.property("pinnedGloballyUntil"),
|
||||
|
||||
parsedPinnedInCategoryUntil: function() {
|
||||
return this._parseDate(this.get("model.pinnedInCategoryUntil"));
|
||||
}.property("model.pinnedInCategoryUntil"),
|
||||
|
||||
parsedPinnedGloballyUntil: function() {
|
||||
return this._parseDate(this.get("model.pinnedGloballyUntil"));
|
||||
}.property("model.pinnedGloballyUntil"),
|
||||
|
||||
_parseDate(date) {
|
||||
return moment(date, ["YYYY-MM-DD", "YYYY-MM-DD HH:mm"]);
|
||||
},
|
||||
|
||||
_isDateValid(parsedDate) {
|
||||
return parsedDate.isValid() && parsedDate > moment();
|
||||
},
|
||||
|
||||
onShow() {
|
||||
this.set("loading", true);
|
||||
|
||||
|
|
|
@ -99,19 +99,6 @@ export default ObjectController.extend(SelectedPostsCount, BufferedContent, {
|
|||
this.set('selectedReplies', []);
|
||||
}.on('init'),
|
||||
|
||||
_togglePinnedStates(property) {
|
||||
const value = this.get('model.pinned_at') ? false : true,
|
||||
topic = this.get('content');
|
||||
|
||||
// optimistic update
|
||||
topic.setProperties({
|
||||
pinned_at: value,
|
||||
pinned_globally: value
|
||||
});
|
||||
|
||||
return topic.saveStatus(property, value);
|
||||
},
|
||||
|
||||
actions: {
|
||||
deleteTopic() {
|
||||
this.deleteTopic();
|
||||
|
@ -371,27 +358,31 @@ export default ObjectController.extend(SelectedPostsCount, BufferedContent, {
|
|||
|
||||
togglePinned() {
|
||||
const value = this.get('model.pinned_at') ? false : true,
|
||||
topic = this.get('content');
|
||||
topic = this.get('content'),
|
||||
until = this.get('model.pinnedInCategoryUntil');
|
||||
|
||||
// optimistic update
|
||||
topic.setProperties({
|
||||
pinned_at: value ? moment() : null,
|
||||
pinned_globally: false
|
||||
pinned_globally: false,
|
||||
pinned_until: value ? until : null
|
||||
});
|
||||
|
||||
return topic.saveStatus("pinned", value);
|
||||
return topic.saveStatus("pinned", value, until);
|
||||
},
|
||||
|
||||
pinGlobally() {
|
||||
const topic = this.get('content');
|
||||
const topic = this.get('content'),
|
||||
until = this.get('model.pinnedGloballyUntil');
|
||||
|
||||
// optimistic update
|
||||
topic.setProperties({
|
||||
pinned_at: moment(),
|
||||
pinned_globally: true
|
||||
pinned_globally: true,
|
||||
pinned_until: until
|
||||
});
|
||||
|
||||
return topic.saveStatus("pinned_globally", true);
|
||||
return topic.saveStatus("pinned_globally", true, until);
|
||||
},
|
||||
|
||||
toggleArchived() {
|
||||
|
|
|
@ -154,13 +154,17 @@ const Topic = RestModel.extend({
|
|||
this.saveStatus(property, !!this.get(property));
|
||||
},
|
||||
|
||||
saveStatus(property, value) {
|
||||
saveStatus(property, value, until) {
|
||||
if (property === 'closed' && value === true) {
|
||||
this.set('details.auto_close_at', null);
|
||||
}
|
||||
return Discourse.ajax(this.get('url') + "/status", {
|
||||
type: 'PUT',
|
||||
data: { status: property, enabled: !!value }
|
||||
data: {
|
||||
status: property,
|
||||
enabled: !!value,
|
||||
until: until
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@ const TopicRoute = Discourse.Route.extend(ShowFooter, {
|
|||
showFeatureTopic() {
|
||||
showModal('featureTopic', { model: this.modelFor('topic'), title: 'topic.feature_topic.title' });
|
||||
this.controllerFor('modal').set('modalClass', 'feature-topic-modal');
|
||||
this.controllerFor('feature_topic').reset();
|
||||
},
|
||||
|
||||
showInvite() {
|
||||
|
|
|
@ -1,80 +1,94 @@
|
|||
<div class="modal-body feature-topic">
|
||||
{{#if model.pinned_at}}
|
||||
<div class="feature-section">
|
||||
<div class="button">
|
||||
{{d-button action="unpin" icon="thumb-tack" label="topic.feature.unpin" class="btn-primary"}}
|
||||
</div>
|
||||
<div class="desc">
|
||||
<p>{{{unPinMessage}}}</p>
|
||||
{{#if model.pinned_globally}}
|
||||
<p>{{i18n "topic.feature_topic.global_pin_note"}}</p>
|
||||
<p>
|
||||
{{#conditional-loading-spinner size="small" condition=loading}}
|
||||
{{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
|
||||
{{/conditional-loading-spinner}}
|
||||
</p>
|
||||
<p>{{i18n "topic.feature_topic.global_pin_note"}}</p>
|
||||
{{else}}
|
||||
<p>{{i18n "topic.feature_topic.pin_note"}}</p>
|
||||
<p>
|
||||
{{#conditional-loading-spinner size="small" condition=loading}}
|
||||
{{{alreadyPinnedMessage}}}
|
||||
{{/conditional-loading-spinner}}
|
||||
</p>
|
||||
<p>{{i18n "topic.feature_topic.pin_note"}}</p>
|
||||
{{/if}}
|
||||
<p>{{{unPinMessage}}}</p>
|
||||
<p>{{d-button action="unpin" icon="thumb-tack" label="topic.feature.unpin" class="btn-primary"}}</p>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="feature-section">
|
||||
<div class="button">
|
||||
{{d-button action="pin" icon="thumb-tack" label="topic.feature.pin" class="btn-primary"}}
|
||||
</div>
|
||||
<div class="desc">
|
||||
<p>{{{pinMessage}}}</p>
|
||||
<p>{{i18n "topic.feature_topic.pin_note"}}</p>
|
||||
<p>
|
||||
{{#conditional-loading-spinner size="small" condition=loading}}
|
||||
{{{alreadyPinnedMessage}}}
|
||||
{{/conditional-loading-spinner}}
|
||||
</p>
|
||||
<p>
|
||||
{{i18n "topic.feature_topic.pin_note"}}
|
||||
</p>
|
||||
<p>
|
||||
{{{pinMessage}}}
|
||||
{{fa-icon "clock-o"}}
|
||||
{{input type="date" value=model.pinnedInCategoryUntil}}
|
||||
</p>
|
||||
<p>
|
||||
{{d-button action="pin" icon="thumb-tack" label="topic.feature.pin" class="btn-primary" disabled=pinDisabled}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="feature-section">
|
||||
<div class="button">
|
||||
{{d-button action="pinGlobally" icon="thumb-tack" label="topic.feature.pin_globally" class="btn-primary"}}
|
||||
</div>
|
||||
<div class="desc">
|
||||
<p>{{i18n "topic.feature_topic.pin_globally"}}</p>
|
||||
<p>{{i18n "topic.feature_topic.global_pin_note"}}</p>
|
||||
<p>
|
||||
{{#conditional-loading-spinner size="small" condition=loading}}
|
||||
{{{i18n "topic.feature_topic.already_pinned_globally" count=pinnedGloballyCount}}}
|
||||
{{/conditional-loading-spinner}}
|
||||
</p>
|
||||
<p>
|
||||
{{i18n "topic.feature_topic.global_pin_note"}}
|
||||
</p>
|
||||
<p>
|
||||
{{i18n "topic.feature_topic.pin_globally"}}
|
||||
{{fa-icon "clock-o"}}
|
||||
{{input type="date" value=model.pinnedGloballyUntil}}
|
||||
</p>
|
||||
<p>
|
||||
{{d-button action="pinGlobally" icon="thumb-tack" label="topic.feature.pin_globally" class="btn-primary" disabled=pinGloballyDisabled}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
<hr>
|
||||
<div class="feature-section">
|
||||
<div class="button">
|
||||
{{#if model.isBanner}}
|
||||
{{d-button action="removeBanner" icon="thumb-tack" label="topic.feature.remove_banner" class="btn-primary"}}
|
||||
{{else}}
|
||||
{{d-button action="makeBanner" icon="thumb-tack" label="topic.feature.make_banner" class="btn-primary"}}
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="desc">
|
||||
{{#if model.isBanner}}
|
||||
<p>{{i18n "topic.feature_topic.remove_banner"}}</p>
|
||||
{{else}}
|
||||
<p>{{i18n "topic.feature_topic.make_banner"}}</p>
|
||||
{{/if}}
|
||||
<p>{{i18n "topic.feature_topic.banner_note"}}</p>
|
||||
<p>
|
||||
{{#conditional-loading-spinner size="small" condition=loading}}
|
||||
{{{i18n "topic.feature_topic.already_banner" count=bannerCount}}}
|
||||
{{/conditional-loading-spinner}}
|
||||
</p>
|
||||
<p>
|
||||
{{i18n "topic.feature_topic.banner_note"}}
|
||||
</p>
|
||||
<p>
|
||||
{{#if model.isBanner}}
|
||||
{{i18n "topic.feature_topic.remove_banner"}}
|
||||
{{else}}
|
||||
{{i18n "topic.feature_topic.make_banner"}}
|
||||
{{/if}}
|
||||
</p>
|
||||
<p>
|
||||
{{#if model.isBanner}}
|
||||
{{d-button action="removeBanner" icon="thumb-tack" label="topic.feature.remove_banner" class="btn-primary"}}
|
||||
{{else}}
|
||||
{{d-button action="makeBanner" icon="thumb-tack" label="topic.feature.make_banner" class="btn-primary"}}
|
||||
{{/if}}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -30,30 +30,36 @@
|
|||
}
|
||||
}
|
||||
|
||||
.modal-body.feature-topic .feature-section {
|
||||
display: block;
|
||||
.button {
|
||||
width: 33%;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
margin-top: 15px;
|
||||
.modal-body.feature-topic {
|
||||
padding: 5px;
|
||||
max-height: 500px;
|
||||
hr {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.desc {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
max-width: 60%;
|
||||
margin-left: 10px;
|
||||
p {
|
||||
margin: 10px 0;
|
||||
.feature-section {
|
||||
display: block;
|
||||
.badge-wrapper {
|
||||
margin-right: 0;
|
||||
}
|
||||
input[type="date"] {
|
||||
width: 120px;
|
||||
margin: 0;
|
||||
}
|
||||
.desc {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
margin-left: 10px;
|
||||
p:first-of-type {
|
||||
margin: 0;
|
||||
}
|
||||
p {
|
||||
margin: 10px 0 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.mobile-view .feature-topic .feature-section {
|
||||
.button {
|
||||
width: auto;
|
||||
display: block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
.desc {
|
||||
display: block;
|
||||
clear: both;
|
||||
|
|
|
@ -165,13 +165,16 @@ class TopicsController < ApplicationController
|
|||
def status
|
||||
params.require(:status)
|
||||
params.require(:enabled)
|
||||
status, topic_id = params[:status], params[:topic_id].to_i
|
||||
enabled = (params[:enabled] == 'true')
|
||||
params.permit(:until)
|
||||
|
||||
status = params[:status]
|
||||
topic_id = params[:topic_id].to_i
|
||||
enabled = params[:enabled] == 'true'
|
||||
|
||||
check_for_status_presence(:status, status)
|
||||
@topic = Topic.find_by(id: topic_id)
|
||||
guardian.ensure_can_moderate!(@topic)
|
||||
@topic.update_status(status, enabled, current_user)
|
||||
@topic.update_status(status, enabled, current_user, until: params[:until])
|
||||
render nothing: true
|
||||
end
|
||||
|
||||
|
|
|
@ -227,7 +227,8 @@ module Jobs
|
|||
end
|
||||
|
||||
def self.enqueue_at(datetime, job_name, opts={})
|
||||
enqueue_in( [(datetime - Time.zone.now).to_i, 0].max, job_name, opts )
|
||||
secs = [(datetime - Time.zone.now).to_i, 0].max
|
||||
enqueue_in(secs, job_name, opts)
|
||||
end
|
||||
|
||||
def self.cancel_scheduled_job(job_name, params={})
|
||||
|
|
16
app/jobs/regular/unpin_topic.rb
Normal file
16
app/jobs/regular/unpin_topic.rb
Normal file
|
@ -0,0 +1,16 @@
|
|||
module Jobs
|
||||
|
||||
class UnpinTopic < Jobs::Base
|
||||
|
||||
def execute(args)
|
||||
topic_id = args[:topic_id]
|
||||
|
||||
raise Discourse::InvalidParameters.new(:topic_id) unless topic_id.present?
|
||||
|
||||
topic = Topic.find_by(id: topic_id)
|
||||
topic.update_pinned(false) if topic.present?
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
|
@ -11,6 +11,7 @@ module Jobs
|
|||
TopicFeaturedUsers.ensure_consistency!
|
||||
PostRevision.ensure_consistency!
|
||||
UserStat.update_view_counts(13.hours.ago)
|
||||
Topic.ensure_consistency!
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -465,7 +465,7 @@ SQL
|
|||
|
||||
# the threshold has been reached, we will close the topic waiting for intervention
|
||||
message = I18n.t("temporarily_closed_due_to_flags")
|
||||
topic.update_status("closed", true, Discourse.system_user, message)
|
||||
topic.update_status("closed", true, Discourse.system_user, message: message)
|
||||
end
|
||||
|
||||
def self.auto_hide_if_needed(acting_user, post, post_action_type)
|
||||
|
|
|
@ -406,8 +406,8 @@ class Topic < ActiveRecord::Base
|
|||
similar
|
||||
end
|
||||
|
||||
def update_status(status, enabled, user, message=nil)
|
||||
TopicStatusUpdate.new(self, user).update!(status, enabled, message)
|
||||
def update_status(status, enabled, user, opts={})
|
||||
TopicStatusUpdate.new(self, user).update!(status, enabled, opts)
|
||||
end
|
||||
|
||||
# Atomically creates the next post number
|
||||
|
@ -726,9 +726,17 @@ class Topic < ActiveRecord::Base
|
|||
TopicUser.change(user.id, id, cleared_pinned_at: nil)
|
||||
end
|
||||
|
||||
def update_pinned(status, global=false)
|
||||
update_column(:pinned_at, status ? Time.now : nil)
|
||||
update_column(:pinned_globally, global)
|
||||
def update_pinned(status, global=false, pinned_until=nil)
|
||||
pinned_until = Time.parse(pinned_until) rescue nil
|
||||
|
||||
update_columns(
|
||||
pinned_at: status ? Time.now : nil,
|
||||
pinned_globally: global,
|
||||
pinned_until: pinned_until
|
||||
)
|
||||
|
||||
Jobs.cancel_scheduled_job(:unpin_topic, topic_id: self.id)
|
||||
Jobs.enqueue_at(pinned_until, :unpin_topic, topic_id: self.id) if pinned_until
|
||||
end
|
||||
|
||||
def draft_key
|
||||
|
@ -745,6 +753,11 @@ class Topic < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def self.ensure_consistency!
|
||||
# unpin topics that might have been missed
|
||||
Topic.where("pinned_until < now()").update_all(pinned_at: nil, pinned_globally: false, pinned_until: nil)
|
||||
end
|
||||
|
||||
def self.auto_close
|
||||
Topic.where("NOT closed AND auto_close_at < ? AND auto_close_user_id IS NOT NULL", 1.minute.ago).each do |t|
|
||||
t.auto_close
|
||||
|
|
|
@ -1,21 +1,20 @@
|
|||
TopicStatusUpdate = Struct.new(:topic, :user) do
|
||||
def update!(status, enabled, message=nil)
|
||||
def update!(status, enabled, opts={})
|
||||
status = Status.new(status, enabled)
|
||||
|
||||
Topic.transaction do
|
||||
change(status)
|
||||
change(status, opts)
|
||||
highest_post_number = topic.highest_post_number
|
||||
|
||||
create_moderator_post_for(status, message)
|
||||
create_moderator_post_for(status, opts[:message])
|
||||
update_read_state_for(status, highest_post_number)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def change(status)
|
||||
def change(status, opts={})
|
||||
if status.pinned? || status.pinned_globally?
|
||||
topic.update_pinned(status.enabled?, status.pinned_globally?)
|
||||
topic.update_pinned(status.enabled?, status.pinned_globally?, opts[:until])
|
||||
elsif status.autoclosed?
|
||||
topic.update_column('closed', status.enabled?)
|
||||
else
|
||||
|
|
|
@ -43,6 +43,7 @@ class TopicViewSerializer < ApplicationSerializer
|
|||
:pinned_globally,
|
||||
:pinned, # Is topic pinned and viewer hasn't cleared the pin?
|
||||
:pinned_at, # Ignores clear pin
|
||||
:pinned_until,
|
||||
:details,
|
||||
:highest_post_number,
|
||||
:last_read_post_number,
|
||||
|
@ -177,6 +178,10 @@ class TopicViewSerializer < ApplicationSerializer
|
|||
object.topic.pinned_at
|
||||
end
|
||||
|
||||
def pinned_until
|
||||
object.topic.pinned_until
|
||||
end
|
||||
|
||||
def actions_summary
|
||||
result = []
|
||||
return [] unless post = object.posts.try(:first)
|
||||
|
|
|
@ -130,11 +130,11 @@ en:
|
|||
enabled: 'pinned this topic %{when}'
|
||||
disabled: 'unpinned this topic %{when}'
|
||||
pinned_globally:
|
||||
enabled: 'pinned this topic %{when}'
|
||||
enabled: 'pinned globally this topic %{when}'
|
||||
disabled: 'unpinned this topic %{when}'
|
||||
visible:
|
||||
enabled: 'unlisted this topic %{when}'
|
||||
disabled: 'listed this topic %{when}'
|
||||
enabled: 'listed this topic %{when}'
|
||||
disabled: 'unlisted this topic %{when}'
|
||||
|
||||
topic_admin_menu: "topic admin actions"
|
||||
|
||||
|
@ -1131,17 +1131,19 @@ en:
|
|||
|
||||
feature_topic:
|
||||
title: "Feature this topic"
|
||||
pin: "Make this topic appear at the top of the {{categoryLink}} category."
|
||||
pin: "Make this topic appear at the top of the {{categoryLink}} category until"
|
||||
confirm_pin: "You already have {{count}} pinned topics. Too many pinned topics may be a burden for new and anonymous users. Are you sure you want to pin another topic in this category?"
|
||||
unpin: "Remove this topic from the top of the {{categoryLink}} category."
|
||||
unpin_until: "Remove this topic from the top of the {{categoryLink}} category or wait until <strong>%{until}</strong>."
|
||||
pin_note: "Users can unpin the topic individually for themselves."
|
||||
already_pinned:
|
||||
zero: "There are no topics pinned in {{categoryLink}}."
|
||||
one: "Topics currently pinned in {{categoryLink}}: <strong class='badge badge-notification unread'>1</strong>."
|
||||
other: "Topics currently pinned in {{categoryLink}}: <strong class='badge badge-notification unread'>{{count}}</strong>."
|
||||
pin_globally: "Make this topic appear at the top of all topic lists, until a staff member unpins it."
|
||||
pin_globally: "Make this topic appear at the top of all topic lists until"
|
||||
confirm_pin_globally: "You already have {{count}} globally pinned topics. Too many pinned topics may be a burden for new and anonymous users. Are you sure you want to pin another topic globally?"
|
||||
unpin_globally: "Remove this topic from the top of all topic lists."
|
||||
unpin_globally_until: "Remove this topic from the top of all topic lists or wait until <strong>%{until}</strong>."
|
||||
global_pin_note: "Users can unpin the topic individually for themselves."
|
||||
already_pinned_globally:
|
||||
zero: "There are no topics pinned globally."
|
||||
|
|
5
db/migrate/20150727210019_add_pinned_until_to_topics.rb
Normal file
5
db/migrate/20150727210019_add_pinned_until_to_topics.rb
Normal file
|
@ -0,0 +1,5 @@
|
|||
class AddPinnedUntilToTopics < ActiveRecord::Migration
|
||||
def change
|
||||
add_column :topics, :pinned_until, :datetime, null: true
|
||||
end
|
||||
end
|
|
@ -324,12 +324,12 @@ describe TopicsController do
|
|||
end
|
||||
|
||||
it 'calls update_status on the forum topic with false' do
|
||||
Topic.any_instance.expects(:update_status).with('closed', false, @user)
|
||||
Topic.any_instance.expects(:update_status).with('closed', false, @user, until: nil)
|
||||
xhr :put, :status, topic_id: @topic.id, status: 'closed', enabled: 'false'
|
||||
end
|
||||
|
||||
it 'calls update_status on the forum topic with true' do
|
||||
Topic.any_instance.expects(:update_status).with('closed', true, @user)
|
||||
Topic.any_instance.expects(:update_status).with('closed', true, @user, until: nil)
|
||||
xhr :put, :status, topic_id: @topic.id, status: 'closed', enabled: 'true'
|
||||
end
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue