UX: Improve the way users set timers for `TopicStatusUpdate`.
This commit is contained in:
parent
0f2e2ea175
commit
5c39c8f24b
|
@ -11,12 +11,14 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
buildBuffer(buffer) {
|
buildBuffer(buffer) {
|
||||||
const nameProperty = this.get('nameProperty');
|
const nameProperty = this.get('nameProperty');
|
||||||
const none = this.get('none');
|
const none = this.get('none');
|
||||||
|
let noneValue = null;
|
||||||
|
|
||||||
// Add none option if required
|
// Add none option if required
|
||||||
if (typeof none === "string") {
|
if (typeof none === "string") {
|
||||||
buffer.push('<option value="">' + I18n.t(none) + "</option>");
|
buffer.push('<option value="">' + I18n.t(none) + "</option>");
|
||||||
} else if (typeof none === "object") {
|
} else if (typeof none === "object") {
|
||||||
buffer.push("<option value=\"\">" + Em.get(none, nameProperty) + "</option>");
|
noneValue = Em.get(none, this.get('valueAttribute'));
|
||||||
|
buffer.push(`<option value="${noneValue}">${Em.get(none, nameProperty)}</option>`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let selected = this.get('value');
|
let selected = this.get('value');
|
||||||
|
@ -47,7 +49,7 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!selectedFound) {
|
if (!selectedFound && !noneValue) {
|
||||||
if (none) {
|
if (none) {
|
||||||
this.set('value', null);
|
this.set('value', null);
|
||||||
} else {
|
} else {
|
||||||
|
@ -89,7 +91,8 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
|
|
||||||
const $elem = this.$();
|
const $elem = this.$();
|
||||||
const caps = this.capabilities;
|
const caps = this.capabilities;
|
||||||
const minimumResultsForSearch = (caps && caps.isIOS) ? -1 : 5;
|
const minimumResultsForSearch = this.get('minimumResultsForSearch') || ((caps && caps.isIOS) ? -1 : 5);
|
||||||
|
|
||||||
if (!this.get("selectionTemplate") && this.get("selectionIcon")) {
|
if (!this.get("selectionTemplate") && this.get("selectionIcon")) {
|
||||||
this.selectionTemplate = (item) => {
|
this.selectionTemplate = (item) => {
|
||||||
let name = Em.get(item, 'text');
|
let name = Em.get(item, 'text');
|
||||||
|
@ -97,13 +100,22 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
return `<i class='fa fa-${this.get("selectionIcon")}'></i>${name}`;
|
return `<i class='fa fa-${this.get("selectionIcon")}'></i>${name}`;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
$elem.select2({
|
|
||||||
formatResult: this.comboTemplate,
|
const options = {
|
||||||
formatSelection: this.selectionTemplate,
|
|
||||||
minimumResultsForSearch,
|
minimumResultsForSearch,
|
||||||
width: this.get('width') || 'resolve',
|
width: this.get('width') || 'resolve',
|
||||||
allowClear: true
|
allowClear: true
|
||||||
});
|
};
|
||||||
|
|
||||||
|
if (this.comboTemplate) {
|
||||||
|
options.formatResult = this.comboTemplate.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.selectionTemplate) {
|
||||||
|
options.formatSelection = this.selectionTemplate.bind(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
$elem.select2(options);
|
||||||
|
|
||||||
const castInteger = this.get('castInteger');
|
const castInteger = this.get('castInteger');
|
||||||
$elem.on("change", e => {
|
$elem.on("change", e => {
|
||||||
|
|
|
@ -0,0 +1,172 @@
|
||||||
|
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';
|
||||||
|
|
||||||
|
const LATER_TODAY = 'later_today';
|
||||||
|
const TOMORROW = 'tomorrow';
|
||||||
|
const LATER_THIS_WEEK = 'later_this_week';
|
||||||
|
const THIS_WEEKEND = 'this_weekend';
|
||||||
|
const NEXT_WEEK = 'next_week';
|
||||||
|
export const PICK_DATE_AND_TIME = 'pick_date_and_time';
|
||||||
|
export const SET_BASED_ON_LAST_POST = 'set_based_on_last_post';
|
||||||
|
|
||||||
|
export const FORMAT = 'YYYY-MM-DD HH:mm';
|
||||||
|
|
||||||
|
export default Combobox.extend({
|
||||||
|
classNames: ['auto-update-input-selector'],
|
||||||
|
isCustom: Ember.computed.equal("value", PICK_DATE_AND_TIME),
|
||||||
|
|
||||||
|
@computed()
|
||||||
|
content() {
|
||||||
|
const selections = [];
|
||||||
|
const now = moment();
|
||||||
|
const canScheduleToday = (24 - now.hour()) > 6;
|
||||||
|
const day = now.day();
|
||||||
|
|
||||||
|
if (canScheduleToday) {
|
||||||
|
selections.push({
|
||||||
|
id: LATER_TODAY,
|
||||||
|
name: I18n.t('topic.auto_update_input.later_today')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
selections.push({
|
||||||
|
id: TOMORROW,
|
||||||
|
name: I18n.t('topic.auto_update_input.tomorrow')
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!canScheduleToday && day < 4) {
|
||||||
|
selections.push({
|
||||||
|
id: LATER_THIS_WEEK,
|
||||||
|
name: I18n.t('topic.auto_update_input.later_this_week')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (day < 5) {
|
||||||
|
selections.push({
|
||||||
|
id: THIS_WEEKEND,
|
||||||
|
name: I18n.t('topic.auto_update_input.this_weekend')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (day !== 7) {
|
||||||
|
selections.push({
|
||||||
|
id: NEXT_WEEK,
|
||||||
|
name: I18n.t('topic.auto_update_input.next_week')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
selections.push({
|
||||||
|
id: PICK_DATE_AND_TIME,
|
||||||
|
name: I18n.t('topic.auto_update_input.pick_date_and_time')
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.get('statusType') === CLOSE_STATUS_TYPE) {
|
||||||
|
selections.push({
|
||||||
|
id: SET_BASED_ON_LAST_POST,
|
||||||
|
name: I18n.t('topic.auto_update_input.set_based_on_last_post')
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return selections;
|
||||||
|
},
|
||||||
|
|
||||||
|
@observes('value')
|
||||||
|
_updateInput() {
|
||||||
|
if (this.get('isCustom')) return;
|
||||||
|
let input = null;
|
||||||
|
const { time } = this.get('updateAt');
|
||||||
|
|
||||||
|
if (time && !Ember.isEmpty(this.get('value'))) {
|
||||||
|
input = time.format(FORMAT);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set('input', input);
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('value')
|
||||||
|
updateAt(value) {
|
||||||
|
return this._updateAt(value);
|
||||||
|
},
|
||||||
|
|
||||||
|
comboTemplate(state) {
|
||||||
|
return this._format(state);
|
||||||
|
},
|
||||||
|
|
||||||
|
selectionTemplate(state) {
|
||||||
|
return this._format(state);
|
||||||
|
},
|
||||||
|
|
||||||
|
_format(state) {
|
||||||
|
let { time, icon } = this._updateAt(state.id);
|
||||||
|
let icons;
|
||||||
|
|
||||||
|
if (icon) {
|
||||||
|
icons = icon.split(',').map(i => {
|
||||||
|
return `<i class='fa fa-${i}'/>`;
|
||||||
|
}).join(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (time) {
|
||||||
|
if (state.id === LATER_TODAY) {
|
||||||
|
time = time.format('hh:mm a');
|
||||||
|
} else {
|
||||||
|
time = time.format('ddd, hh:mm a');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let output = "";
|
||||||
|
|
||||||
|
if (!Ember.isEmpty(icons)) {
|
||||||
|
output += `<span class='auto-update-input-selector-icons'>${icons}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
output += `<span>${state.text}</span>`;
|
||||||
|
|
||||||
|
if (time) {
|
||||||
|
output += `<span class='auto-update-input-selector-datetime'>${time}</span>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
_updateAt(selection) {
|
||||||
|
let time = moment();
|
||||||
|
let icon;
|
||||||
|
const timeOfDay = this.get('statusType') !== CLOSE_STATUS_TYPE ? 8 : 18;
|
||||||
|
|
||||||
|
switch(selection) {
|
||||||
|
case LATER_TODAY:
|
||||||
|
time = time.hour(18).minute(0);
|
||||||
|
icon = 'desktop';
|
||||||
|
break;
|
||||||
|
case TOMORROW:
|
||||||
|
time = time.add(1, 'day').hour(timeOfDay).minute(0);
|
||||||
|
icon = 'sun-o';
|
||||||
|
break;
|
||||||
|
case LATER_THIS_WEEK:
|
||||||
|
time = time.add(2, 'day').hour(timeOfDay).minute(0);
|
||||||
|
icon = 'briefcase';
|
||||||
|
break;
|
||||||
|
case THIS_WEEKEND:
|
||||||
|
time = time.day(6).hour(timeOfDay).minute(0);
|
||||||
|
icon = 'bed';
|
||||||
|
break;
|
||||||
|
case NEXT_WEEK:
|
||||||
|
time = time.add(1, 'week').day(1).hour(timeOfDay).minute(0);
|
||||||
|
icon = 'briefcase';
|
||||||
|
break;
|
||||||
|
case PICK_DATE_AND_TIME:
|
||||||
|
time = null;
|
||||||
|
icon = 'calendar-plus-o';
|
||||||
|
break;
|
||||||
|
case SET_BASED_ON_LAST_POST:
|
||||||
|
time = null;
|
||||||
|
icon = 'clock-o';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return { time, icon };
|
||||||
|
},
|
||||||
|
});
|
|
@ -1,47 +1,92 @@
|
||||||
import { default as computed, observes } from "ember-addons/ember-computed-decorators";
|
import { default as computed, observes } from "ember-addons/ember-computed-decorators";
|
||||||
|
import {
|
||||||
|
FORMAT,
|
||||||
|
PICK_DATE_AND_TIME,
|
||||||
|
SET_BASED_ON_LAST_POST
|
||||||
|
} from "discourse/components/auto-update-input-selector";
|
||||||
|
|
||||||
export default Ember.Component.extend({
|
export default Ember.Component.extend({
|
||||||
limited: false,
|
selection: null,
|
||||||
|
date: null,
|
||||||
|
time: null,
|
||||||
|
isCustom: Ember.computed.equal('selection', PICK_DATE_AND_TIME),
|
||||||
|
isBasedOnLastPost: Ember.computed.equal('selection', SET_BASED_ON_LAST_POST),
|
||||||
|
|
||||||
didInsertElement() {
|
init() {
|
||||||
this._super();
|
this._super();
|
||||||
this._updateInputValid();
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed("limited")
|
const input = this.get('input');
|
||||||
inputUnitsKey(limited) {
|
|
||||||
return limited ? "topic.auto_update_input.limited.units" : "topic.auto_update_input.all.units";
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed("limited")
|
if (input) {
|
||||||
inputExamplesKey(limited) {
|
if (this.get('basedOnLastPost')) {
|
||||||
return limited ? "topic.auto_update_input.limited.examples" : "topic.auto_update_input.all.examples";
|
this.set('selection', SET_BASED_ON_LAST_POST);
|
||||||
},
|
|
||||||
|
|
||||||
@observes("input", "limited")
|
|
||||||
_updateInputValid() {
|
|
||||||
this.set(
|
|
||||||
"inputValid", this._isInputValid(this.get("input"), this.get("limited"))
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
_isInputValid(input, limited) {
|
|
||||||
const t = (input || "").toString().trim();
|
|
||||||
|
|
||||||
if (t.length === 0) {
|
|
||||||
return true;
|
|
||||||
// "empty" is always valid
|
|
||||||
} else if (limited) {
|
|
||||||
// only # of hours in limited mode
|
|
||||||
return t.match(/^(\d+\.)?\d+$/);
|
|
||||||
} else {
|
|
||||||
if (t.match(/^\d{4}-\d{1,2}-\d{1,2}(?: \d{1,2}:\d{2}(\s?[AP]M)?){0,1}$/i)) {
|
|
||||||
// timestamp must be in the future
|
|
||||||
return moment(t).isAfter();
|
|
||||||
} else {
|
} else {
|
||||||
// either # of hours or absolute time
|
this.set('selection', PICK_DATE_AND_TIME);
|
||||||
return (t.match(/^(\d+\.)?\d+$/) || t.match(/^\d{1,2}:\d{2}(\s?[AP]M)?$/i)) !== null;
|
const datetime = moment(input);
|
||||||
|
this.set('date', datetime.toDate());
|
||||||
|
this.set('time', datetime.format("HH:mm"));
|
||||||
|
this._updateInput();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
|
@observes("date", "time")
|
||||||
|
_updateInput() {
|
||||||
|
const date = moment(this.get('date')).format("YYYY-MM-DD");
|
||||||
|
const time = (this.get('time') && ` ${this.get('time')}`) || '';
|
||||||
|
this.set('input', moment(`${date}${time}`).format(FORMAT));
|
||||||
|
},
|
||||||
|
|
||||||
|
@observes("isBasedOnLastPost")
|
||||||
|
_updateBasedOnLastPost() {
|
||||||
|
this.set('basedOnLastPost', this.get('isBasedOnLastPost'));
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed("input", "isBasedOnLastPost")
|
||||||
|
duration(input, isBasedOnLastPost) {
|
||||||
|
const now = moment();
|
||||||
|
|
||||||
|
if (isBasedOnLastPost) {
|
||||||
|
return parseFloat(input);
|
||||||
|
} else {
|
||||||
|
return moment(input) - now;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed("input", "isBasedOnLastPost")
|
||||||
|
executeAt(input, isBasedOnLastPost) {
|
||||||
|
if (isBasedOnLastPost) {
|
||||||
|
return moment().add(input, 'hours').format(FORMAT);
|
||||||
|
} else {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed("statusType", "input", "isCustom", "date", "time", "willCloseImmediately")
|
||||||
|
showTopicStatusInfo(statusType, input, isCustom, date, time, willCloseImmediately) {
|
||||||
|
if (!statusType || willCloseImmediately) return false;
|
||||||
|
|
||||||
|
if (isCustom) {
|
||||||
|
return date || time;
|
||||||
|
} else {
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('isBasedOnLastPost', 'input', 'lastPostedAt')
|
||||||
|
willCloseImmediately(isBasedOnLastPost, input, lastPostedAt) {
|
||||||
|
if (isBasedOnLastPost && input) {
|
||||||
|
let closeDate = moment(lastPostedAt);
|
||||||
|
closeDate = closeDate.add(input, 'hours');
|
||||||
|
return closeDate < moment();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
@computed('isBasedOnLastPost', 'lastPostedAt')
|
||||||
|
willCloseI18n(isBasedOnLastPost, lastPostedAt) {
|
||||||
|
if (isBasedOnLastPost) {
|
||||||
|
const diff = Math.round((new Date() - new Date(lastPostedAt)) / (1000*60*60));
|
||||||
|
return I18n.t('topic.auto_close_immediate', { count: diff });
|
||||||
|
}
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import ComboboxView from 'discourse-common/components/combo-box';
|
import Combobox from 'discourse-common/components/combo-box';
|
||||||
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
import { categoryBadgeHTML } from 'discourse/helpers/category-link';
|
||||||
import computed from 'ember-addons/ember-computed-decorators';
|
import computed from 'ember-addons/ember-computed-decorators';
|
||||||
import { observes, on } from 'ember-addons/ember-computed-decorators';
|
import { observes, on } from 'ember-addons/ember-computed-decorators';
|
||||||
import PermissionType from 'discourse/models/permission-type';
|
import PermissionType from 'discourse/models/permission-type';
|
||||||
import Category from 'discourse/models/category';
|
import Category from 'discourse/models/category';
|
||||||
|
|
||||||
export default ComboboxView.extend({
|
export default Combobox.extend({
|
||||||
classNames: ['combobox category-combobox'],
|
classNames: ['combobox category-combobox'],
|
||||||
dataAttributes: ['id', 'description_text'],
|
dataAttributes: ['id', 'description_text'],
|
||||||
overrideWidths: true,
|
overrideWidths: true,
|
||||||
|
|
|
@ -110,9 +110,9 @@ export default Ember.Component.extend({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed('composer.title')
|
@computed('composer.title', 'composer.titleLength')
|
||||||
isAbsoluteUrl() {
|
isAbsoluteUrl(title, titleLength) {
|
||||||
return this.get('composer.titleLength') > 0 && /^(https?:)?\/\/[\w\.\-]+/i.test(this.get('composer.title'));
|
return titleLength > 0 && /^(https?:)?\/\/[\w\.\-]+/i.test(title);
|
||||||
},
|
},
|
||||||
|
|
||||||
bodyIsDefault() {
|
bodyIsDefault() {
|
||||||
|
|
|
@ -5,7 +5,8 @@ export default DatePicker.extend({
|
||||||
|
|
||||||
_opts() {
|
_opts() {
|
||||||
return {
|
return {
|
||||||
defaultDate: moment().add(1, "day").toDate(),
|
defaultDate: this.get('defaultDate') || moment().add(1, "day").toDate(),
|
||||||
|
setDefaultDate: !!this.get('defaultDate'),
|
||||||
minDate: new Date(),
|
minDate: new Date(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* global Pikaday:true */
|
/* global Pikaday:true */
|
||||||
import loadScript from "discourse/lib/load-script";
|
import loadScript from "discourse/lib/load-script";
|
||||||
import { on } from "ember-addons/ember-computed-decorators";
|
import { default as computed, on } from "ember-addons/ember-computed-decorators";
|
||||||
|
|
||||||
export default Em.Component.extend({
|
export default Em.Component.extend({
|
||||||
classNames: ["date-picker-wrapper"],
|
classNames: ["date-picker-wrapper"],
|
||||||
|
@ -39,6 +39,11 @@ export default Em.Component.extend({
|
||||||
this._picker = null;
|
this._picker = null;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@computed()
|
||||||
|
placeholder() {
|
||||||
|
return I18n.t("dates.placeholder");
|
||||||
|
},
|
||||||
|
|
||||||
_opts() {
|
_opts() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,21 +2,21 @@ import { bufferedRender } from 'discourse-common/lib/buffered-render';
|
||||||
import Category from 'discourse/models/category';
|
import Category from 'discourse/models/category';
|
||||||
|
|
||||||
export default Ember.Component.extend(bufferedRender({
|
export default Ember.Component.extend(bufferedRender({
|
||||||
elementId: 'topic-status-info',
|
classNames: ['topic-status-info'],
|
||||||
delayedRerender: null,
|
delayedRerender: null,
|
||||||
|
|
||||||
rerenderTriggers: [
|
rerenderTriggers: [
|
||||||
'topic.topic_status_update',
|
'statusType',
|
||||||
'topic.topic_status_update.execute_at',
|
'executeAt',
|
||||||
'topic.topic_status_update.based_on_last_post',
|
'basedOnLastPost',
|
||||||
'topic.topic_status_update.duration',
|
'duration',
|
||||||
'topic.topic_status_update.category_id',
|
'categoryId',
|
||||||
],
|
],
|
||||||
|
|
||||||
buildBuffer(buffer) {
|
buildBuffer(buffer) {
|
||||||
if (!this.get('topic.topic_status_update.execute_at')) return;
|
if (!this.get('executeAt')) return;
|
||||||
|
|
||||||
let statusUpdateAt = moment(this.get('topic.topic_status_update.execute_at'));
|
let statusUpdateAt = moment(this.get('executeAt'));
|
||||||
if (statusUpdateAt < new Date()) return;
|
if (statusUpdateAt < new Date()) return;
|
||||||
|
|
||||||
let duration = moment.duration(statusUpdateAt - moment());
|
let duration = moment.duration(statusUpdateAt - moment());
|
||||||
|
@ -33,7 +33,7 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
rerenderDelay = 60000;
|
rerenderDelay = 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
let autoCloseHours = this.get("topic.topic_status_update.duration") || 0;
|
let autoCloseHours = this.get("duration") || 0;
|
||||||
|
|
||||||
buffer.push('<h3><i class="fa fa-clock-o"></i> ');
|
buffer.push('<h3><i class="fa fa-clock-o"></i> ');
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
duration: moment.duration(autoCloseHours, "hours").humanize(),
|
duration: moment.duration(autoCloseHours, "hours").humanize(),
|
||||||
};
|
};
|
||||||
|
|
||||||
const categoryId = this.get('topic.topic_status_update.category_id');
|
const categoryId = this.get('categoryId');
|
||||||
|
|
||||||
if (categoryId) {
|
if (categoryId) {
|
||||||
const category = Category.findById(categoryId);
|
const category = Category.findById(categoryId);
|
||||||
|
@ -67,9 +67,9 @@ export default Ember.Component.extend(bufferedRender({
|
||||||
},
|
},
|
||||||
|
|
||||||
_noticeKey() {
|
_noticeKey() {
|
||||||
const statusType = this.get('topic.topic_status_update.status_type');
|
const statusType = this.get('statusType');
|
||||||
|
|
||||||
if (this.get("topic.topic_status_update.based_on_last_post")) {
|
if (this.get("basedOnLastPost")) {
|
||||||
return `topic.status_update_notice.auto_${statusType}_based_on_last_post`;
|
return `topic.status_update_notice.auto_${statusType}_based_on_last_post`;
|
||||||
} else {
|
} else {
|
||||||
return `topic.status_update_notice.auto_${statusType}`;
|
return `topic.status_update_notice.auto_${statusType}`;
|
||||||
|
|
|
@ -3,16 +3,11 @@ import ModalFunctionality from 'discourse/mixins/modal-functionality';
|
||||||
import TopicStatusUpdate from 'discourse/models/topic-status-update';
|
import TopicStatusUpdate from 'discourse/models/topic-status-update';
|
||||||
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
import { popupAjaxError } from 'discourse/lib/ajax-error';
|
||||||
|
|
||||||
const CLOSE_STATUS_TYPE = 'close';
|
export const CLOSE_STATUS_TYPE = 'close';
|
||||||
const OPEN_STATUS_TYPE = 'open';
|
const OPEN_STATUS_TYPE = 'open';
|
||||||
const PUBLISH_TO_CATEGORY_STATUS_TYPE = 'publish_to_category';
|
const PUBLISH_TO_CATEGORY_STATUS_TYPE = 'publish_to_category';
|
||||||
|
|
||||||
export default Ember.Controller.extend(ModalFunctionality, {
|
export default Ember.Controller.extend(ModalFunctionality, {
|
||||||
closeStatusType: CLOSE_STATUS_TYPE,
|
|
||||||
openStatusType: OPEN_STATUS_TYPE,
|
|
||||||
publishToCategoryStatusType: PUBLISH_TO_CATEGORY_STATUS_TYPE,
|
|
||||||
updateTimeValid: null,
|
|
||||||
updateTimeInvalid: Em.computed.not('updateTimeValid'),
|
|
||||||
loading: false,
|
loading: false,
|
||||||
updateTime: null,
|
updateTime: null,
|
||||||
topicStatusUpdate: Ember.computed.alias("model.topic_status_update"),
|
topicStatusUpdate: Ember.computed.alias("model.topic_status_update"),
|
||||||
|
@ -21,42 +16,18 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||||
autoClose: Ember.computed.equal('selection', CLOSE_STATUS_TYPE),
|
autoClose: Ember.computed.equal('selection', CLOSE_STATUS_TYPE),
|
||||||
publishToCategory: Ember.computed.equal('selection', PUBLISH_TO_CATEGORY_STATUS_TYPE),
|
publishToCategory: Ember.computed.equal('selection', PUBLISH_TO_CATEGORY_STATUS_TYPE),
|
||||||
|
|
||||||
@computed('autoClose', 'updateTime')
|
@computed("model.closed")
|
||||||
disableAutoClose(autoClose, updateTime) {
|
statusUpdates(closed) {
|
||||||
return updateTime && !autoClose;
|
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') }
|
||||||
|
];
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed('autoOpen', 'updateTime')
|
@computed('updateTime', 'loading')
|
||||||
disableAutoOpen(autoOpen, updateTime) {
|
saveDisabled(updateTime, loading) {
|
||||||
return updateTime && !autoOpen;
|
return Ember.isEmpty(updateTime) || loading;
|
||||||
},
|
|
||||||
|
|
||||||
@computed('publishToCatgory', 'updateTime')
|
|
||||||
disablePublishToCategory(publishToCatgory, updateTime) {
|
|
||||||
return updateTime && !publishToCatgory;
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed('topicStatusUpdate.based_on_last_post', 'updateTime', 'model.last_posted_at')
|
|
||||||
willCloseImmediately(basedOnLastPost, updateTime, lastPostedAt) {
|
|
||||||
if (!basedOnLastPost) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const closeDate = new Date(lastPostedAt);
|
|
||||||
closeDate.setHours(closeDate.getHours() + updateTime);
|
|
||||||
return closeDate < new Date();
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed('topicStatusUpdate.based_on_last_post', 'model.last_posted_at')
|
|
||||||
willCloseI18n(basedOnLastPost, lastPostedAt) {
|
|
||||||
if (basedOnLastPost) {
|
|
||||||
const diff = Math.round((new Date() - new Date(lastPostedAt)) / (1000*60*60));
|
|
||||||
return I18n.t('topic.auto_close_immediate', { count: diff });
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
@computed('updateTime', 'updateTimeInvalid', 'loading')
|
|
||||||
saveDisabled(updateTime, updateTimeInvalid, loading) {
|
|
||||||
return Ember.isEmpty(updateTime) || updateTimeInvalid || loading;
|
|
||||||
},
|
},
|
||||||
|
|
||||||
@computed("model.visible")
|
@computed("model.visible")
|
||||||
|
@ -66,29 +37,31 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||||
|
|
||||||
@observes("topicStatusUpdate.execute_at", "topicStatusUpdate.duration")
|
@observes("topicStatusUpdate.execute_at", "topicStatusUpdate.duration")
|
||||||
_setUpdateTime() {
|
_setUpdateTime() {
|
||||||
|
if (!this.get('topicStatusUpdate.execute_at')) return;
|
||||||
|
|
||||||
let time = null;
|
let time = null;
|
||||||
|
|
||||||
if (this.get("topicStatusUpdate.based_on_last_post")) {
|
if (this.get("topicStatusUpdate.based_on_last_post")) {
|
||||||
time = this.get("topicStatusUpdate.duration");
|
time = this.get("topicStatusUpdate.duration");
|
||||||
} else if (this.get("topicStatusUpdate.execute_at")) {
|
} else if (this.get("topicStatusUpdate.execute_at")) {
|
||||||
const closeTime = new Date(this.get("topicStatusUpdate.execute_at"));
|
const closeTime = moment(this.get('topicStatusUpdate.execute_at'));
|
||||||
|
|
||||||
if (closeTime > new Date()) {
|
if (closeTime > moment()) {
|
||||||
time = moment(closeTime).format("YYYY-MM-DD HH:mm");
|
time = closeTime.format("YYYY-MM-DD HH:mm");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.set("updateTime", time);
|
this.set("updateTime", time);
|
||||||
},
|
},
|
||||||
|
|
||||||
_setStatusUpdate(time, status_type) {
|
_setStatusUpdate(time, statusType) {
|
||||||
this.set('loading', true);
|
this.set('loading', true);
|
||||||
|
|
||||||
TopicStatusUpdate.updateStatus(
|
TopicStatusUpdate.updateStatus(
|
||||||
this.get('model.id'),
|
this.get('model.id'),
|
||||||
time,
|
time,
|
||||||
this.get('topicStatusUpdate.based_on_last_post'),
|
this.get('topicStatusUpdate.based_on_last_post'),
|
||||||
status_type,
|
statusType,
|
||||||
this.get('categoryId')
|
this.get('categoryId')
|
||||||
).then(result => {
|
).then(result => {
|
||||||
if (time) {
|
if (time) {
|
||||||
|
@ -102,8 +75,11 @@ export default Ember.Controller.extend(ModalFunctionality, {
|
||||||
|
|
||||||
this.set('model.closed', result.closed);
|
this.set('model.closed', result.closed);
|
||||||
} else {
|
} else {
|
||||||
this.set('topicStatusUpdate', Ember.Object.create({}));
|
this.setProperties({
|
||||||
this.set('selection', null);
|
topicStatusUpdate: Ember.Object.create({}),
|
||||||
|
selection: null,
|
||||||
|
updateTime: null
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
popupAjaxError(error);
|
popupAjaxError(error);
|
||||||
|
|
|
@ -54,7 +54,7 @@ const TopicRoute = Discourse.Route.extend({
|
||||||
const model = this.modelFor('topic');
|
const model = this.modelFor('topic');
|
||||||
model.set('topic_status_update', Ember.Object.create(model.get('topic_status_update')));
|
model.set('topic_status_update', Ember.Object.create(model.get('topic_status_update')));
|
||||||
showModal('edit-topic-status-update', { model });
|
showModal('edit-topic-status-update', { model });
|
||||||
this.controllerFor('modal').set('modalClass', 'topic-close-modal');
|
this.controllerFor('modal').set('modalClass', 'edit-topic-status-update-modal');
|
||||||
},
|
},
|
||||||
|
|
||||||
showChangeTimestamp() {
|
showChangeTimestamp() {
|
||||||
|
|
|
@ -1,24 +1,52 @@
|
||||||
<div class="auto-update-input">
|
<div class="auto-update-input">
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>
|
<label>{{i18n "topic.topic_status_update.when"}}</label>
|
||||||
{{i18n inputLabelKey}}
|
|
||||||
{{text-field value=input}}
|
|
||||||
{{i18n inputUnitsKey}}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{{#if inputExamplesKey}}
|
{{auto-update-input-selector
|
||||||
<div class="examples">
|
valueAttribute="id"
|
||||||
{{i18n inputExamplesKey}}
|
minimumResultsForSearch=-1
|
||||||
</div>
|
statusType=statusType
|
||||||
{{/if}}
|
value=selection
|
||||||
|
input=input
|
||||||
|
width="50%"
|
||||||
|
none="topic.auto_update_input.none"}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#unless hideBasedOnLastPost}}
|
{{#if isCustom}}
|
||||||
|
<div class="control-group">
|
||||||
|
{{fa-icon "calendar"}} {{date-picker-future value=date defaultDate=date}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="control-group">
|
||||||
|
{{fa-icon "clock-o"}}
|
||||||
|
{{input type="time" value=time}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if isBasedOnLastPost}}
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
<label>
|
<label>
|
||||||
{{input type="checkbox" checked=basedOnLastPost}}
|
{{i18n 'topic.topic_status_update.num_of_hours'}}
|
||||||
{{i18n 'topic.auto_close.based_on_last_post'}}
|
{{text-field value=input type="number"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
{{/unless}}
|
|
||||||
|
{{#if willCloseImmediately}}
|
||||||
|
<div class="warning">
|
||||||
|
{{fa-icon "warning"}}
|
||||||
|
{{willCloseI18n}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
|
{{/if}}
|
||||||
|
|
||||||
|
{{#if showTopicStatusInfo}}
|
||||||
|
<div class="alert alert-info">
|
||||||
|
{{topic-status-info
|
||||||
|
statusType=statusType
|
||||||
|
executeAt=executeAt
|
||||||
|
basedOnLastPost=basedOnLastPost
|
||||||
|
duration=duration
|
||||||
|
categoryId=categoryId}}
|
||||||
|
</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
<input type="text" class="date-picker">
|
{{input type="text" class="date-picker" placeholder=placeholder}}
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
<section class='field'>
|
<section class='field'>
|
||||||
{{auto-update-input
|
<div class="control-group">
|
||||||
inputLabelKey='topic.auto_close.label'
|
<label>
|
||||||
input=category.auto_close_hours
|
{{i18n 'topic.auto_close.label'}}
|
||||||
basedOnLastPost=category.auto_close_based_on_last_post
|
{{text-field value=category.auto_close_hours type="number"}}
|
||||||
inputExamplesKey=''
|
</label>
|
||||||
limited=true}}
|
|
||||||
|
<label>
|
||||||
|
{{input type="checkbox" checked=category.auto_close_based_on_last_post}}
|
||||||
|
{{i18n 'topic.auto_close.based_on_last_post'}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class='field'>
|
<section class='field'>
|
||||||
|
|
|
@ -1,59 +1,14 @@
|
||||||
<form>
|
<form>
|
||||||
{{#d-modal-body title="topic.topic_status_update.title" autoFocus="false"}}
|
{{#d-modal-body title="topic.topic_status_update.title" autoFocus="false"}}
|
||||||
<div class="radios">
|
<div class="control-group">
|
||||||
{{radio-button
|
{{combo-box content=statusUpdates value=selection width="50%"}}
|
||||||
disabled=disableAutoClose
|
|
||||||
name="auto-close"
|
|
||||||
id="auto-close"
|
|
||||||
value=closeStatusType
|
|
||||||
selection=selection}}
|
|
||||||
|
|
||||||
<label class="radio" for="auto-close">
|
|
||||||
{{fa-icon "clock-o"}} {{fa-icon "lock"}}
|
|
||||||
|
|
||||||
{{#if model.closed}}
|
|
||||||
{{i18n 'topic.temp_open.title'}}
|
|
||||||
{{else}}
|
|
||||||
{{i18n 'topic.auto_close.title'}}
|
|
||||||
{{/if}}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{{radio-button
|
|
||||||
disabled=disableAutoOpen
|
|
||||||
name="auto-reopen"
|
|
||||||
id="auto-reopen"
|
|
||||||
value=openStatusType
|
|
||||||
selection=selection}}
|
|
||||||
|
|
||||||
<label class="radio" for="auto-reopen">
|
|
||||||
{{fa-icon "clock-o"}} {{fa-icon "unlock"}}
|
|
||||||
|
|
||||||
{{#if model.closed}}
|
|
||||||
{{i18n 'topic.auto_reopen.title'}}
|
|
||||||
{{else}}
|
|
||||||
{{i18n 'topic.temp_close.title'}}
|
|
||||||
{{/if}}
|
|
||||||
</label>
|
|
||||||
|
|
||||||
{{radio-button
|
|
||||||
disabled=disablePublishToCategory
|
|
||||||
name="publish-to-category"
|
|
||||||
id="publish-to-category"
|
|
||||||
value=publishToCategoryStatusType
|
|
||||||
selection=selection}}
|
|
||||||
|
|
||||||
<label class="radio" for="publish-to-category">
|
|
||||||
{{fa-icon "clock-o"}} {{i18n 'topic.publish_to_category.title'}}
|
|
||||||
</label>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
{{#if autoOpen}}
|
{{#if autoOpen}}
|
||||||
{{auto-update-input
|
{{auto-update-input
|
||||||
inputLabelKey='topic.topic_status_update.time'
|
|
||||||
input=updateTime
|
input=updateTime
|
||||||
inputValid=updateTimeValid
|
statusType=selection
|
||||||
hideBasedOnLastPost=true
|
|
||||||
basedOnLastPost=false}}
|
basedOnLastPost=false}}
|
||||||
{{else if publishToCategory}}
|
{{else if publishToCategory}}
|
||||||
<div class="control-group">
|
<div class="control-group">
|
||||||
|
@ -62,25 +17,16 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{auto-update-input
|
{{auto-update-input
|
||||||
inputLabelKey='topic.topic_status_update.time'
|
|
||||||
input=updateTime
|
input=updateTime
|
||||||
inputValid=updateTimeValid
|
statusType=selection
|
||||||
hideBasedOnLastPost=true
|
categoryId=categoryId
|
||||||
basedOnLastPost=false}}
|
basedOnLastPost=false}}
|
||||||
{{else if autoClose}}
|
{{else if autoClose}}
|
||||||
{{auto-update-input
|
{{auto-update-input
|
||||||
inputLabelKey='topic.topic_status_update.time'
|
|
||||||
input=updateTime
|
input=updateTime
|
||||||
inputValid=updateTimeValid
|
statusType=selection
|
||||||
limited=topicStatusUpdate.based_on_last_post
|
basedOnLastPost=topicStatusUpdate.based_on_last_post
|
||||||
basedOnLastPost=topicStatusUpdate.based_on_last_post}}
|
lastPostedAt=model.last_posted_at}}
|
||||||
|
|
||||||
{{#if willCloseImmediately}}
|
|
||||||
<div class="warning">
|
|
||||||
{{fa-icon "warning"}}
|
|
||||||
{{willCloseI18n}}
|
|
||||||
</div>
|
|
||||||
{{/if}}
|
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/d-modal-body}}
|
{{/d-modal-body}}
|
||||||
|
|
|
@ -174,7 +174,13 @@
|
||||||
{{#conditional-loading-spinner condition=model.postStream.loadingFilter}}
|
{{#conditional-loading-spinner condition=model.postStream.loadingFilter}}
|
||||||
{{#if loadedAllPosts}}
|
{{#if loadedAllPosts}}
|
||||||
|
|
||||||
{{topic-status-info topic=model}}
|
{{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}}
|
||||||
|
|
||||||
{{#if session.showSignupCta}}
|
{{#if session.showSignupCta}}
|
||||||
{{! replace "Log In to Reply" with the infobox }}
|
{{! replace "Log In to Reply" with the infobox }}
|
||||||
{{signup-cta}}
|
{{signup-cta}}
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
.edit-topic-status-update-modal {
|
||||||
|
.modal-body {
|
||||||
|
max-height: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
input.date-picker, input[type="time"] {
|
||||||
|
width: 150px;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.pull-right {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auto-update-input {
|
||||||
|
input {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert-info {
|
||||||
|
margin: 0 -15px -15px -15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pika-single {
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topic-status-info {
|
||||||
|
border: none;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: normal;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
.topic-close-modal {
|
|
||||||
label {
|
|
||||||
display: inline-block;
|
|
||||||
}
|
|
||||||
|
|
||||||
.radios {
|
|
||||||
padding-bottom: 20px;
|
|
||||||
display: inline-block;
|
|
||||||
|
|
||||||
input[type='radio'] {
|
|
||||||
vertical-align: middle;
|
|
||||||
margin: 0px;
|
|
||||||
}
|
|
||||||
|
|
||||||
label {
|
|
||||||
padding: 0 10px 0px 5px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn.pull-right {
|
|
||||||
margin-right: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.auto-update-input {
|
|
||||||
input {
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
.auto-update-input-selector-datetime {
|
||||||
|
float: right;
|
||||||
|
color: lighten($primary, 40%);
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auto-update-input-selector-icons {
|
||||||
|
margin-right: 10px;
|
||||||
|
}
|
|
@ -16,7 +16,7 @@
|
||||||
.show-topic-admin,
|
.show-topic-admin,
|
||||||
#topic-progress,
|
#topic-progress,
|
||||||
.quote-controls,
|
.quote-controls,
|
||||||
#topic-status-info,
|
.topic-status-info,
|
||||||
div.lazyYT,
|
div.lazyYT,
|
||||||
.post-info.edits,
|
.post-info.edits,
|
||||||
.post-action,
|
.post-action,
|
||||||
|
|
|
@ -79,7 +79,7 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#topic-status-info {
|
.topic-status-info {
|
||||||
border-top: 1px solid dark-light-diff($primary, $secondary, 90%, -75%);
|
border-top: 1px solid dark-light-diff($primary, $secondary, 90%, -75%);
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|
|
@ -43,7 +43,7 @@
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
|
|
||||||
#topic-status-info {
|
.topic-status-info {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,6 +127,7 @@ en:
|
||||||
other: "%{count} years later"
|
other: "%{count} years later"
|
||||||
previous_month: 'Previous Month'
|
previous_month: 'Previous Month'
|
||||||
next_month: 'Next Month'
|
next_month: 'Next Month'
|
||||||
|
placeholder: Pick a date
|
||||||
share:
|
share:
|
||||||
topic: 'share a link to this topic'
|
topic: 'share a link to this topic'
|
||||||
post: 'post #%{postNumber}'
|
post: 'post #%{postNumber}'
|
||||||
|
@ -1484,16 +1485,19 @@ en:
|
||||||
topic_status_update:
|
topic_status_update:
|
||||||
title: "Set Topic Timer"
|
title: "Set Topic Timer"
|
||||||
save: "Set Timer"
|
save: "Set Timer"
|
||||||
time: "Time:"
|
num_of_hours: "Number of hours:"
|
||||||
remove: "Remove Timer"
|
remove: "Remove Timer"
|
||||||
publish_to: "Publish To:"
|
publish_to: "Publish To:"
|
||||||
|
when: "When:"
|
||||||
auto_update_input:
|
auto_update_input:
|
||||||
limited:
|
none: ""
|
||||||
units: "(# of hours)"
|
later_today: "Later today"
|
||||||
examples: 'Enter number of hours (24).'
|
tomorrow: "Tomorrow"
|
||||||
all:
|
later_this_week: "Later this week"
|
||||||
units: ""
|
this_weekend: "This weekend"
|
||||||
examples: 'Enter number of hours (24), absolute time (17:30) or timestamp (2013-11-22 14:00).'
|
next_week: "Next week"
|
||||||
|
pick_date_and_time: "Pick date and time"
|
||||||
|
set_based_on_last_post: "Close based on last post"
|
||||||
publish_to_category:
|
publish_to_category:
|
||||||
title: "Schedule Publishing"
|
title: "Schedule Publishing"
|
||||||
temp_open:
|
temp_open:
|
||||||
|
@ -1504,7 +1508,7 @@ en:
|
||||||
title: "Close Temporarily"
|
title: "Close Temporarily"
|
||||||
auto_close:
|
auto_close:
|
||||||
title: "Auto-Close Topic"
|
title: "Auto-Close Topic"
|
||||||
label: "Auto-close topic time:"
|
label: "Auto-close topic hours:"
|
||||||
error: "Please enter a valid value."
|
error: "Please enter a valid value."
|
||||||
based_on_last_post: "Don't close until the last post in the topic is at least this old."
|
based_on_last_post: "Don't close until the last post in the topic is at least this old."
|
||||||
|
|
||||||
|
@ -2010,8 +2014,6 @@ en:
|
||||||
security: "Security"
|
security: "Security"
|
||||||
special_warning: "Warning: This category is a pre-seeded category and the security settings cannot be edited. If you do not wish to use this category, delete it instead of repurposing it."
|
special_warning: "Warning: This category is a pre-seeded category and the security settings cannot be edited. If you do not wish to use this category, delete it instead of repurposing it."
|
||||||
images: "Images"
|
images: "Images"
|
||||||
auto_close_label: "Auto-close topics after:"
|
|
||||||
auto_close_units: "hours"
|
|
||||||
email_in: "Custom incoming email address:"
|
email_in: "Custom incoming email address:"
|
||||||
email_in_allow_strangers: "Accept emails from anonymous users with no accounts"
|
email_in_allow_strangers: "Accept emails from anonymous users with no accounts"
|
||||||
email_in_disabled: "Posting new topics via email is disabled in the Site Settings. To enable posting new topics via email, "
|
email_in_disabled: "Posting new topics via email is disabled in the Site Settings. To enable posting new topics via email, "
|
||||||
|
|
|
@ -56,3 +56,19 @@ componentTest('with none', {
|
||||||
assert.equal(this.$("select option:eq(2)").text(), 'trout');
|
assert.equal(this.$("select option:eq(2)").text(), 'trout');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
componentTest('with Object none', {
|
||||||
|
template: '{{combo-box content=items none=none value=value selected="something"}}',
|
||||||
|
setup() {
|
||||||
|
this.set('none', { id: 'something', name: 'none' });
|
||||||
|
this.set('items', ['evil', 'trout', 'hat']);
|
||||||
|
},
|
||||||
|
|
||||||
|
test(assert) {
|
||||||
|
assert.equal(this.get('value'), 'something');
|
||||||
|
assert.equal(this.$("select option:eq(0)").text(), 'none');
|
||||||
|
assert.equal(this.$("select option:eq(0)").val(), 'something');
|
||||||
|
assert.equal(this.$("select option:eq(1)").text(), 'evil');
|
||||||
|
assert.equal(this.$("select option:eq(2)").text(), 'trout');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
Loading…
Reference in New Issue