mirror of
https://github.com/codeninjasllc/discourse.git
synced 2024-11-23 23:58:31 -05:00
Auto-close time can be entered in 3 ways, so a topic can close at any time
This commit is contained in:
parent
67b6d37da0
commit
a9ab98ef9e
19 changed files with 193 additions and 80 deletions
|
@ -0,0 +1,28 @@
|
||||||
|
Discourse.AutoCloseFormComponent = Ember.Component.extend({
|
||||||
|
|
||||||
|
autoCloseValid: false,
|
||||||
|
|
||||||
|
label: function() {
|
||||||
|
return I18n.t( this.get('labelKey') || 'composer.auto_close_label' );
|
||||||
|
}.property('labelKey'),
|
||||||
|
|
||||||
|
autoCloseChanged: function() {
|
||||||
|
if( this.get('autoCloseTime') && this.get('autoCloseTime').length > 0 ) {
|
||||||
|
this.set('autoCloseTime', this.get('autoCloseTime').replace(/[^\d:-\s]/g, '') );
|
||||||
|
}
|
||||||
|
this.set('autoCloseValid', this.isAutoCloseValid());
|
||||||
|
}.observes('autoCloseTime'),
|
||||||
|
|
||||||
|
isAutoCloseValid: function() {
|
||||||
|
if (this.get('autoCloseTime')) {
|
||||||
|
var t = this.get('autoCloseTime').trim();
|
||||||
|
if (t.match(/^[\d]{4}-[\d]{1,2}-[\d]{1,2} [\d]{1,2}:[\d]{2}/)) {
|
||||||
|
return moment(t).isAfter(); // In the future
|
||||||
|
} else {
|
||||||
|
return (t.match(/^[\d]+$/) || t.match(/^[\d]{1,2}:[\d]{2}$/)) !== null;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
|
@ -9,20 +9,23 @@
|
||||||
**/
|
**/
|
||||||
Discourse.EditTopicAutoCloseController = Discourse.ObjectController.extend(Discourse.ModalFunctionality, {
|
Discourse.EditTopicAutoCloseController = Discourse.ObjectController.extend(Discourse.ModalFunctionality, {
|
||||||
|
|
||||||
setDays: function() {
|
auto_close_valid: true,
|
||||||
|
auto_close_invalid: Em.computed.not('auto_close_valid'),
|
||||||
|
|
||||||
|
setAutoCloseTime: function() {
|
||||||
if( this.get('details.auto_close_at') ) {
|
if( this.get('details.auto_close_at') ) {
|
||||||
var closeTime = new Date( this.get('details.auto_close_at') );
|
var closeTime = new Date( this.get('details.auto_close_at') );
|
||||||
if (closeTime > new Date()) {
|
if (closeTime > new Date()) {
|
||||||
this.set('auto_close_days', Math.round(moment(closeTime).diff(new Date(), 'days', true)));
|
this.set('auto_close_time', moment(closeTime).format("YYYY-MM-DD HH:mm"));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.set('details.auto_close_days', '');
|
this.set('details.auto_close_time', '');
|
||||||
}
|
}
|
||||||
}.observes('details.auto_close_at'),
|
}.observes('details.auto_close_at'),
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
saveAutoClose: function() {
|
saveAutoClose: function() {
|
||||||
this.setAutoClose( parseFloat(this.get('auto_close_days')) );
|
this.setAutoClose( this.get('auto_close_time') );
|
||||||
},
|
},
|
||||||
|
|
||||||
removeAutoClose: function() {
|
removeAutoClose: function() {
|
||||||
|
@ -30,19 +33,23 @@ Discourse.EditTopicAutoCloseController = Discourse.ObjectController.extend(Disco
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
setAutoClose: function(days) {
|
setAutoClose: function(time) {
|
||||||
var self = this;
|
var self = this;
|
||||||
this.send('hideModal');
|
this.send('hideModal');
|
||||||
Discourse.ajax({
|
Discourse.ajax({
|
||||||
url: '/t/' + this.get('id') + '/autoclose',
|
url: '/t/' + this.get('id') + '/autoclose',
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
dataType: 'html', // no custom errors, jquery 1.9 enforces json
|
dataType: 'json',
|
||||||
data: { auto_close_days: days > 0 ? days : null }
|
data: { auto_close_time: Discourse.Utilities.timestampFromAutocloseString(time) }
|
||||||
}).then(function(){
|
}).then(function(result){
|
||||||
self.send('closeModal');
|
if (result.success) {
|
||||||
self.set('details.auto_close_at', moment().add('days', days).format());
|
self.send('closeModal');
|
||||||
|
self.set('details.auto_close_at', result.auto_close_at);
|
||||||
|
} else {
|
||||||
|
bootbox.alert(I18n.t('composer.auto_close_error'), function() { self.send('showModal'); } );
|
||||||
|
}
|
||||||
}, function (error) {
|
}, function (error) {
|
||||||
bootbox.alert(I18n.t('generic_error'), function() { self.send('showModal'); } );
|
bootbox.alert(I18n.t('composer.auto_close_error'), function() { self.send('showModal'); } );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -322,6 +322,26 @@ Discourse.Utilities = {
|
||||||
image.src = url;
|
image.src = url;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
timestampFromAutocloseString: function(arg) {
|
||||||
|
if (!arg) return null;
|
||||||
|
if (arg.match(/^[\d]{4}-[\d]{1,2}-[\d]{1,2} [\d]{1,2}:[\d]{2}/)) {
|
||||||
|
return moment(arg).toJSON(); // moment will add the timezone
|
||||||
|
} else {
|
||||||
|
var matches = arg.match(/^([\d]{1,2}):([\d]{2})$/); // just the time HH:MM
|
||||||
|
if (matches) {
|
||||||
|
var now = moment(),
|
||||||
|
t = moment(new Date(now.year(), now.month(), now.date(), matches[1], matches[2]));
|
||||||
|
if (t.isAfter()) {
|
||||||
|
return t.toJSON();
|
||||||
|
} else {
|
||||||
|
return t.add('days', 1).toJSON();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -465,7 +465,7 @@ Discourse.Composer = Discourse.Model.extend({
|
||||||
moderator: currentUser.get('moderator'),
|
moderator: currentUser.get('moderator'),
|
||||||
yours: true,
|
yours: true,
|
||||||
newPost: true,
|
newPost: true,
|
||||||
auto_close_days: this.get('auto_close_days')
|
auto_close_time: Discourse.Utilities.timestampFromAutocloseString(this.get('auto_close_time'))
|
||||||
});
|
});
|
||||||
|
|
||||||
// If we're in a topic, we can append the post instantly.
|
// If we're in a topic, we can append the post instantly.
|
||||||
|
|
|
@ -180,7 +180,7 @@ Discourse.Post = Discourse.Model.extend({
|
||||||
title: this.get('title'),
|
title: this.get('title'),
|
||||||
image_sizes: this.get('imageSizes'),
|
image_sizes: this.get('imageSizes'),
|
||||||
target_usernames: this.get('target_usernames'),
|
target_usernames: this.get('target_usernames'),
|
||||||
auto_close_days: this.get('auto_close_days')
|
auto_close_time: Discourse.Utilities.timestampFromAutocloseString(this.get('auto_close_time'))
|
||||||
};
|
};
|
||||||
|
|
||||||
var metaData = this.get('metaData');
|
var metaData = this.get('metaData');
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
<div class="auto-close-fields">
|
|
||||||
<i class="icon icon-time"></i>
|
|
||||||
{{view.label}}
|
|
||||||
{{textField value=view.autoCloseDays maxlength="3"}}
|
|
||||||
{{i18n composer.auto_close_units}}
|
|
||||||
</div>
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
<div class="auto-close-fields">
|
||||||
|
<div>
|
||||||
|
<i class="icon icon-time"></i>
|
||||||
|
{{label}}
|
||||||
|
{{textField value=autoCloseTime}}
|
||||||
|
{{i18n composer.auto_close_units}}
|
||||||
|
</div>
|
||||||
|
<div class="examples">
|
||||||
|
{{i18n composer.auto_close_examples}}
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -48,13 +48,13 @@
|
||||||
<button class='btn' {{action showOptions}}>{{i18n topic.options}}</button>
|
<button class='btn' {{action showOptions}}>{{i18n topic.options}}</button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if model.showAdminOptions}}
|
{{#if model.showAdminOptions}}
|
||||||
<button {{action toggleAdminOptions target="view"}} class="btn no-text" title='{{i18n composer.admin_options_title}}'><i class="icon icon-wrench"></i></button>
|
<button {{action toggleAdminOptions target="view"}} class="btn no-text show-admin-options" title='{{i18n composer.admin_options_title}}'><i class="icon icon-wrench"></i></button>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/unless}}
|
{{/unless}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="admin-options-form">
|
<div class="admin-options-form">
|
||||||
{{autoCloseForm autoCloseDays=model.auto_close_days}}
|
{{auto-close-form autoCloseTime=model.auto_close_time}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<form>
|
<form>
|
||||||
{{autoCloseForm autoCloseDays=auto_close_days}}
|
{{auto-close-form autoCloseTime=auto_close_time autoCloseValid=auto_close_valid}}
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
<button class='btn btn-primary' {{action saveAutoClose}}>{{i18n topic.auto_close_save}}</button>
|
<button class='btn btn-primary' {{action saveAutoClose}} {{bindAttr disabled="auto_close_invalid"}}>{{i18n topic.auto_close_save}}</button>
|
||||||
<a {{action closeModal}}>{{i18n cancel}}</a>
|
<a {{action closeModal}}>{{i18n cancel}}</a>
|
||||||
<button class='btn pull-right' {{action removeAutoClose}}>{{i18n topic.auto_close_remove}}</button>
|
<button class='btn pull-right' {{action removeAutoClose}}>{{i18n topic.auto_close_remove}}</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,23 +0,0 @@
|
||||||
/**
|
|
||||||
This view renders the form to set or change a topic or category's auto-close setting.
|
|
||||||
|
|
||||||
@class AutoCloseFormView
|
|
||||||
@extends Ember.View
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
Discourse.AutoCloseFormView = Ember.View.extend({
|
|
||||||
templateName: 'auto_close_form',
|
|
||||||
|
|
||||||
label: function() {
|
|
||||||
return I18n.t( this.get('labelKey') || 'composer.auto_close_label' );
|
|
||||||
}.property('labelKey'),
|
|
||||||
|
|
||||||
autoCloseChanged: function() {
|
|
||||||
if( this.get('autoCloseDays') && this.get('autoCloseDays').length > 0 ) {
|
|
||||||
this.set('autoCloseDays', this.get('autoCloseDays').replace(/[^\d]/g, '') );
|
|
||||||
}
|
|
||||||
}.observes('autoCloseDays')
|
|
||||||
});
|
|
||||||
|
|
||||||
Discourse.View.registerHelper('autoCloseForm', Discourse.AutoCloseFormView);
|
|
|
@ -334,8 +334,12 @@
|
||||||
display: block;
|
display: block;
|
||||||
bottom: 8px;
|
bottom: 8px;
|
||||||
}
|
}
|
||||||
|
.auto-close-fields .examples {
|
||||||
|
margin-top: 0;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.title-input, .category-input {
|
.title-input, .category-input, .show-admin-options {
|
||||||
position: relative;
|
position: relative;
|
||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
@ -523,7 +527,11 @@ div.ac-wrap {
|
||||||
|
|
||||||
.auto-close-fields {
|
.auto-close-fields {
|
||||||
input {
|
input {
|
||||||
width: 50px;
|
width: 150px;
|
||||||
|
}
|
||||||
|
.examples {
|
||||||
|
margin: 12px 0 0 17px;
|
||||||
|
color: $dark_gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -543,7 +551,7 @@ div.ac-wrap {
|
||||||
}
|
}
|
||||||
|
|
||||||
#reply-control button.btn.no-text {
|
#reply-control button.btn.no-text {
|
||||||
margin: 7px 0 0 5px;
|
margin: 7px 0 0 5px; // works in safari, but not chrome and firefox
|
||||||
position: absolute;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -225,7 +225,7 @@ class PostsController < ApplicationController
|
||||||
:category,
|
:category,
|
||||||
:target_usernames,
|
:target_usernames,
|
||||||
:reply_to_post_number,
|
:reply_to_post_number,
|
||||||
:auto_close_days,
|
:auto_close_time,
|
||||||
:auto_track
|
:auto_track
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -153,12 +153,15 @@ class TopicsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def autoclose
|
def autoclose
|
||||||
raise Discourse::InvalidParameters.new(:auto_close_days) unless params.has_key?(:auto_close_days)
|
raise Discourse::InvalidParameters.new(:auto_close_time) unless params.has_key?(:auto_close_time)
|
||||||
@topic = Topic.where(id: params[:topic_id].to_i).first
|
topic = Topic.where(id: params[:topic_id].to_i).first
|
||||||
guardian.ensure_can_moderate!(@topic)
|
guardian.ensure_can_moderate!(topic)
|
||||||
@topic.set_auto_close(params[:auto_close_days], current_user)
|
topic.set_auto_close(params[:auto_close_time], current_user)
|
||||||
@topic.save
|
if topic.save
|
||||||
render nothing: true
|
render json: success_json.merge!(auto_close_at: topic.auto_close_at)
|
||||||
|
else
|
||||||
|
render_json_error(topic)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def destroy
|
def destroy
|
||||||
|
|
|
@ -146,7 +146,7 @@ class Topic < ActiveRecord::Base
|
||||||
self.bumped_at ||= Time.now
|
self.bumped_at ||= Time.now
|
||||||
self.last_post_user_id ||= user_id
|
self.last_post_user_id ||= user_id
|
||||||
if !@ignore_category_auto_close and self.category and self.category.auto_close_days and self.auto_close_at.nil?
|
if !@ignore_category_auto_close and self.category and self.category.auto_close_days and self.auto_close_at.nil?
|
||||||
set_auto_close(self.category.auto_close_days)
|
set_auto_close(self.category.auto_close_days * 24)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -602,9 +602,10 @@ class Topic < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# TODO: change this method, along with category's auto_close_days. Use hours.
|
||||||
def auto_close_days=(num_days)
|
def auto_close_days=(num_days)
|
||||||
@ignore_category_auto_close = true
|
@ignore_category_auto_close = true
|
||||||
set_auto_close(num_days)
|
set_auto_close(num_days * 24)
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.auto_close
|
def self.auto_close
|
||||||
|
@ -622,10 +623,27 @@ class Topic < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def set_auto_close(num_days, by_user=nil)
|
# Valid arguments for the auto close time:
|
||||||
num_days = num_days.to_i
|
# * An integer, which is the number of hours from now to close the topic.
|
||||||
self.auto_close_at = (num_days > 0 ? num_days.days.from_now : nil)
|
# * A time, like "12:00", which is the time at which the topic will close in the current day
|
||||||
if num_days > 0
|
# or the next day if that time has already passed today.
|
||||||
|
# * A timestamp, like "2013-11-25 13:00", when the topic should close.
|
||||||
|
# * A timestamp with timezone in JSON format. (e.g., "2013-11-26T21:00:00.000Z")
|
||||||
|
# * nil, to prevent the topic from automatically closing.
|
||||||
|
def set_auto_close(arg, by_user=nil)
|
||||||
|
if arg.is_a?(String) and matches = /^([\d]{1,2}):([\d]{1,2})$/.match(arg.strip)
|
||||||
|
now = Time.zone.now
|
||||||
|
self.auto_close_at = Time.zone.local(now.year, now.month, now.day, matches[1].to_i, matches[2].to_i)
|
||||||
|
self.auto_close_at += 1.day if self.auto_close_at < now
|
||||||
|
elsif arg.is_a?(String) and arg.include?('-') and timestamp = Time.zone.parse(arg)
|
||||||
|
self.auto_close_at = timestamp
|
||||||
|
self.errors.add(:auto_close_at, :invalid) if timestamp < Time.zone.now
|
||||||
|
else
|
||||||
|
num_hours = arg.to_i
|
||||||
|
self.auto_close_at = (num_hours > 0 ? num_hours.hours.from_now : nil)
|
||||||
|
end
|
||||||
|
|
||||||
|
unless self.auto_close_at.nil?
|
||||||
self.auto_close_started_at ||= Time.zone.now
|
self.auto_close_started_at ||= Time.zone.now
|
||||||
if by_user and by_user.staff?
|
if by_user and by_user.staff?
|
||||||
self.auto_close_user = by_user
|
self.auto_close_user = by_user
|
||||||
|
|
|
@ -517,8 +517,10 @@ en:
|
||||||
toggler: "hide or show the composer panel"
|
toggler: "hide or show the composer panel"
|
||||||
|
|
||||||
admin_options_title: "Optional staff settings for this topic"
|
admin_options_title: "Optional staff settings for this topic"
|
||||||
auto_close_label: "Auto-close topic after:"
|
auto_close_label: "Auto-close topic time:"
|
||||||
auto_close_units: "days"
|
auto_close_units: "(# of hours, a time, or a timestamp)"
|
||||||
|
auto_close_examples: 'Examples: 24, 17:00, 2013-11-22 14:00'
|
||||||
|
auto_close_error: "Please enter a valid value."
|
||||||
|
|
||||||
notifications:
|
notifications:
|
||||||
title: "notifications of @name mentions, replies to your posts and topics, private messages, etc"
|
title: "notifications of @name mentions, replies to your posts and topics, private messages, etc"
|
||||||
|
|
|
@ -16,7 +16,7 @@ class TopicCreator
|
||||||
topic_params = setup
|
topic_params = setup
|
||||||
@topic = Topic.new(topic_params)
|
@topic = Topic.new(topic_params)
|
||||||
|
|
||||||
setup_auto_close_days if @opts[:auto_close_days]
|
setup_auto_close_time if @opts[:auto_close_time]
|
||||||
|
|
||||||
process_private_message if @opts[:archetype] == Archetype.private_message
|
process_private_message if @opts[:archetype] == Archetype.private_message
|
||||||
save_topic
|
save_topic
|
||||||
|
@ -55,9 +55,9 @@ class TopicCreator
|
||||||
topic_params
|
topic_params
|
||||||
end
|
end
|
||||||
|
|
||||||
def setup_auto_close_days
|
def setup_auto_close_time
|
||||||
@guardian.ensure_can_moderate!(@topic)
|
@guardian.ensure_can_moderate!(@topic)
|
||||||
@topic.auto_close_days = @opts[:auto_close_days]
|
@topic.set_auto_close(@opts[:auto_close_time], @user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def process_private_message
|
def process_private_message
|
||||||
|
|
|
@ -190,7 +190,7 @@ describe PostCreator do
|
||||||
it 'ensures the user can auto-close the topic' do
|
it 'ensures the user can auto-close the topic' do
|
||||||
Guardian.any_instance.stubs(:can_moderate?).returns(false)
|
Guardian.any_instance.stubs(:can_moderate?).returns(false)
|
||||||
expect {
|
expect {
|
||||||
PostCreator.new(user, basic_topic_params.merge(auto_close_days: 2)).create
|
PostCreator.new(user, basic_topic_params.merge(auto_close_time: 2)).create
|
||||||
}.to raise_error(Discourse::InvalidAccess)
|
}.to raise_error(Discourse::InvalidAccess)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -739,12 +739,12 @@ describe TopicsController do
|
||||||
describe 'autoclose' do
|
describe 'autoclose' do
|
||||||
|
|
||||||
it 'needs you to be logged in' do
|
it 'needs you to be logged in' do
|
||||||
lambda { xhr :put, :autoclose, topic_id: 99, auto_close_days: 3}.should raise_error(Discourse::NotLoggedIn)
|
lambda { xhr :put, :autoclose, topic_id: 99, auto_close_time: '24'}.should raise_error(Discourse::NotLoggedIn)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'needs you to be an admin or mod' do
|
it 'needs you to be an admin or mod' do
|
||||||
user = log_in
|
user = log_in
|
||||||
xhr :put, :autoclose, topic_id: 99, auto_close_days: 3
|
xhr :put, :autoclose, topic_id: 99, auto_close_time: '24'
|
||||||
response.should be_forbidden
|
response.should be_forbidden
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -755,13 +755,15 @@ describe TopicsController do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can set a topic's auto close time" do
|
it "can set a topic's auto close time" do
|
||||||
Topic.any_instance.expects(:set_auto_close).with("3", @admin)
|
Topic.any_instance.expects(:set_auto_close).with("24", @admin)
|
||||||
xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: 3
|
xhr :put, :autoclose, topic_id: @topic.id, auto_close_time: '24'
|
||||||
|
json = ::JSON.parse(response.body)
|
||||||
|
json.should have_key('auto_close_at')
|
||||||
end
|
end
|
||||||
|
|
||||||
it "can remove a topic's auto close time" do
|
it "can remove a topic's auto close time" do
|
||||||
Topic.any_instance.expects(:set_auto_close).with(nil, anything)
|
Topic.any_instance.expects(:set_auto_close).with(nil, anything)
|
||||||
xhr :put, :autoclose, topic_id: @topic.id, auto_close_days: nil
|
xhr :put, :autoclose, topic_id: @topic.id, auto_close_time: nil
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1074,13 +1074,56 @@ describe Topic do
|
||||||
|
|
||||||
before { Discourse.stubs(:system_user).returns(admin) }
|
before { Discourse.stubs(:system_user).returns(admin) }
|
||||||
|
|
||||||
it 'sets auto_close_at' do
|
it 'can take a number of hours as an integer' do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
topic.set_auto_close(3, admin)
|
topic.set_auto_close(72, admin)
|
||||||
expect(topic.auto_close_at).to eq(3.days.from_now)
|
expect(topic.auto_close_at).to eq(3.days.from_now)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
it 'can take a number of hours as a string' do
|
||||||
|
Timecop.freeze(Time.zone.now) do
|
||||||
|
topic.set_auto_close('18', admin)
|
||||||
|
expect(topic.auto_close_at).to eq(18.hours.from_now)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can take a time later in the day" do
|
||||||
|
Timecop.freeze(Time.zone.local(2013,11,20,8,0)) do
|
||||||
|
topic.set_auto_close('13:00', admin)
|
||||||
|
topic.auto_close_at.should == Time.zone.local(2013,11,20,13,0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can take a time for the next day" do
|
||||||
|
Timecop.freeze(Time.zone.local(2013,11,20,8,0)) do
|
||||||
|
topic.set_auto_close('5:00', admin)
|
||||||
|
topic.auto_close_at.should == Time.zone.local(2013,11,21,5,0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can take a timestamp for a future time" do
|
||||||
|
Timecop.freeze(Time.zone.local(2013,11,20,8,0)) do
|
||||||
|
topic.set_auto_close('2013-11-22 5:00', admin)
|
||||||
|
topic.auto_close_at.should == Time.zone.local(2013,11,22,5,0)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "sets a validation error when given a timestamp in the past" do
|
||||||
|
Timecop.freeze(Time.zone.local(2013,11,20,8,0)) do
|
||||||
|
topic.set_auto_close('2013-11-19 5:00', admin)
|
||||||
|
topic.auto_close_at.should == Time.zone.local(2013,11,19,5,0)
|
||||||
|
topic.errors[:auto_close_at].should be_present
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
it "can take a timestamp with timezone" do
|
||||||
|
Timecop.freeze(Time.utc(2013,11,20,12,0)) do
|
||||||
|
topic.set_auto_close('2013-11-25T01:35:00-08:00', admin)
|
||||||
|
topic.auto_close_at.should == Time.utc(2013,11,25,9,35)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'sets auto_close_user to given user if it is a staff user' do
|
it 'sets auto_close_user to given user if it is a staff user' do
|
||||||
topic.set_auto_close(3, admin)
|
topic.set_auto_close(3, admin)
|
||||||
expect(topic.auto_close_user_id).to eq(admin.id)
|
expect(topic.auto_close_user_id).to eq(admin.id)
|
||||||
|
@ -1102,20 +1145,20 @@ describe Topic do
|
||||||
expect(staff_topic.auto_close_user_id).to eq(999)
|
expect(staff_topic.auto_close_user_id).to eq(999)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'clears auto_close_at if num_days is nil' do
|
it 'clears auto_close_at if arg is nil' do
|
||||||
closing_topic.set_auto_close(nil)
|
closing_topic.set_auto_close(nil)
|
||||||
expect(closing_topic.auto_close_at).to be_nil
|
expect(closing_topic.auto_close_at).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'clears auto_close_started_at if num_days is nil' do
|
it 'clears auto_close_started_at if arg is nil' do
|
||||||
closing_topic.set_auto_close(nil)
|
closing_topic.set_auto_close(nil)
|
||||||
expect(closing_topic.auto_close_started_at).to be_nil
|
expect(closing_topic.auto_close_started_at).to be_nil
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'updates auto_close_at if it was already set to close' do
|
it 'updates auto_close_at if it was already set to close' do
|
||||||
Timecop.freeze(Time.zone.now) do
|
Timecop.freeze(Time.zone.now) do
|
||||||
closing_topic.set_auto_close(14)
|
closing_topic.set_auto_close(48)
|
||||||
expect(closing_topic.auto_close_at).to eq(14.days.from_now)
|
expect(closing_topic.auto_close_at).to eq(2.days.from_now)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue