UX: Allow users to remove a remind me topic timer.

This commit is contained in:
Guo Xiang Tan 2017-10-05 11:48:42 +08:00
parent f5a2ed99b0
commit b0557c6692
12 changed files with 213 additions and 108 deletions

View File

@ -0,0 +1,50 @@
import { default as computed, observes, on } from "ember-addons/ember-computed-decorators";
import {
PUBLISH_TO_CATEGORY_STATUS_TYPE,
OPEN_STATUS_TYPE,
DELETE_STATUS_TYPE,
REMINDER_TYPE,
CLOSE_STATUS_TYPE
} from 'discourse/controllers/edit-topic-timer';
export default Ember.Component.extend({
selection: Ember.computed.alias('topicTimer.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),
publishToCategory: Ember.computed.equal('selection', PUBLISH_TO_CATEGORY_STATUS_TYPE),
reminder: Ember.computed.equal('selection', REMINDER_TYPE),
showTimeOnly: Ember.computed.or('autoOpen', 'autoDelete', 'reminder'),
@computed('topicTimer.updateTime', 'loading', 'publishToCategory', 'topicTimer.category_id')
saveDisabled(updateTime, loading, publishToCategory, topicTimerCategoryId) {
return Ember.isEmpty(updateTime) ||
loading ||
(publishToCategory && !topicTimerCategoryId);
},
@computed("topic.visible")
excludeCategoryId(visible) {
if (visible) return this.get('topic.category_id');
},
@on('init')
@observes("topicTimer", "topicTimer.execute_at", "topicTimer.duration")
_setUpdateTime() {
let time = null;
const executeAt = this.get('topicTimer.execute_at');
if (executeAt && this.get("topicTimer.based_on_last_post")) {
time = this.get("topicTimer.duration");
} else if (executeAt) {
const closeTime = moment(executeAt);
if (closeTime > moment()) {
time = closeTime.format("YYYY-MM-DD HH:mm");
}
}
this.set("topicTimer.updateTime", time);
}
});

View File

@ -1,67 +1,51 @@
import { default as computed, observes } from "ember-addons/ember-computed-decorators";
import { default as computed } from "ember-addons/ember-computed-decorators";
import ModalFunctionality from 'discourse/mixins/modal-functionality';
import TopicTimer from 'discourse/models/topic-timer';
import { popupAjaxError } from 'discourse/lib/ajax-error';
export const CLOSE_STATUS_TYPE = 'close';
const OPEN_STATUS_TYPE = 'open';
export const OPEN_STATUS_TYPE = 'open';
export const PUBLISH_TO_CATEGORY_STATUS_TYPE = 'publish_to_category';
const DELETE_STATUS_TYPE = 'delete';
const REMINDER_TYPE = 'reminder';
export const DELETE_STATUS_TYPE = 'delete';
export const REMINDER_TYPE = 'reminder';
export default Ember.Controller.extend(ModalFunctionality, {
loading: false,
updateTime: null,
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),
publishToCategory: Ember.computed.equal('selection', PUBLISH_TO_CATEGORY_STATUS_TYPE),
reminder: Ember.computed.equal('selection', REMINDER_TYPE),
showTimeOnly: Ember.computed.or('autoOpen', 'autoDelete', 'reminder'),
isPublic: "true",
@computed("model.closed")
timerTypes(closed) {
publicTimerTypes(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') },
{ id: PUBLISH_TO_CATEGORY_STATUS_TYPE, name: I18n.t('topic.publish_to_category.title') },
{ id: DELETE_STATUS_TYPE, name: I18n.t('topic.auto_delete.title') },
{ id: DELETE_STATUS_TYPE, name: I18n.t('topic.auto_delete.title') }
];
},
@computed()
privateTimerTypes() {
return [
{ id: REMINDER_TYPE, name: I18n.t('topic.reminder.title') }
];
},
@computed('updateTime', 'loading', 'publishToCategory', 'topicTimer.category_id')
saveDisabled(updateTime, loading, publishToCategory, topicTimerCategoryId) {
return Ember.isEmpty(updateTime) ||
loading ||
(publishToCategory && !topicTimerCategoryId);
},
@computed("model.visible")
excludeCategoryId(visible) {
if (visible) return this.get('model.category_id');
},
@observes("topicTimer.execute_at", "topicTimer.duration")
_setUpdateTime() {
if (!this.get('topicTimer.execute_at')) return;
let time = null;
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");
}
@computed("isPublic", 'publicTimerTypes', 'privateTimerTypes')
selections(isPublic, publicTimerTypes, privateTimerTypes) {
if (isPublic === 'true') {
return publicTimerTypes;
} else {
return privateTimerTypes;
}
},
this.set("updateTime", time);
@computed('isPublic', 'model.topic_timer', 'model.private_topic_timer')
topicTimer(isPublic, publicTopicTimer, privateTopicTimer) {
if (isPublic === 'true') {
return publicTopicTimer;
} else {
return privateTopicTimer;
}
},
_setTimer(time, statusType) {
@ -85,10 +69,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
this.set('model.closed', result.closed);
} else {
const topicTimer = this.get('isPublic') === 'true' ? 'topic_timer' : 'private_topic_timer';
this.set(`model.${topicTimer}`, Ember.Object.create({}));
this.setProperties({
topicTimer: Ember.Object.create({}),
selection: null,
updateTime: null
});
}
}).catch(error => {
@ -98,11 +83,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
actions: {
saveTimer() {
this._setTimer(this.get("updateTime"), this.get('selection'));
this._setTimer(this.get("topicTimer.updateTime"), this.get('topicTimer.status_type'));
},
removeTimer() {
this._setTimer(null, this.get('selection'));
this._setTimer(null, this.get('topicTimer.status_type'));
}
}
});

View File

@ -54,6 +54,7 @@ const TopicRoute = Discourse.Route.extend({
showTopicStatusUpdate() {
const model = this.modelFor('topic');
model.set('topic_timer', Ember.Object.create(model.get('topic_timer')));
model.set('private_topic_timer', Ember.Object.create(model.get('private_topic_timer')));
showModal('edit-topic-timer', { model });
this.controllerFor('modal').set('modalClass', 'edit-topic-timer-modal');
},

View File

@ -0,0 +1,36 @@
<form>
<div class="control-group">
{{combo-box content=timerTypes value=selection width="50%"}}
</div>
<div>
{{#if showTimeOnly}}
{{future-date-input
input=topicTimer.updateTime
statusType=selection
includeWeekend=true
basedOnLastPost=false}}
{{else if publishToCategory}}
<div class="control-group">
<label>{{i18n 'topic.topic_status_update.publish_to'}}</label>
{{category-select-box
value=topicTimer.category_id
excludeCategoryId=excludeCategoryId}}
</div>
{{future-date-input
input=topicTimer.updateTime
statusType=selection
includeWeekend=true
categoryId=topicTimer.category_id
basedOnLastPost=false}}
{{else if autoClose}}
{{future-date-input
input=topicTimer.updateTime
statusType=selection
includeWeekend=true
basedOnLastPost=topicTimer.based_on_last_post
lastPostedAt=model.last_posted_at}}
{{/if}}
</div>
</form>

View File

@ -1,54 +1,35 @@
<form>
{{#d-modal-body title="topic.topic_status_update.title" autoFocus="false"}}
<div class="control-group">
{{combo-box content=timerTypes value=selection width="50%"}}
</div>
{{#d-modal-body title="topic.topic_status_update.title" autoFocus="false"}}
<div class="radios">
<label for="public-topic-timer">
{{radio-button id='public-topic-timer' name="topic-timer" value="true" selection=isPublic}}
<b>{{i18n 'topic.topic_status_update.public_timer_types'}}</b>
</label>
<div>
{{#if showTimeOnly}}
{{future-date-input
input=updateTime
statusType=selection
includeWeekend=true
basedOnLastPost=false}}
{{else if publishToCategory}}
<div class="control-group">
<label>{{i18n 'topic.topic_status_update.publish_to'}}</label>
{{category-select-box
value=topicTimer.category_id
excludeCategoryId=excludeCategoryId}}
</div>
{{future-date-input
input=updateTime
statusType=selection
includeWeekend=true
categoryId=topicTimer.category_id
basedOnLastPost=false}}
{{else if autoClose}}
{{future-date-input
input=updateTime
statusType=selection
includeWeekend=true
basedOnLastPost=topicTimer.based_on_last_post
lastPostedAt=model.last_posted_at}}
{{/if}}
</div>
{{/d-modal-body}}
<div class="modal-footer">
{{d-button class="btn-primary"
disabled=saveDisabled
label="topic.topic_status_update.save"
action="saveTimer"}}
{{d-modal-cancel close=(action "closeModal")}}
{{conditional-loading-spinner size="small" condition=loading}}
{{#if topicTimer.execute_at}}
{{d-button class="pull-right btn-danger"
action="removeTimer"
label='topic.topic_status_update.remove'}}
{{/if}}
<label for="private-topic-timer">
{{radio-button id='private-topic-timer' name="topic-timer" value="false" selection=isPublic}}
<b>{{i18n 'topic.topic_status_update.private_timer_types'}}</b>
</label>
</div>
</form>
{{edit-topic-timer-form
topic=model
topicTimer=topicTimer
timerTypes=selections
updateTime=updateTime
closeModal="closeModal"}}
{{/d-modal-body}}
<div class="modal-footer">
{{d-button class="btn-primary"
disabled=saveDisabled
label="topic.topic_status_update.save"
action="saveTimer"}}
{{conditional-loading-spinner size="small" condition=loading}}
{{#if topicTimer.execute_at}}
{{d-button class="pull-right btn-danger"
action="removeTimer"
label='topic.topic_status_update.remove'}}
{{/if}}
</div>

View File

@ -199,12 +199,21 @@
</div>
{{/if}}
{{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 model.private_topic_timer.execute_at}}
{{topic-timer-info
statusType=model.private_topic_timer.status_type
executeAt=model.private_topic_timer.execute_at
duration=model.private_topic_timer.duration}}
{{/if}}
{{#if model.topic_timer.execute_at}}
{{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}}
{{#if session.showSignupCta}}
{{! replace "Log In to Reply" with the infobox }}

View File

@ -8,8 +8,18 @@
text-align: left;
}
.radios {
margin-bottom: 10px;
}
label {
vertical-align: middle;
display: inline-block;
padding-right: 5px;
input {
vertical-align: middle;
}
}
.btn.pull-right {

View File

@ -69,8 +69,8 @@
}
.topic-status-info {
border-top: 1px solid $primary-low;
padding-top: 10px;
border-top: 1px solid $primary-low;
padding: 10px 0px;
height: 20px;
max-width: 757px;
}

View File

@ -411,6 +411,7 @@ class Topic < ActiveRecord::Base
def reload(options = nil)
@post_numbers = nil
@public_topic_timer = nil
@private_topic_timer = nil
super(options)
end
@ -1002,6 +1003,10 @@ SQL
@public_topic_timer ||= topic_timers.find_by(deleted_at: nil, public_type: true)
end
def private_topic_timer(user)
@private_topic_Timer ||= topic_timers.find_by(deleted_at: nil, public_type: false, user_id: user.id)
end
def delete_topic_timer(status_type, by_user: Discourse.system_user)
options = { status_type: status_type }
options.merge!(user: by_user) unless TopicTimer.public_types[status_type]

View File

@ -61,6 +61,7 @@ class TopicViewSerializer < ApplicationSerializer
:message_archived,
:tags,
:topic_timer,
:private_topic_timer,
:unicode_title,
:message_bus_last_id,
:participant_count
@ -242,6 +243,15 @@ class TopicViewSerializer < ApplicationSerializer
TopicTimerSerializer.new(object.topic.public_topic_timer, root: false)
end
def include_private_topic_timer?
scope.user
end
def private_topic_timer
timer = object.topic.private_topic_timer(scope.user)
TopicTimerSerializer.new(timer, root: false)
end
def tags
object.topic.tags.map(&:name)
end

View File

@ -1555,12 +1555,14 @@ en:
deleted: "The topic has been deleted"
topic_status_update:
title: "Set Topic Timer"
title: "Topic Timer"
save: "Set Timer"
num_of_hours: "Number of hours:"
remove: "Remove Timer"
publish_to: "Publish To:"
when: "When:"
public_timer_types: Topic Timers
private_timer_types: User Topic Timers
auto_update_input:
none: ""
later_today: "Later today"

View File

@ -1167,6 +1167,22 @@ describe Topic do
end
end
describe '#private_topic_timer' do
let(:user) { Fabricate(:user) }
let(:topic_timer) do
Fabricate(:topic_timer,
public_type: false,
user: user,
status_type: TopicTimer.private_types[:reminder]
)
end
it 'should return the right record' do
expect(topic_timer.topic.private_topic_timer(user)).to eq(topic_timer)
end
end
describe '#set_or_create_timer' do
let(:topic) { Fabricate.build(:topic) }