mirror of
https://github.com/discourse/discourse.git
synced 2025-01-18 10:42:45 +08:00
UX: Allow users to remove a remind me topic timer.
This commit is contained in:
parent
f5a2ed99b0
commit
b0557c6692
|
@ -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);
|
||||
}
|
||||
});
|
|
@ -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'));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -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');
|
||||
},
|
||||
|
|
|
@ -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>
|
|
@ -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>
|
||||
|
|
|
@ -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 }}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user