FIX: Autoclose message was not correct when immediate
FEATURE: Warn when setting auto-close for right now
This commit is contained in:
parent
b09ee9cb82
commit
e52852dd0f
|
@ -5,6 +5,8 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
|||
export default Ember.Controller.extend(ModalFunctionality, {
|
||||
auto_close_valid: true,
|
||||
auto_close_invalid: Em.computed.not('auto_close_valid'),
|
||||
disable_submit: Em.computed.or('auto_close_invalid', 'loading'),
|
||||
loading: false,
|
||||
|
||||
@observes("model.details.auto_close_at", "model.details.auto_close_hours")
|
||||
setAutoCloseTime() {
|
||||
|
@ -29,7 +31,7 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
|||
|
||||
setAutoClose(time) {
|
||||
const self = this;
|
||||
this.send('hideModal');
|
||||
this.set('loading', true);
|
||||
Discourse.ajax({
|
||||
url: `/t/${this.get('model.id')}/autoclose`,
|
||||
type: 'PUT',
|
||||
|
@ -40,16 +42,34 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
|||
timezone_offset: (new Date().getTimezoneOffset())
|
||||
}
|
||||
}).then(result => {
|
||||
self.set('loading', false);
|
||||
if (result.success) {
|
||||
this.send('closeModal');
|
||||
this.set('model.details.auto_close_at', result.auto_close_at);
|
||||
this.set('model.details.auto_close_hours', result.auto_close_hours);
|
||||
} else {
|
||||
bootbox.alert(I18n.t('composer.auto_close.error'), function() { self.send('reopenModal'); } );
|
||||
bootbox.alert(I18n.t('composer.auto_close.error'));
|
||||
}
|
||||
}).catch(() => {
|
||||
bootbox.alert(I18n.t('composer.auto_close.error'), function() { self.send('reopenModal'); } );
|
||||
// TODO - incorrectly responds to network errors as bad input
|
||||
bootbox.alert(I18n.t('composer.auto_close.error'));
|
||||
self.set('loading', false);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
willCloseImmediately: function() {
|
||||
if (!this.get('model.details.auto_close_based_on_last_post')) {
|
||||
return false;
|
||||
}
|
||||
let closeDate = new Date(this.get('model.last_posted_at'));
|
||||
closeDate.setHours(closeDate.getHours() + this.get('model.auto_close_time'));
|
||||
return closeDate < new Date();
|
||||
}.property('model.details.auto_close_based_on_last_post', 'model.auto_close_time', 'model.last_posted_at'),
|
||||
|
||||
willCloseI18n: function() {
|
||||
if (this.get('model.details.auto_close_based_on_last_post')) {
|
||||
return I18n.t('topic.auto_close_immediate', {hours: this.get('model.auto_close_time')});
|
||||
}
|
||||
}.property('model.details.auto_close_based_on_last_post', 'model.auto_close_time')
|
||||
|
||||
});
|
||||
|
|
|
@ -340,6 +340,13 @@ const Topic = RestModel.extend({
|
|||
keys.forEach(key => this.set(key, json[key]));
|
||||
},
|
||||
|
||||
reload() {
|
||||
const self = this;
|
||||
return Discourse.ajax('/t/' + this.get('id'), { type: 'GET' }).then(function(topic_json) {
|
||||
self.updateFromJson(topic_json);
|
||||
});
|
||||
},
|
||||
|
||||
isPinnedUncategorized: function() {
|
||||
return this.get('pinned') && this.get('category.isUncategorizedCategory');
|
||||
}.property('pinned', 'category.isUncategorizedCategory'),
|
||||
|
|
|
@ -4,10 +4,17 @@
|
|||
autoCloseValid=auto_close_valid
|
||||
autoCloseBasedOnLastPost=model.details.auto_close_based_on_last_post
|
||||
limited=model.details.auto_close_based_on_last_post }}
|
||||
{{#if willCloseImmediately}}
|
||||
<div class="warning">
|
||||
{{fa-icon "warning"}}
|
||||
{{willCloseI18n}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
{{d-button class="btn-primary" disabled=auto_close_invalid label="topic.auto_close_save" action="saveAutoClose"}}
|
||||
{{d-button class="btn-primary" disabled=disable_submit label="topic.auto_close_save" action="saveAutoClose"}}
|
||||
<a {{action "closeModal"}}>{{i18n 'cancel'}}</a>
|
||||
{{conditional-loading-spinner size="small" condition=loading}}
|
||||
{{d-button class="pull-right" action="removeAutoClose" label="topic.auto_close_remove"}}
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -835,10 +835,12 @@ class Topic < ActiveRecord::Base
|
|||
self.auto_close_at = utc.local(now.year, now.month, now.day, m[1].to_i, m[2].to_i)
|
||||
self.auto_close_at += offset_minutes * 60 if offset_minutes
|
||||
self.auto_close_at += 1.day if self.auto_close_at < now
|
||||
self.auto_close_hours = -1
|
||||
elsif arg.is_a?(String) && arg.include?("-") && timestamp = utc.parse(arg)
|
||||
# a timestamp in client's time zone, like "2015-5-27 12:00"
|
||||
self.auto_close_at = timestamp
|
||||
self.auto_close_at += offset_minutes * 60 if offset_minutes
|
||||
self.auto_close_hours = -1
|
||||
self.errors.add(:auto_close_at, :invalid) if timestamp < Time.zone.now
|
||||
else
|
||||
num_hours = arg.to_f
|
||||
|
@ -864,6 +866,10 @@ class Topic < ActiveRecord::Base
|
|||
else
|
||||
self.auto_close_user ||= (self.user.staff? || self.user.trust_level == TrustLevel[4] ? self.user : Discourse.system_user)
|
||||
end
|
||||
|
||||
if self.auto_close_at.try(:<, Time.zone.now)
|
||||
auto_close(auto_close_user)
|
||||
end
|
||||
end
|
||||
|
||||
self
|
||||
|
|
|
@ -52,7 +52,16 @@ TopicStatusUpdate = Struct.new(:topic, :user) do
|
|||
end
|
||||
|
||||
def message_for_autoclosed(locale_key)
|
||||
num_minutes = topic.auto_close_started_at ? ((Time.zone.now - topic.auto_close_started_at) / 1.minute).round : topic.age_in_minutes
|
||||
num_minutes = ((
|
||||
if topic.auto_close_based_on_last_post
|
||||
topic.auto_close_hours.hours
|
||||
elsif topic.auto_close_started_at
|
||||
Time.zone.now - topic.auto_close_started_at
|
||||
else
|
||||
Time.zone.now - topic.created_at
|
||||
end
|
||||
) / 1.minute).round
|
||||
|
||||
if num_minutes.minutes >= 2.days
|
||||
I18n.t("#{locale_key}_days", count: (num_minutes.minutes / 1.day).round)
|
||||
else
|
||||
|
|
|
@ -1142,6 +1142,7 @@ en:
|
|||
auto_close_title: 'Auto-Close Settings'
|
||||
auto_close_save: "Save"
|
||||
auto_close_remove: "Don't Auto-Close This Topic"
|
||||
auto_close_immediate: "The last post in the topic is already %{hours} hours old, so the topic will be closed immediately."
|
||||
|
||||
progress:
|
||||
title: topic progress
|
||||
|
|
|
@ -1036,6 +1036,46 @@ describe TopicsController do
|
|||
Topic.any_instance.expects(:set_auto_close).with(nil, anything)
|
||||
xhr :put, :autoclose, topic_id: @topic.id, auto_close_time: nil, auto_close_based_on_last_post: false, timezone_offset: -240
|
||||
end
|
||||
|
||||
it "will close a topic when the time expires" do
|
||||
topic = Fabricate(:topic)
|
||||
Timecop.freeze(20.hours.ago) do
|
||||
create_post(topic: topic, raw: "This is the body of my cool post in the topic, but it's a bit old now")
|
||||
end
|
||||
topic.save
|
||||
|
||||
Jobs.expects(:enqueue_at).at_least_once
|
||||
xhr :put, :autoclose, topic_id: topic.id, auto_close_time: 24, auto_close_based_on_last_post: true
|
||||
|
||||
topic.reload
|
||||
expect(topic.closed).to eq(false)
|
||||
expect(topic.posts.last.raw).to match(/cool post/)
|
||||
|
||||
Timecop.freeze(5.hours.from_now) do
|
||||
Jobs::CloseTopic.new.execute({topic_id: topic.id, user_id: @admin.id})
|
||||
end
|
||||
|
||||
topic.reload
|
||||
expect(topic.closed).to eq(true)
|
||||
expect(topic.posts.last.raw).to match(/automatically closed/)
|
||||
end
|
||||
|
||||
it "will immediately close if the last post is old enough" do
|
||||
topic = Fabricate(:topic)
|
||||
Timecop.freeze(20.hours.ago) do
|
||||
create_post(topic: topic)
|
||||
end
|
||||
topic.save
|
||||
Topic.reset_highest(topic.id)
|
||||
topic.reload
|
||||
|
||||
xhr :put, :autoclose, topic_id: topic.id, auto_close_time: 10, auto_close_based_on_last_post: true
|
||||
|
||||
topic.reload
|
||||
expect(topic.closed).to eq(true)
|
||||
expect(topic.posts.last.raw).to match(/after the last reply/)
|
||||
expect(topic.posts.last.raw).to match(/10 hours/)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -3,18 +3,21 @@
|
|||
require 'rails_helper'
|
||||
require_dependency 'post_destroyer'
|
||||
|
||||
# TODO - test pinning, create_moderator_post
|
||||
|
||||
describe TopicStatusUpdate do
|
||||
|
||||
let(:user) { Fabricate(:user) }
|
||||
let(:admin) { Fabricate(:admin) }
|
||||
|
||||
it "avoids notifying on automatically closed topics" do
|
||||
# TODO: TopicStatusUpdate should supress message bus updates from the users it "pretends to read"
|
||||
# TODO: TopicStatusUpdate should suppress message bus updates from the users it "pretends to read"
|
||||
post = PostCreator.create(user,
|
||||
raw: "this is a test post 123 this is a test post",
|
||||
title: "hello world title",
|
||||
)
|
||||
# TODO needed so counts sync up, PostCreator really should not give back out-of-date Topic
|
||||
post.topic.set_auto_close('10')
|
||||
post.topic.reload
|
||||
|
||||
TopicStatusUpdate.new(post.topic, admin).update!("autoclosed", true)
|
||||
|
@ -27,6 +30,7 @@ describe TopicStatusUpdate do
|
|||
|
||||
it "adds an autoclosed message" do
|
||||
topic = create_topic
|
||||
topic.set_auto_close('10')
|
||||
|
||||
TopicStatusUpdate.new(topic, admin).update!("autoclosed", true)
|
||||
|
||||
|
@ -39,13 +43,14 @@ describe TopicStatusUpdate do
|
|||
it "adds an autoclosed message based on last post" do
|
||||
topic = create_topic
|
||||
topic.auto_close_based_on_last_post = true
|
||||
topic.set_auto_close('10')
|
||||
|
||||
TopicStatusUpdate.new(topic, admin).update!("autoclosed", true)
|
||||
|
||||
last_post = topic.posts.last
|
||||
expect(last_post.post_type).to eq(Post.types[:small_action])
|
||||
expect(last_post.action_code).to eq('autoclosed.enabled')
|
||||
expect(last_post.raw).to eq(I18n.t("topic_statuses.autoclosed_enabled_lastpost_minutes", count: 0))
|
||||
expect(last_post.raw).to eq(I18n.t("topic_statuses.autoclosed_enabled_lastpost_hours", count: 10))
|
||||
end
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue