rename topic_status_update to topic_timer

This commit is contained in:
Neil Lalonde 2017-05-11 18:23:18 -04:00
parent 92d63b59a7
commit 55b61e9bea
39 changed files with 297 additions and 287 deletions

View File

@ -1,6 +1,6 @@
import { default as computed, observes } from "ember-addons/ember-computed-decorators";
import Combobox from 'discourse-common/components/combo-box';
import { CLOSE_STATUS_TYPE } from 'discourse/controllers/edit-topic-status-update';
import { CLOSE_STATUS_TYPE } from 'discourse/controllers/edit-topic-timer';
const LATER_TODAY = 'later_today';
const TOMORROW = 'tomorrow';

View File

@ -1,6 +1,6 @@
import { default as computed, observes } from "ember-addons/ember-computed-decorators";
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import TopicStatusUpdate from 'discourse/models/topic-status-update';
import TopicTimer from 'discourse/models/topic-timer';
import { popupAjaxError } from 'discourse/lib/ajax-error';
export const CLOSE_STATUS_TYPE = 'close';
@ -11,8 +11,8 @@ const DELETE_STATUS_TYPE = 'delete';
export default Ember.Controller.extend(ModalFunctionality, {
loading: false,
updateTime: null,
topicStatusUpdate: Ember.computed.alias("model.topic_status_update"),
selection: Ember.computed.alias('model.topic_status_update.status_type'),
topicTimer: Ember.computed.alias("model.topic_timer"),
selection: Ember.computed.alias('model.topic_timer.status_type'),
autoOpen: Ember.computed.equal('selection', OPEN_STATUS_TYPE),
autoClose: Ember.computed.equal('selection', CLOSE_STATUS_TYPE),
autoDelete: Ember.computed.equal('selection', DELETE_STATUS_TYPE),
@ -21,7 +21,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
showTimeOnly: Ember.computed.or('autoOpen', 'autoDelete'),
@computed("model.closed")
statusUpdates(closed) {
timerTypes(closed) {
return [
{ id: CLOSE_STATUS_TYPE, name: I18n.t(closed ? 'topic.temp_open.title' : 'topic.auto_close.title'), },
{ id: OPEN_STATUS_TYPE, name: I18n.t(closed ? 'topic.auto_reopen.title' : 'topic.temp_close.title') },
@ -40,16 +40,16 @@ export default Ember.Controller.extend(ModalFunctionality, {
if (visible) return this.get('model.category_id');
},
@observes("topicStatusUpdate.execute_at", "topicStatusUpdate.duration")
@observes("topicTimer.execute_at", "topicTimer.duration")
_setUpdateTime() {
if (!this.get('topicStatusUpdate.execute_at')) return;
if (!this.get('topicTimer.execute_at')) return;
let time = null;
if (this.get("topicStatusUpdate.based_on_last_post")) {
time = this.get("topicStatusUpdate.duration");
} else if (this.get("topicStatusUpdate.execute_at")) {
const closeTime = moment(this.get('topicStatusUpdate.execute_at'));
if (this.get("topicTimer.based_on_last_post")) {
time = this.get("topicTimer.duration");
} else if (this.get("topicTimer.execute_at")) {
const closeTime = moment(this.get('topicTimer.execute_at'));
if (closeTime > moment()) {
time = closeTime.format("YYYY-MM-DD HH:mm");
@ -59,20 +59,20 @@ export default Ember.Controller.extend(ModalFunctionality, {
this.set("updateTime", time);
},
_setStatusUpdate(time, statusType) {
_setTimer(time, statusType) {
this.set('loading', true);
TopicStatusUpdate.updateStatus(
TopicTimer.updateStatus(
this.get('model.id'),
time,
this.get('topicStatusUpdate.based_on_last_post'),
this.get('topicTimer.based_on_last_post'),
statusType,
this.get('categoryId')
).then(result => {
if (time) {
this.send('closeModal');
this.get("topicStatusUpdate").setProperties({
this.get("topicTimer").setProperties({
execute_at: result.execute_at,
duration: result.duration,
category_id: result.category_id
@ -81,7 +81,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
this.set('model.closed', result.closed);
} else {
this.setProperties({
topicStatusUpdate: Ember.Object.create({}),
topicTimer: Ember.Object.create({}),
selection: null,
updateTime: null
});
@ -92,12 +92,12 @@ export default Ember.Controller.extend(ModalFunctionality, {
},
actions: {
saveStatusUpdate() {
this._setStatusUpdate(this.get("updateTime"), this.get('selection'));
saveTimer() {
this._setTimer(this.get("updateTime"), this.get('selection'));
},
removeStatusUpdate() {
this._setStatusUpdate(null, this.get('selection'));
removeTimer() {
this._setTimer(null, this.get('selection'));
}
}
});

View File

@ -1,9 +1,9 @@
import { ajax } from 'discourse/lib/ajax';
import RestModel from 'discourse/models/rest';
const TopicStatusUpdate = RestModel.extend({});
const TopicTimer = RestModel.extend({});
TopicStatusUpdate.reopenClass({
TopicTimer.reopenClass({
updateStatus(topicId, time, basedOnLastPost, statusType, categoryId) {
let data = {
time: time,
@ -15,11 +15,11 @@ TopicStatusUpdate.reopenClass({
if (categoryId) data.category_id = categoryId;
return ajax({
url: `/t/${topicId}/status_update`,
url: `/t/${topicId}/timer`,
type: 'POST',
data
});
}
});
export default TopicStatusUpdate;
export default TopicTimer;

View File

@ -52,9 +52,9 @@ const TopicRoute = Discourse.Route.extend({
showTopicStatusUpdate() {
const model = this.modelFor('topic');
model.set('topic_status_update', Ember.Object.create(model.get('topic_status_update')));
showModal('edit-topic-status-update', { model });
this.controllerFor('modal').set('modalClass', 'edit-topic-status-update-modal');
model.set('topic_timer', Ember.Object.create(model.get('topic_timer')));
showModal('edit-topic-timer', { model });
this.controllerFor('modal').set('modalClass', 'edit-topic-timer-modal');
},
showChangeTimestamp() {

View File

@ -41,7 +41,7 @@
{{#if showTopicStatusInfo}}
<div class="alert alert-info">
{{topic-status-info
{{topic-timer-info
statusType=statusType
executeAt=executeAt
basedOnLastPost=basedOnLastPost

View File

@ -1,7 +1,7 @@
<form>
{{#d-modal-body title="topic.topic_status_update.title" autoFocus="false"}}
<div class="control-group">
{{combo-box content=statusUpdates value=selection width="50%"}}
{{combo-box content=timerTypes value=selection width="50%"}}
</div>
<div>
@ -25,7 +25,7 @@
{{auto-update-input
input=updateTime
statusType=selection
basedOnLastPost=topicStatusUpdate.based_on_last_post
basedOnLastPost=topicTimer.based_on_last_post
lastPostedAt=model.last_posted_at}}
{{/if}}
</div>
@ -35,14 +35,14 @@
{{d-button class="btn-primary"
disabled=saveDisabled
label="topic.topic_status_update.save"
action="saveStatusUpdate"}}
action="saveTimer"}}
<a {{action "closeModal"}}>{{i18n 'cancel'}}</a>
{{conditional-loading-spinner size="small" condition=loading}}
{{#if topicStatusUpdate.execute_at}}
{{#if topicTimer.execute_at}}
{{d-button class="pull-right btn-danger"
action="removeStatusUpdate"
action="removeTimer"
label='topic.topic_status_update.remove'}}
{{/if}}
</div>

View File

@ -174,12 +174,12 @@
{{#conditional-loading-spinner condition=model.postStream.loadingFilter}}
{{#if loadedAllPosts}}
{{topic-status-info
statusType=model.topic_status_update.status_type
executeAt=model.topic_status_update.execute_at
basedOnLastPost=model.topic_status_update.based_on_last_post
duration=model.topic_status_update.duration
categoryId=model.topic_status_update.category_id}}
{{topic-timer-info
statusType=model.topic_timer.status_type
executeAt=model.topic_timer.execute_at
basedOnLastPost=model.topic_timer.based_on_last_post
duration=model.topic_timer.duration
categoryId=model.topic_timer.category_id}}
{{#if session.showSignupCta}}
{{! replace "Log In to Reply" with the infobox }}

View File

@ -1,4 +1,4 @@
.edit-topic-status-update-modal {
.edit-topic-timer-modal {
.modal-body {
max-height: none;
}

View File

@ -22,6 +22,7 @@ class TopicsController < ApplicationController
:clear_pin,
:re_pin,
:status_update,
:timer,
:bulk,
:reset_new,
:change_post_owners,
@ -275,8 +276,8 @@ class TopicsController < ApplicationController
@topic.update_status(status, enabled, current_user, until: params[:until])
render json: success_json.merge!(
topic_status_update: TopicStatusUpdateSerializer.new(
TopicStatusUpdate.find_by(topic: @topic), root: false
topic_status_update: TopicTimerSerializer.new(
TopicTimer.find_by(topic: @topic), root: false
)
)
end
@ -289,13 +290,13 @@ class TopicsController < ApplicationController
toggle_mute
end
def status_update
def timer
params.permit(:time, :timezone_offset, :based_on_last_post, :category_id)
params.require(:status_type)
status_type =
begin
TopicStatusUpdate.types.fetch(params[:status_type].to_sym)
TopicTimer.types.fetch(params[:status_type].to_sym)
rescue
invalid_param(:status_type)
end
@ -311,7 +312,7 @@ class TopicsController < ApplicationController
options.merge!(category_id: params[:category_id]) if !params[:category_id].blank?
topic_status_update = topic.set_or_create_status_update(
topic_status_update = topic.set_or_create_timer(
status_type,
params[:time],
options

View File

@ -2,20 +2,19 @@ module Jobs
class DeleteTopic < Jobs::Base
def execute(args)
topic_status_update = TopicStatusUpdate.find_by(id: args[:topic_status_update_id])
topic_timer = TopicTimer.find_by(id: args[:topic_timer_id] || args[:topic_status_update_id])
topic = topic_status_update&.topic
topic = topic_timer&.topic
if topic_status_update.blank? || topic.blank? ||
topic_status_update.execute_at > Time.zone.now
if topic_timer.blank? || topic.blank? || topic_timer.execute_at > Time.zone.now
return
end
if Guardian.new(topic_status_update.user).can_delete?(topic)
if Guardian.new(topic_timer.user).can_delete?(topic)
first_post = topic.ordered_posts.first
PostDestroyer.new(topic_status_update.user, first_post, { context: I18n.t("topic_statuses.auto_deleted_by_timer") }).destroy
PostDestroyer.new(topic_timer.user, first_post, { context: I18n.t("topic_statuses.auto_deleted_by_timer") }).destroy
end
end
end
end
end

View File

@ -1,22 +1,22 @@
module Jobs
class PublishTopicToCategory < Jobs::Base
def execute(args)
topic_status_update = TopicStatusUpdate.find_by(id: args[:topic_status_update_id])
raise Discourse::InvalidParameters.new(:topic_status_update_id) if topic_status_update.blank?
topic_timer = TopicTimer.find_by(id: args[:topic_timer_id] || args[:topic_status_update_id])
raise Discourse::InvalidParameters.new(:topic_timer_id) if topic_timer.blank?
topic = topic_status_update.topic
topic = topic_timer.topic
return if topic.blank?
PostTimestampChanger.new(timestamp: Time.zone.now, topic: topic).change! do
if topic.private_message?
topic = TopicConverter.new(topic, Discourse.system_user)
.convert_to_public_topic(topic_status_update.category_id)
.convert_to_public_topic(topic_timer.category_id)
else
topic.change_category_to_id(topic_status_update.category_id)
topic.change_category_to_id(topic_timer.category_id)
end
topic.update_columns(visible: true)
topic_status_update.trash!(Discourse.system_user)
topic_timer.trash!(Discourse.system_user)
end
MessageBus.publish("/topic/#{topic.id}", reload_topic: true, refresh_stream: true)

View File

@ -1,18 +1,18 @@
module Jobs
class ToggleTopicClosed < Jobs::Base
def execute(args)
topic_status_update = TopicStatusUpdate.find_by(id: args[:topic_status_update_id])
topic_timer = TopicTimer.find_by(id: args[:topic_timer_id] || args[:topic_status_update_id])
state = !!args[:state]
if topic_status_update.blank? ||
topic_status_update.execute_at > Time.zone.now ||
(topic = topic_status_update.topic).blank? ||
if topic_timer.blank? ||
topic_timer.execute_at > Time.zone.now ||
(topic = topic_timer.topic).blank? ||
topic.closed == state
return
end
user = topic_status_update.user
user = topic_timer.user
if Guardian.new(user).can_close?(topic)
topic.update_status('autoclosed', state, user)

View File

@ -25,7 +25,7 @@ module Jobs
ScoreCalculator.new.calculate(args)
# Re-run stuff that we missed
TopicStatusUpdate.ensure_consistency!
TopicTimer.ensure_consistency!
# Forces rebake of old posts where needed, as long as no system avatars need updating
unless UserAvatar.where("last_gravatar_download_attempt IS NULL").limit(1).first

View File

@ -202,7 +202,7 @@ SQL
t = Topic.new(title: I18n.t("category.topic_prefix", category: name), user: user, pinned_at: Time.now, category_id: id)
t.skip_callbacks = true
t.ignore_category_auto_close = true
t.set_or_create_status_update(TopicStatusUpdate.types[:close], nil)
t.set_or_create_timer(TopicTimer.types[:close], nil)
t.save!(validate: false)
update_column(:topic_id, t.id)
t.posts.create(raw: post_template, user: user)

View File

@ -521,8 +521,8 @@ SQL
)
)
topic.set_or_create_status_update(
TopicStatusUpdate.types[:open],
topic.set_or_create_timer(
TopicTimer.types[:open],
SiteSetting.num_hours_to_close_topic,
by_user: Discourse.system_user
)

View File

@ -121,7 +121,7 @@ class Topic < ActiveRecord::Base
has_many :topic_links
has_many :topic_invites
has_many :invites, through: :topic_invites, source: :invite
has_many :topic_status_updates, dependent: :destroy
has_many :topic_timers, dependent: :destroy
has_one :user_warning
has_one :first_post, -> {where post_number: 1}, class_name: Post
@ -215,10 +215,10 @@ class Topic < ActiveRecord::Base
if !@ignore_category_auto_close &&
self.category &&
self.category.auto_close_hours &&
!topic_status_update&.execute_at
!topic_timer&.execute_at
self.set_or_create_status_update(
TopicStatusUpdate.types[:close],
self.set_or_create_timer(
TopicTimer.types[:close],
self.category.auto_close_hours,
based_on_last_post: self.category.auto_close_based_on_last_post
)
@ -952,8 +952,12 @@ SQL
Topic.where("pinned_until < now()").update_all(pinned_at: nil, pinned_globally: false, pinned_until: nil)
end
def topic_timer
@topic_timer ||= topic_timers.where('deleted_at IS NULL').first
end
def topic_status_update
@topic_status_update ||= topic_status_updates.where('deleted_at IS NULL').first
topic_timer # will be used to filter timers unrelated to topic status
end
# Valid arguments for the time:
@ -968,31 +972,31 @@ SQL
# * timezone_offset: (Integer) offset from UTC in minutes of the given argument.
# * based_on_last_post: True if time should be based on timestamp of the last post.
# * category_id: Category that the update will apply to.
def set_or_create_status_update(status_type, time, by_user: nil, timezone_offset: 0, based_on_last_post: false, category_id: SiteSetting.uncategorized_category_id)
topic_status_update = TopicStatusUpdate.find_or_initialize_by(
def set_or_create_timer(status_type, time, by_user: nil, timezone_offset: 0, based_on_last_post: false, category_id: SiteSetting.uncategorized_category_id)
topic_timer = TopicTimer.find_or_initialize_by(
status_type: status_type,
topic: self
)
if time.blank?
topic_status_update.trash!(trashed_by: by_user || Discourse.system_user)
topic_timer.trash!(trashed_by: by_user || Discourse.system_user)
return
end
time_now = Time.zone.now
topic_status_update.based_on_last_post = !based_on_last_post.blank?
topic_timer.based_on_last_post = !based_on_last_post.blank?
if status_type == TopicStatusUpdate.types[:publish_to_category]
topic_status_update.category = Category.find_by(id: category_id)
if status_type == TopicTimer.types[:publish_to_category]
topic_timer.category = Category.find_by(id: category_id)
end
if topic_status_update.based_on_last_post
if topic_timer.based_on_last_post
num_hours = time.to_f
if num_hours > 0
last_post_created_at = self.ordered_posts.last.present? ? self.ordered_posts.last.created_at : time_now
topic_status_update.execute_at = last_post_created_at + num_hours.hours
topic_status_update.created_at = last_post_created_at
topic_timer.execute_at = last_post_created_at + num_hours.hours
topic_timer.created_at = last_post_created_at
end
else
utc = Time.find_zone("UTC")
@ -1001,37 +1005,37 @@ SQL
if is_timestamp && m = /^(\d{1,2}):(\d{2})(?:\s*[AP]M)?$/i.match(time.strip)
# a time of day in client's time zone, like "15:00"
topic_status_update.execute_at = utc.local(now.year, now.month, now.day, m[1].to_i, m[2].to_i)
topic_status_update.execute_at += timezone_offset * 60 if timezone_offset
topic_status_update.execute_at += 1.day if topic_status_update.execute_at < now
topic_timer.execute_at = utc.local(now.year, now.month, now.day, m[1].to_i, m[2].to_i)
topic_timer.execute_at += timezone_offset * 60 if timezone_offset
topic_timer.execute_at += 1.day if topic_timer.execute_at < now
elsif is_timestamp && time.include?("-") && timestamp = utc.parse(time)
# a timestamp in client's time zone, like "2015-5-27 12:00"
topic_status_update.execute_at = timestamp
topic_status_update.execute_at += timezone_offset * 60 if timezone_offset
topic_status_update.errors.add(:execute_at, :invalid) if timestamp < now
topic_timer.execute_at = timestamp
topic_timer.execute_at += timezone_offset * 60 if timezone_offset
topic_timer.errors.add(:execute_at, :invalid) if timestamp < now
else
num_hours = time.to_f
if num_hours > 0
topic_status_update.execute_at = num_hours.hours.from_now
topic_timer.execute_at = num_hours.hours.from_now
end
end
end
if topic_status_update.execute_at
if topic_timer.execute_at
if by_user&.staff? || by_user&.trust_level == TrustLevel[4]
topic_status_update.user = by_user
topic_timer.user = by_user
else
topic_status_update.user ||= (self.user.staff? || self.user.trust_level == TrustLevel[4] ? self.user : Discourse.system_user)
topic_timer.user ||= (self.user.staff? || self.user.trust_level == TrustLevel[4] ? self.user : Discourse.system_user)
end
if self.persisted?
topic_status_update.save!
topic_timer.save!
else
self.topic_status_updates << topic_status_update
self.topic_timers << topic_timer
end
topic_status_update
topic_timer
end
end

View File

@ -1,4 +1,4 @@
class TopicStatusUpdate < ActiveRecord::Base
class TopicTimer < ActiveRecord::Base
include Trashable
belongs_to :user
@ -41,12 +41,12 @@ class TopicStatusUpdate < ActiveRecord::Base
end
def self.ensure_consistency!
TopicStatusUpdate.where("topic_status_updates.execute_at < ?", Time.zone.now)
.find_each do |topic_status_update|
TopicTimer.where("topic_timers.execute_at < ?", Time.zone.now)
.find_each do |topic_timer|
topic_status_update.send(
"schedule_auto_#{self.types[topic_status_update.status_type]}_job",
topic_status_update.execute_at
topic_timer.send(
"schedule_auto_#{self.types[topic_timer.status_type]}_job",
topic_timer.execute_at
)
end
end
@ -64,22 +64,22 @@ class TopicStatusUpdate < ActiveRecord::Base
def ensure_update_will_happen
if created_at && (execute_at < created_at)
errors.add(:execute_at, I18n.t(
'activerecord.errors.models.topic_status_update.attributes.execute_at.in_the_past'
'activerecord.errors.models.topic_timer.attributes.execute_at.in_the_past'
))
end
end
def cancel_auto_close_job
Jobs.cancel_scheduled_job(:toggle_topic_closed, topic_status_update_id: id)
Jobs.cancel_scheduled_job(:toggle_topic_closed, topic_timer_id: id)
end
alias_method :cancel_auto_open_job, :cancel_auto_close_job
def cancel_auto_publish_to_category_job
Jobs.cancel_scheduled_job(:publish_topic_to_category, topic_status_update_id: id)
Jobs.cancel_scheduled_job(:publish_topic_to_category, topic_timer_id: id)
end
def cancel_auto_delete_job
Jobs.cancel_scheduled_job(:delete_topic, topic_status_update_id: id)
Jobs.cancel_scheduled_job(:delete_topic, topic_timer_id: id)
end
def schedule_auto_open_job(time)
@ -87,7 +87,7 @@ class TopicStatusUpdate < ActiveRecord::Base
topic.update_status('closed', true, user) if !topic.closed
Jobs.enqueue_at(time, :toggle_topic_closed,
topic_status_update_id: id,
topic_timer_id: id,
state: false
)
end
@ -97,27 +97,27 @@ class TopicStatusUpdate < ActiveRecord::Base
topic.update_status('closed', false, user) if topic.closed
Jobs.enqueue_at(time, :toggle_topic_closed,
topic_status_update_id: id,
topic_timer_id: id,
state: true
)
end
def schedule_auto_publish_to_category_job(time)
Jobs.enqueue_at(time, :publish_topic_to_category, topic_status_update_id: id)
Jobs.enqueue_at(time, :publish_topic_to_category, topic_timer_id: id)
end
def publishing_to_category?
self.status_type.to_i == TopicStatusUpdate.types[:publish_to_category]
self.status_type.to_i == TopicTimer.types[:publish_to_category]
end
def schedule_auto_delete_job(time)
Jobs.enqueue_at(time, :delete_topic, topic_status_update_id: id)
Jobs.enqueue_at(time, :delete_topic, topic_timer_id: id)
end
end
# == Schema Information
#
# Table name: topic_status_updates
# Table name: topic_timers
#
# id :integer not null, primary key
# execute_at :datetime not null

View File

@ -1,4 +1,4 @@
class TopicStatusUpdateSerializer < ApplicationSerializer
class TopicTimerSerializer < ApplicationSerializer
attributes :id,
:execute_at,
:duration,
@ -7,6 +7,6 @@ class TopicStatusUpdateSerializer < ApplicationSerializer
:category_id
def status_type
TopicStatusUpdate.types[object.status_type]
TopicTimer.types[object.status_type]
end
end

View File

@ -60,7 +60,7 @@ class TopicViewSerializer < ApplicationSerializer
:message_archived,
:tags,
:featured_link,
:topic_status_update,
:topic_timer,
:unicode_title
# TODO: Split off into proper object / serializer
@ -249,9 +249,9 @@ class TopicViewSerializer < ApplicationSerializer
SiteSetting.tagging_enabled
end
def topic_status_update
TopicStatusUpdateSerializer.new(
object.topic.topic_status_update, root: false
def topic_timer
TopicTimerSerializer.new(
object.topic.topic_timer, root: false
)
end

View File

@ -38,9 +38,9 @@ TopicStatusUpdater = Struct.new(:topic, :user) do
if @topic_status_update
if status.manually_closing_topic? || status.closing_topic?
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], nil)
topic.set_or_create_timer(TopicTimer.types[:close], nil)
elsif status.manually_opening_topic? || status.opening_topic?
topic.set_or_create_status_update(TopicStatusUpdate.types[:open], nil)
topic.set_or_create_timer(TopicTimer.types[:open], nil)
end
end

View File

@ -401,7 +401,7 @@ en:
attributes:
name:
taken: is already in use by another emoji
topic_status_update:
topic_timer:
attributes:
execute_at:
in_the_past: "must be in the future."

View File

@ -605,7 +605,7 @@ Discourse::Application.routes.draw do
put "t/:topic_id/re-pin" => "topics#re_pin", constraints: {topic_id: /\d+/}
put "t/:topic_id/mute" => "topics#mute", constraints: {topic_id: /\d+/}
put "t/:topic_id/unmute" => "topics#unmute", constraints: {topic_id: /\d+/}
post "t/:topic_id/status_update" => "topics#status_update", constraints: {topic_id: /\d+/}
post "t/:topic_id/timer" => "topics#timer", constraints: {topic_id: /\d+/}
put "t/:topic_id/make-banner" => "topics#make_banner", constraints: {topic_id: /\d+/}
put "t/:topic_id/remove-banner" => "topics#remove_banner", constraints: {topic_id: /\d+/}
put "t/:topic_id/remove-allowed-user" => "topics#remove_allowed_user", constraints: {topic_id: /\d+/}

View File

@ -1,12 +1,13 @@
class MoveAutoCloseColumnsToTopicStatusUpdate < ActiveRecord::Migration
def up
# The 1 in the fourth column is TopicStatusUpdate.types[:close], an enum with value 1.
execute <<~SQL
INSERT INTO topic_status_updates(topic_id, user_id, execute_at, status_type, based_on_last_post, created_at, updated_at)
SELECT
t.id,
t.auto_close_user_id,
t.auto_close_at,
#{TopicStatusUpdate.types[:close]},
1,
t.auto_close_based_on_last_post,
t.auto_close_started_at,
t.auto_close_started_at

View File

@ -0,0 +1,5 @@
class RenameTopicStatusUpdatesToTopicTimers < ActiveRecord::Migration
def change
rename_table :topic_status_updates, :topic_timers
end
end

View File

@ -390,15 +390,15 @@ class PostCreator
end
def update_topic_auto_close
topic_status_update = @topic.topic_status_update
topic_timer = @topic.topic_timer
if topic_status_update &&
topic_status_update.based_on_last_post &&
topic_status_update.duration > 0
if topic_timer &&
topic_timer.based_on_last_post &&
topic_timer.duration > 0
@topic.set_or_create_status_update(TopicStatusUpdate.types[:close],
topic_status_update.duration,
based_on_last_post: topic_status_update.based_on_last_post
@topic.set_or_create_timer(TopicTimer.types[:close],
topic_timer.duration,
based_on_last_post: topic_timer.based_on_last_post
)
end
end

View File

@ -269,12 +269,12 @@ describe PostCreator do
it "doesn't update topic's auto close when it's not based on last post" do
Timecop.freeze do
topic = Fabricate(:topic).set_or_create_status_update(TopicStatusUpdate.types[:close], 12)
topic = Fabricate(:topic).set_or_create_timer(TopicTimer.types[:close], 12)
PostCreator.new(topic.user, topic_id: topic.id, raw: "this is a second post").create
topic.reload
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.execute_at).to be_within(1.second).of(Time.zone.now + 12.hours)
expect(topic_status_update.created_at).to be_within(1.second).of(Time.zone.now)
end
@ -283,7 +283,7 @@ describe PostCreator do
it "updates topic's auto close date when it's based on last post" do
Timecop.freeze do
topic = Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update,
topic_timers: [Fabricate(:topic_timer,
based_on_last_post: true,
execute_at: Time.zone.now - 12.hours,
created_at: Time.zone.now - 24.hours
@ -294,7 +294,7 @@ describe PostCreator do
PostCreator.new(topic.user, topic_id: topic.id, raw: "this is a second post").create
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.execute_at).to be_within(1.second).of(Time.zone.now + 12.hours)
expect(topic_status_update.created_at).to be_within(1.second).of(Time.zone.now)
end
@ -362,7 +362,7 @@ describe PostCreator do
Guardian.any_instance.stubs(:can_moderate?).returns(false)
expect {
PostCreator.new(user, basic_topic_params.merge(auto_close_time: 2)).create!
}.to_not change { TopicStatusUpdate.count }
}.to_not change { TopicTimer.count }
end
end
end

View File

@ -413,8 +413,8 @@ describe TopicsController do
end
it 'should update the status of the topic correctly' do
@topic = Fabricate(:topic, user: @user, closed: true, topic_status_updates: [
Fabricate(:topic_status_update, status_type: TopicStatusUpdate.types[:open])
@topic = Fabricate(:topic, user: @user, closed: true, topic_timers: [
Fabricate(:topic_timer, status_type: TopicTimer.types[:open])
])
xhr :put, :status, topic_id: @topic.id, status: 'closed', enabled: 'false'

View File

@ -1,6 +0,0 @@
Fabricator(:topic_status_update) do
user
topic
execute_at Time.zone.now + 1.hour
status_type TopicStatusUpdate.types[:close]
end

View File

@ -0,0 +1,6 @@
Fabricator(:topic_timer) do
user
topic
execute_at Time.zone.now + 1.hour
status_type TopicTimer.types[:close]
end

View File

@ -7,9 +7,9 @@ RSpec.describe "Managing a topic's status update", type: :request do
context 'when a user is not logged in' do
it 'should return the right response' do
expect do
post "/t/#{topic.id}/status_update.json",
post "/t/#{topic.id}/timer.json",
time: '24',
status_type: TopicStatusUpdate.types[1]
status_type: TopicTimer.types[1]
end.to raise_error(Discourse::NotLoggedIn)
end
end
@ -18,9 +18,9 @@ RSpec.describe "Managing a topic's status update", type: :request do
it 'should return the right response' do
sign_in(user)
post "/t/#{topic.id}/status_update.json",
post "/t/#{topic.id}/timer.json",
time: '24',
status_type: TopicStatusUpdate.types[1]
status_type: TopicTimer.types[1]
expect(response.status).to eq(403)
expect(JSON.parse(response.body)["error_type"]).to eq('invalid_access')
@ -37,13 +37,13 @@ RSpec.describe "Managing a topic's status update", type: :request do
it 'should be able to create a topic status update' do
time = 24
post "/t/#{topic.id}/status_update.json",
post "/t/#{topic.id}/timer.json",
time: 24,
status_type: TopicStatusUpdate.types[1]
status_type: TopicTimer.types[1]
expect(response).to be_success
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
@ -60,11 +60,11 @@ RSpec.describe "Managing a topic's status update", type: :request do
end
it 'should be able to delete a topic status update' do
topic.update!(topic_status_updates: [Fabricate(:topic_status_update)])
topic.update!(topic_timers: [Fabricate(:topic_timer)])
post "/t/#{topic.id}/status_update.json",
post "/t/#{topic.id}/timer.json",
time: nil,
status_type: TopicStatusUpdate.types[1]
status_type: TopicTimer.types[1]
expect(response).to be_success
expect(topic.reload.topic_status_update).to eq(nil)
@ -80,14 +80,14 @@ RSpec.describe "Managing a topic's status update", type: :request do
it 'should be able to create the topic status update' do
SiteSetting.queue_jobs = true
post "/t/#{topic.id}/status_update.json",
post "/t/#{topic.id}/timer.json",
time: 24,
status_type: TopicStatusUpdate.types[3],
status_type: TopicTimer.types[3],
category_id: topic.category_id
expect(response).to be_success
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
@ -95,7 +95,7 @@ RSpec.describe "Managing a topic's status update", type: :request do
.to be_within(1.second).of(24.hours.from_now)
expect(topic_status_update.status_type)
.to eq(TopicStatusUpdate.types[:publish_to_category])
.to eq(TopicTimer.types[:publish_to_category])
json = JSON.parse(response.body)
@ -106,7 +106,7 @@ RSpec.describe "Managing a topic's status update", type: :request do
describe 'invalid status type' do
it 'should raise the right error' do
expect do
post "/t/#{topic.id}/status_update.json",
post "/t/#{topic.id}/timer.json",
time: 10,
status_type: 'something'
end.to raise_error(Discourse::InvalidParameters)

View File

@ -46,14 +46,14 @@ describe Topic do
it 'should schedule the topic to auto-close' do
topic
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
expect(topic.topic_status_update.execute_at).to be_within_one_second_of(2.hours.from_now)
args = job_klass.jobs.last['args'].first
expect(args["topic_status_update_id"]).to eq(topic.topic_status_update.id)
expect(args["topic_timer_id"]).to eq(topic.topic_status_update.id)
expect(args["state"]).to eq(true)
end
@ -64,7 +64,7 @@ describe Topic do
it 'should schedule the topic to auto-close' do
staff_topic
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(staff_topic)
expect(topic_status_update.execute_at).to be_within_one_second_of(2.hours.from_now)
@ -72,7 +72,7 @@ describe Topic do
args = job_klass.jobs.last['args'].first
expect(args["topic_status_update_id"]).to eq(topic_status_update.id)
expect(args["topic_timer_id"]).to eq(topic_status_update.id)
expect(args["state"]).to eq(true)
end
@ -95,7 +95,7 @@ describe Topic do
it 'should schedule the topic to auto-close' do
regular_user_topic
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(regular_user_topic)
expect(topic_status_update.execute_at).to be_within_one_second_of(2.hours.from_now)
@ -103,7 +103,7 @@ describe Topic do
args = job_klass.jobs.last['args'].first
expect(args["topic_status_update_id"]).to eq(topic_status_update.id)
expect(args["topic_timer_id"]).to eq(topic_status_update.id)
expect(args["state"]).to eq(true)
end
end

View File

@ -5,7 +5,7 @@ describe Jobs::DeleteTopic do
let(:topic) do
Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update, user: admin)]
topic_timers: [Fabricate(:topic_timer, user: admin)]
)
end
@ -18,7 +18,7 @@ describe Jobs::DeleteTopic do
it "can close a topic" do
first_post
Timecop.freeze(2.hours.from_now) do
described_class.new.execute(topic_status_update_id: topic.topic_status_update.id)
described_class.new.execute(topic_timer_id: topic.topic_timer.id)
expect(topic.reload).to be_trashed
expect(first_post.reload).to be_trashed
end
@ -29,17 +29,17 @@ describe Jobs::DeleteTopic do
topic.trash!
Timecop.freeze(2.hours.from_now) do
Topic.any_instance.expects(:trash!).never
described_class.new.execute(topic_status_update_id: topic.topic_status_update.id)
described_class.new.execute(topic_timer_id: topic.topic_timer.id)
end
end
it "should do nothing if it's too early" do
t = Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update, user: admin, execute_at: 5.hours.from_now)]
topic_timers: [Fabricate(:topic_timer, user: admin, execute_at: 5.hours.from_now)]
)
create_post(topic: t)
Timecop.freeze(4.hours.from_now) do
described_class.new.execute(topic_status_update_id: t.topic_status_update.id)
described_class.new.execute(topic_timer_id: t.topic_timer.id)
expect(t.reload).to_not be_trashed
end
end
@ -47,14 +47,14 @@ describe Jobs::DeleteTopic do
describe "user isn't authorized to delete topics" do
let(:topic) {
Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update, user: Fabricate(:user))]
topic_timers: [Fabricate(:topic_timer, user: Fabricate(:user))]
)
}
it "shouldn't delete the topic" do
create_post(topic: topic)
Timecop.freeze(2.hours.from_now) do
described_class.new.execute(topic_status_update_id: topic.topic_status_update.id)
described_class.new.execute(topic_timer_id: topic.topic_timer.id)
expect(topic.reload).to_not be_trashed
end
end

View File

@ -5,9 +5,9 @@ RSpec.describe Jobs::PublishTopicToCategory do
let(:another_category) { Fabricate(:category) }
let(:topic) do
Fabricate(:topic, category: category, topic_status_updates: [
Fabricate(:topic_status_update,
status_type: TopicStatusUpdate.types[:publish_to_category],
Fabricate(:topic, category: category, topic_timers: [
Fabricate(:topic_timer,
status_type: TopicTimer.types[:publish_to_category],
category_id: another_category.id
)
])
@ -17,9 +17,9 @@ RSpec.describe Jobs::PublishTopicToCategory do
SiteSetting.queue_jobs = true
end
describe 'when topic_status_update_id is invalid' do
describe 'when topic_timer_id is invalid' do
it 'should raise the right error' do
expect { described_class.new.execute(topic_status_update_id: -1) }
expect { described_class.new.execute(topic_timer_id: -1) }
.to raise_error(Discourse::InvalidParameters)
end
end
@ -29,7 +29,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
Timecop.travel(1.hour.ago) { topic }
topic.trash!
described_class.new.execute(topic_status_update_id: topic.topic_status_update.id)
described_class.new.execute(topic_timer_id: topic.topic_timer.id)
topic.reload
expect(topic.category).to eq(category)
@ -41,13 +41,13 @@ RSpec.describe Jobs::PublishTopicToCategory do
Timecop.travel(1.hour.ago) { topic.update!(visible: false) }
message = MessageBus.track_publish do
described_class.new.execute(topic_status_update_id: topic.topic_status_update.id)
described_class.new.execute(topic_timer_id: topic.topic_timer.id)
end.first
topic.reload
expect(topic.category).to eq(another_category)
expect(topic.visible).to eq(true)
expect(TopicStatusUpdate.find_by(id: topic.topic_status_update.id)).to eq(nil)
expect(TopicTimer.find_by(id: topic.topic_timer.id)).to eq(nil)
%w{created_at bumped_at updated_at last_posted_at}.each do |attribute|
expect(topic.public_send(attribute)).to be_within(1.second).of(Time.zone.now)
@ -68,7 +68,7 @@ RSpec.describe Jobs::PublishTopicToCategory do
it 'should publish the topic to the new category' do
message = MessageBus.track_publish do
described_class.new.execute(topic_status_update_id: topic.topic_status_update.id)
described_class.new.execute(topic_timer_id: topic.topic_timer.id)
end.last
topic.reload

View File

@ -5,7 +5,7 @@ describe Jobs::ToggleTopicClosed do
let(:topic) do
Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update, user: admin)]
topic_timers: [Fabricate(:topic_timer, user: admin)]
)
end
@ -18,7 +18,7 @@ describe Jobs::ToggleTopicClosed do
Timecop.travel(1.hour.from_now) do
described_class.new.execute(
topic_status_update_id: topic.topic_status_update.id,
topic_timer_id: topic.topic_timer.id,
state: true
)
@ -35,7 +35,7 @@ describe Jobs::ToggleTopicClosed do
Timecop.travel(1.hour.from_now) do
described_class.new.execute(
topic_status_update_id: topic.topic_status_update.id,
topic_timer_id: topic.topic_timer.id,
state: false
)
@ -54,7 +54,7 @@ describe Jobs::ToggleTopicClosed do
Topic.any_instance.expects(:update_status).never
described_class.new.execute(
topic_status_update_id: topic.topic_status_update.id,
topic_timer_id: topic.topic_timer.id,
state: true
)
end
@ -63,13 +63,13 @@ describe Jobs::ToggleTopicClosed do
describe 'when user is not authorized to close topics' do
let(:topic) do
Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update, execute_at: 2.hours.from_now)]
topic_timers: [Fabricate(:topic_timer, execute_at: 2.hours.from_now)]
)
end
it 'should not do anything' do
described_class.new.execute(
topic_status_update_id: topic.topic_status_update.id,
topic_timer_id: topic.topic_timer.id,
state: false
)

View File

@ -496,11 +496,11 @@ describe PostAction do
expect(topic.reload.closed).to eq(true)
topic_status_update = TopicStatusUpdate.last
topic_status_update = TopicTimer.last
expect(topic_status_update.topic).to eq(topic)
expect(topic_status_update.execute_at).to be_within(1.second).of(1.hour.from_now)
expect(topic_status_update.status_type).to eq(TopicStatusUpdate.types[:open])
expect(topic_status_update.status_type).to eq(TopicTimer.types[:open])
end
end

View File

@ -746,7 +746,7 @@ describe Topic do
expect(@topic).to be_closed
expect(@topic.bumped_at.to_f).to eq(@original_bumped_at)
expect(@topic.moderator_posts_count).to eq(1)
expect(@topic.topic_status_updates.first).to eq(nil)
expect(@topic.topic_timers.first).to eq(nil)
end
end
end
@ -777,7 +777,7 @@ describe Topic do
freeze_time(2.days.ago)
@topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 48)
@topic.set_or_create_timer(TopicTimer.types[:close], 48)
@topic.save!
freeze_time(2.days.from_now)
@ -1100,12 +1100,12 @@ describe Topic do
end
end
describe '#set_or_create_status_update' do
describe '#set_or_create_timer' do
let(:topic) { Fabricate.build(:topic) }
let(:closing_topic) do
Fabricate(:topic,
topic_status_updates: [Fabricate(:topic_status_update, execute_at: 5.hours.from_now)]
topic_timers: [Fabricate(:topic_timer, execute_at: 5.hours.from_now)]
)
end
@ -1116,146 +1116,146 @@ describe Topic do
it 'can take a number of hours as an integer' do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 72, by_user: admin)
expect(topic.topic_status_updates.first.execute_at).to eq(3.days.from_now)
topic.set_or_create_timer(TopicTimer.types[:close], 72, by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(3.days.from_now)
end
end
it 'can take a number of hours as an integer, with timezone offset' do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 72, {by_user: admin, timezone_offset: 240})
expect(topic.topic_status_updates.first.execute_at).to eq(3.days.from_now)
topic.set_or_create_timer(TopicTimer.types[:close], 72, {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(3.days.from_now)
end
end
it 'can take a number of hours as a string' do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '18', by_user: admin)
expect(topic.topic_status_updates.first.execute_at).to eq(18.hours.from_now)
topic.set_or_create_timer(TopicTimer.types[:close], '18', by_user: admin)
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
end
end
it 'can take a number of hours as a string, with timezone offset' do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '18', {by_user: admin, timezone_offset: 240})
expect(topic.topic_status_updates.first.execute_at).to eq(18.hours.from_now)
topic.set_or_create_timer(TopicTimer.types[:close], '18', {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
end
end
it 'can take a number of hours as a string and can handle based on last post' do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '18', {by_user: admin, based_on_last_post: true})
expect(topic.topic_status_updates.first.execute_at).to eq(18.hours.from_now)
topic.set_or_create_timer(TopicTimer.types[:close], '18', {by_user: admin, based_on_last_post: true})
expect(topic.topic_timers.first.execute_at).to eq(18.hours.from_now)
end
end
it "can take a time later in the day" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '13:00', {by_user: admin})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,20,13,0))
topic.set_or_create_timer(TopicTimer.types[:close], '13:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,20,13,0))
end
end
it "can take a time later in the day, with timezone offset" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '13:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,20,17,0))
topic.set_or_create_timer(TopicTimer.types[:close], '13:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,20,17,0))
end
end
it "can take a time for the next day" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '5:00', {by_user: admin})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,21,5,0))
topic.set_or_create_timer(TopicTimer.types[:close], '5:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,21,5,0))
end
end
it "can take a time for the next day, with timezone offset" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '1:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,21,5,0))
topic.set_or_create_timer(TopicTimer.types[:close], '1:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,21,5,0))
end
end
it "can take a timestamp for a future time" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '2013-11-22 5:00', {by_user: admin})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,22,5,0))
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-22 5:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,22,5,0))
end
end
it "can take a timestamp for a future time, with timezone offset" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '2013-11-22 5:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,22,9,0))
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-22 5:00', {by_user: admin, timezone_offset: 240})
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,22,9,0))
end
end
it "sets a validation error when given a timestamp in the past" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '2013-11-19 5:00', {by_user: admin})
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-19 5:00', {by_user: admin})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.zone.local(2013,11,19,5,0))
expect(topic.topic_status_updates.first.errors[:execute_at]).to be_present
expect(topic.topic_timers.first.execute_at).to eq(Time.zone.local(2013,11,19,5,0))
expect(topic.topic_timers.first.errors[:execute_at]).to be_present
end
end
it "can take a timestamp with timezone" do
Timecop.freeze(now) do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '2013-11-25T01:35:00-08:00', {by_user: admin})
expect(topic.topic_status_updates.first.execute_at).to eq(Time.utc(2013,11,25,9,35))
topic.set_or_create_timer(TopicTimer.types[:close], '2013-11-25T01:35:00-08:00', {by_user: admin})
expect(topic.topic_timers.first.execute_at).to eq(Time.utc(2013,11,25,9,35))
end
end
it 'sets topic status update user to given user if it is a staff or TL4 user' do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 3, {by_user: admin})
expect(topic.topic_status_updates.first.user).to eq(admin)
topic.set_or_create_timer(TopicTimer.types[:close], 3, {by_user: admin})
expect(topic.topic_timers.first.user).to eq(admin)
end
it 'sets topic status update user to given user if it is a TL4 user' do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 3, {by_user: trust_level_4})
expect(topic.topic_status_updates.first.user).to eq(trust_level_4)
topic.set_or_create_timer(TopicTimer.types[:close], 3, {by_user: trust_level_4})
expect(topic.topic_timers.first.user).to eq(trust_level_4)
end
it 'sets topic status update user to system user if given user is not staff or a TL4 user' do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 3, {by_user: Fabricate.build(:user, id: 444)})
expect(topic.topic_status_updates.first.user).to eq(admin)
topic.set_or_create_timer(TopicTimer.types[:close], 3, {by_user: Fabricate.build(:user, id: 444)})
expect(topic.topic_timers.first.user).to eq(admin)
end
it 'sets topic status update user to system user if user is not given and topic creator is not staff nor TL4 user' do
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 3)
expect(topic.topic_status_updates.first.user).to eq(admin)
topic.set_or_create_timer(TopicTimer.types[:close], 3)
expect(topic.topic_timers.first.user).to eq(admin)
end
it 'sets topic status update user to topic creator if it is a staff user' do
staff_topic = Fabricate.build(:topic, user: Fabricate.build(:admin, id: 999))
staff_topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 3)
expect(staff_topic.topic_status_updates.first.user_id).to eq(999)
staff_topic.set_or_create_timer(TopicTimer.types[:close], 3)
expect(staff_topic.topic_timers.first.user_id).to eq(999)
end
it 'sets topic status update user to topic creator if it is a TL4 user' do
tl4_topic = Fabricate.build(:topic, user: Fabricate.build(:trust_level_4, id: 998))
tl4_topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 3)
expect(tl4_topic.topic_status_updates.first.user_id).to eq(998)
tl4_topic.set_or_create_timer(TopicTimer.types[:close], 3)
expect(tl4_topic.topic_timers.first.user_id).to eq(998)
end
it 'removes close topic status update if arg is nil' do
closing_topic.set_or_create_status_update(TopicStatusUpdate.types[:close], nil)
closing_topic.set_or_create_timer(TopicTimer.types[:close], nil)
closing_topic.reload
expect(closing_topic.topic_status_updates.first).to be_nil
expect(closing_topic.topic_timers.first).to be_nil
end
it 'updates topic status update execute_at if it was already set to close' do
Timecop.freeze(now) do
closing_topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 48)
closing_topic.set_or_create_timer(TopicTimer.types[:close], 48)
expect(closing_topic.reload.topic_status_update.execute_at).to eq(2.days.from_now)
end
end
it "does not update topic's topic status created_at it was already set to close" do
expect{
closing_topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 14)
}.to_not change { closing_topic.topic_status_updates.first.created_at }
closing_topic.set_or_create_timer(TopicTimer.types[:close], 14)
}.to_not change { closing_topic.topic_timers.first.created_at }
end
describe "when category's default auto close is set" do
@ -1263,14 +1263,14 @@ describe Topic do
let(:topic) { Fabricate(:topic, category: category) }
it "should be able to override category's default auto close" do
expect(topic.topic_status_updates.first.duration).to eq(4)
expect(topic.topic_timers.first.duration).to eq(4)
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], 2, by_user: admin)
topic.set_or_create_timer(TopicTimer.types[:close], 2, by_user: admin)
expect(topic.reload.closed).to eq(false)
Timecop.travel(3.hours.from_now) do
TopicStatusUpdate.ensure_consistency!
TopicTimer.ensure_consistency!
expect(topic.reload.closed).to eq(true)
end
end

View File

@ -1,7 +1,7 @@
require 'rails_helper'
RSpec.describe TopicStatusUpdate, type: :model do
let(:topic_status_update) { Fabricate(:topic_status_update) }
RSpec.describe TopicTimer, type: :model do
let(:topic_timer) { Fabricate(:topic_timer) }
let(:topic) { Fabricate(:topic) }
before do
@ -11,10 +11,10 @@ RSpec.describe TopicStatusUpdate, type: :model do
context "validations" do
describe '#status_type' do
it 'should ensure that only one active topic status update exists' do
topic_status_update.update!(topic: topic)
Fabricate(:topic_status_update, deleted_at: Time.zone.now, topic: topic)
topic_timer.update!(topic: topic)
Fabricate(:topic_timer, deleted_at: Time.zone.now, topic: topic)
expect { Fabricate(:topic_status_update, topic: topic) }
expect { Fabricate(:topic_timer, topic: topic) }
.to raise_error(ActiveRecord::RecordInvalid)
end
end
@ -22,26 +22,26 @@ RSpec.describe TopicStatusUpdate, type: :model do
describe '#execute_at' do
describe 'when #execute_at is greater than #created_at' do
it 'should be valid' do
topic_status_update = Fabricate.build(:topic_status_update,
topic_timer = Fabricate.build(:topic_timer,
execute_at: Time.zone.now + 1.hour,
user: Fabricate(:user),
topic: Fabricate(:topic)
)
expect(topic_status_update).to be_valid
expect(topic_timer).to be_valid
end
end
describe 'when #execute_at is smaller than #created_at' do
it 'should not be valid' do
topic_status_update = Fabricate.build(:topic_status_update,
topic_timer = Fabricate.build(:topic_timer,
execute_at: Time.zone.now - 1.hour,
created_at: Time.zone.now,
user: Fabricate(:user),
topic: Fabricate(:topic)
)
expect(topic_status_update).to_not be_valid
expect(topic_timer).to_not be_valid
end
end
end
@ -50,25 +50,25 @@ RSpec.describe TopicStatusUpdate, type: :model do
describe 'when #status_type is publish_to_category' do
describe 'when #category_id is not present' do
it 'should not be valid' do
topic_status_update = Fabricate.build(:topic_status_update,
status_type: TopicStatusUpdate.types[:publish_to_category]
topic_timer = Fabricate.build(:topic_timer,
status_type: TopicTimer.types[:publish_to_category]
)
expect(topic_status_update).to_not be_valid
expect(topic_status_update.errors.keys).to include(:category_id)
expect(topic_timer).to_not be_valid
expect(topic_timer.errors.keys).to include(:category_id)
end
end
describe 'when #category_id is present' do
it 'should be valid' do
topic_status_update = Fabricate.build(:topic_status_update,
status_type: TopicStatusUpdate.types[:publish_to_category],
topic_timer = Fabricate.build(:topic_timer,
status_type: TopicTimer.types[:publish_to_category],
category_id: Fabricate(:category).id,
user: Fabricate(:user),
topic: Fabricate(:topic)
)
expect(topic_status_update).to be_valid
expect(topic_timer).to be_valid
end
end
end
@ -79,51 +79,51 @@ RSpec.describe TopicStatusUpdate, type: :model do
describe 'when #execute_at and #user_id are not changed' do
it 'should not schedule another to update topic' do
Jobs.expects(:enqueue_at).with(
topic_status_update.execute_at,
topic_timer.execute_at,
:toggle_topic_closed,
topic_status_update_id: topic_status_update.id,
topic_timer_id: topic_timer.id,
state: true
).once
topic_status_update
topic_timer
Jobs.expects(:cancel_scheduled_job).never
topic_status_update.update!(topic: Fabricate(:topic))
topic_timer.update!(topic: Fabricate(:topic))
end
end
describe 'when #execute_at value is changed' do
it 'reschedules the job' do
Timecop.freeze do
topic_status_update
topic_timer
Jobs.expects(:cancel_scheduled_job).with(
:toggle_topic_closed, topic_status_update_id: topic_status_update.id
:toggle_topic_closed, topic_timer_id: topic_timer.id
)
Jobs.expects(:enqueue_at).with(
3.days.from_now, :toggle_topic_closed,
topic_status_update_id: topic_status_update.id,
topic_timer_id: topic_timer.id,
state: true
)
topic_status_update.update!(execute_at: 3.days.from_now, created_at: Time.zone.now)
topic_timer.update!(execute_at: 3.days.from_now, created_at: Time.zone.now)
end
end
describe 'when execute_at is smaller than the current time' do
it 'should enqueue the job immediately' do
Timecop.freeze do
topic_status_update
topic_timer
Jobs.expects(:enqueue_at).with(
Time.zone.now, :toggle_topic_closed,
topic_status_update_id: topic_status_update.id,
topic_timer_id: topic_timer.id,
state: true
)
topic_status_update.update!(
topic_timer.update!(
execute_at: Time.zone.now - 1.hour,
created_at: Time.zone.now - 2.hour
)
@ -135,22 +135,22 @@ RSpec.describe TopicStatusUpdate, type: :model do
describe 'when user is changed' do
it 'should update the job' do
Timecop.freeze do
topic_status_update
topic_timer
Jobs.expects(:cancel_scheduled_job).with(
:toggle_topic_closed, topic_status_update_id: topic_status_update.id
:toggle_topic_closed, topic_timer_id: topic_timer.id
)
admin = Fabricate(:admin)
Jobs.expects(:enqueue_at).with(
topic_status_update.execute_at,
topic_timer.execute_at,
:toggle_topic_closed,
topic_status_update_id: topic_status_update.id,
topic_timer_id: topic_timer.id,
state: true
)
topic_status_update.update!(user: admin)
topic_timer.update!(user: admin)
end
end
end
@ -158,22 +158,22 @@ RSpec.describe TopicStatusUpdate, type: :model do
describe 'when a open topic status update is created for an open topic' do
let(:topic) { Fabricate(:topic, closed: false) }
let(:topic_status_update) do
Fabricate(:topic_status_update,
let(:topic_timer) do
Fabricate(:topic_timer,
status_type: described_class.types[:open],
topic: topic
)
end
it 'should close the topic' do
topic_status_update
topic_timer
expect(topic.reload.closed).to eq(true)
end
describe 'when topic has been deleted' do
it 'should not queue the job' do
topic.trash!
topic_status_update
topic_timer
expect(Jobs::ToggleTopicClosed.jobs).to eq([])
end
@ -183,22 +183,22 @@ RSpec.describe TopicStatusUpdate, type: :model do
describe 'when a close topic status update is created for a closed topic' do
let(:topic) { Fabricate(:topic, closed: true) }
let(:topic_status_update) do
Fabricate(:topic_status_update,
let(:topic_timer) do
Fabricate(:topic_timer,
status_type: described_class.types[:close],
topic: topic
)
end
it 'should open the topic' do
topic_status_update
topic_timer
expect(topic.reload.closed).to eq(false)
end
describe 'when topic has been deleted' do
it 'should not queue the job' do
topic.trash!
topic_status_update
topic_timer
expect(Jobs::ToggleTopicClosed.jobs).to eq([])
end
@ -213,20 +213,20 @@ RSpec.describe TopicStatusUpdate, type: :model do
end
it 'should enqueue jobs that have been missed' do
close_topic_status_update = Fabricate(:topic_status_update,
close_topic_timer = Fabricate(:topic_timer,
execute_at: Time.zone.now - 1.hour,
created_at: Time.zone.now - 2.hour
)
open_topic_status_update = Fabricate(:topic_status_update,
open_topic_timer = Fabricate(:topic_timer,
status_type: described_class.types[:open],
execute_at: Time.zone.now - 1.hour,
created_at: Time.zone.now - 2.hour
)
Fabricate(:topic_status_update)
Fabricate(:topic_timer)
Fabricate(:topic_status_update,
Fabricate(:topic_timer,
execute_at: Time.zone.now - 1.hour,
created_at: Time.zone.now - 2.hour
).topic.trash!
@ -236,12 +236,12 @@ RSpec.describe TopicStatusUpdate, type: :model do
job_args = Jobs::ToggleTopicClosed.jobs.first["args"].first
expect(job_args["topic_status_update_id"]).to eq(close_topic_status_update.id)
expect(job_args["topic_timer_id"]).to eq(close_topic_timer.id)
expect(job_args["state"]).to eq(true)
job_args = Jobs::ToggleTopicClosed.jobs.last["args"].first
expect(job_args["topic_status_update_id"]).to eq(open_topic_status_update.id)
expect(job_args["topic_timer_id"]).to eq(open_topic_timer.id)
expect(job_args["state"]).to eq(false)
end
end

View File

@ -17,7 +17,7 @@ describe TopicStatusUpdater do
title: "hello world title",
)
# TODO needed so counts sync up, PostCreator really should not give back out-of-date Topic
post.topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '10')
post.topic.set_or_create_timer(TopicTimer.types[:close], '10')
post.topic.reload
TopicStatusUpdater.new(post.topic, admin).update!("autoclosed", true)
@ -30,7 +30,7 @@ describe TopicStatusUpdater do
it "adds an autoclosed message" do
topic = create_topic
topic.set_or_create_status_update(TopicStatusUpdate.types[:close], '10')
topic.set_or_create_timer(TopicTimer.types[:close], '10')
TopicStatusUpdater.new(topic, admin).update!("autoclosed", true)
@ -44,8 +44,8 @@ describe TopicStatusUpdater do
topic = create_topic
Fabricate(:post, topic: topic)
topic.set_or_create_status_update(
TopicStatusUpdate.types[:close], '10', based_on_last_post: true
topic.set_or_create_timer(
TopicTimer.types[:close], '10', based_on_last_post: true
)
TopicStatusUpdater.new(topic, admin).update!("autoclosed", true)