UX: Require an extra click to open topic draft

When there is a topic draft in place instead of showing "+ New Topic"
we will show "+ Open Draft", this allows topic drafts to be much less
intrusive.

Also, fixes draft handling of tags
This commit is contained in:
Sam 2018-04-17 14:45:01 +10:00
parent 2024ea5bd3
commit 56cbfa2611
20 changed files with 112 additions and 49 deletions

View File

@ -1 +1,4 @@
export default Ember.Component.extend({ tagName: '' });
export default Ember.Component.extend({
tagName: '',
label: 'topic.create'
});

View File

@ -13,6 +13,12 @@ export default Ember.Component.extend({
return this.site.get('categoriesList');
},
@computed('hasDraft')
createTopicLabel(hasDraft)
{
return hasDraft ? 'topic.open_draft': 'topic.create';
},
@computed('category.can_edit')
showCategoryEdit: canEdit => canEdit,

View File

@ -41,7 +41,8 @@ function loadDraft(store, opts) {
composerState: Composer.DRAFT,
composerTime: draft.composerTime,
typingTime: draft.typingTime,
whisper: draft.whisper
whisper: draft.whisper,
tags: draft.tags
});
return composer;
}
@ -730,25 +731,26 @@ export default Ember.Controller.extend({
destroyDraft() {
const key = this.get('model.draftKey');
if (key) {
if (key === 'new_topic') {
this.send('clearTopicDraft');
}
Draft.clear(key, this.get('model.draftSequence'));
}
},
cancelComposer() {
const self = this;
return new Ember.RSVP.Promise(function (resolve) {
if (self.get('model.hasMetaData') || self.get('model.replyDirty')) {
return new Ember.RSVP.Promise((resolve) => {
if (this.get('model.hasMetaData') || this.get('model.replyDirty')) {
bootbox.dialog(I18n.t("post.abandon.confirm"), [
{ label: I18n.t("post.abandon.no_value") },
{
label: I18n.t("post.abandon.yes_value"),
'class': 'btn-danger',
callback(result) {
callback: (result) => {
if (result) {
self.destroyDraft();
self.get('model').clearState();
self.close();
this.destroyDraft();
this.get('model').clearState();
this.close();
resolve();
}
}
@ -756,9 +758,9 @@ export default Ember.Controller.extend({
]);
} else {
// it is possible there is some sort of crazy draft with no body ... just give up on it
self.destroyDraft();
self.get('model').clearState();
self.close();
this.destroyDraft();
this.get('model').clearState();
this.close();
resolve();
}
});

View File

@ -1,3 +1,10 @@
import NavigationDefaultController from 'discourse/controllers/navigation/default';
export default NavigationDefaultController.extend();
export default NavigationDefaultController.extend({
discoveryCategories: Ember.inject.controller('discovery/categories'),
draft: function() {
return this.get('discoveryCategories.model.draft');
}.property('discoveryCategories.model', 'discoveryCategories.model.draft')
});

View File

@ -1,4 +1,9 @@
export default Ember.Controller.extend({
discovery: Ember.inject.controller(),
discoveryTopics: Ember.inject.controller('discovery/topics'),
draft: function() {
return this.get('discoveryTopics.model.draft');
}.property('discoveryTopics.model', 'discoveryTopics.model.draft')
});

View File

@ -61,6 +61,10 @@ export default Ember.Controller.extend(BulkTopicSelection, {
categories: Ember.computed.alias('site.categoriesList'),
createTopicLabel: function() {
return this.get('list.draft') ? 'topic.open_draft' : 'topic.create';
}.property('list', 'list.draft'),
@computed('canCreateTopic', 'category', 'canCreateTopicOnCategory')
createTopicDisabled(canCreateTopic, category, canCreateTopicOnCategory) {
return !canCreateTopic || (category && !canCreateTopicOnCategory);

View File

@ -518,7 +518,8 @@ const Composer = RestModel.extend({
targetUsernames: opts.usernames,
composerTotalOpened: opts.composerTime,
typingTime: opts.typingTime,
whisper: opts.whisper
whisper: opts.whisper,
tags: opts.tags
});
if (opts.post) {
@ -836,7 +837,8 @@ const Composer = RestModel.extend({
metaData: this.get('metaData'),
usernames: this.get('targetUsernames'),
composerTime: this.get('composerTime'),
typingTime: this.get('typingTime')
typingTime: this.get('typingTime'),
tags: this.get('tags')
};
this.set('draftStatus', I18n.t('composer.saving_draft_tip'));

View File

@ -118,8 +118,6 @@ export default (filterArg, params) => {
this.controllerFor('discovery/topics').setProperties(topicOpts);
this.searchService.set('searchContext', category.get('searchContext'));
this.set('topics', null);
this.openTopicDraft(topics);
},
renderTemplate() {

View File

@ -106,8 +106,6 @@ export default function(filter, extras) {
}
}
this.controllerFor('discovery/topics').setProperties(topicOpts);
this.openTopicDraft(model);
this.controllerFor('navigation/default').set('canCreateTopic', model.get('can_create_topic'));
},

View File

@ -52,7 +52,25 @@ const DiscourseRoute = Ember.Route.extend({
refreshTitle() {
Ember.run.once(this, this._refreshTitleOnce);
},
clearTopicDraft() {
// perhaps re-delegate this to root controller in all cases?
// TODO also poison the store so it does not come back from the
// dead
if (this.get('controller.list.draft')) {
this.set('controller.list.draft', null);
}
if (this.controllerFor("discovery/categories").get('model.draft')) {
this.controllerFor("discovery/categories").set('model.draft', null);
}
if (this.controllerFor("discovery/topics").get('model.draft')) {
this.controllerFor("discovery/topics").set('model.draft', null);
}
}
},
redirectIfLoginRequired() {
@ -63,17 +81,18 @@ const DiscourseRoute = Ember.Route.extend({
},
openTopicDraft(model){
// If there's a draft, open the create topic composer
if (model.draft) {
const composer = this.controllerFor('composer');
if (!composer.get('model.viewOpen')) {
composer.open({
action: Composer.CREATE_TOPIC,
draft: model.draft,
draftKey: model.draft_key,
draftSequence: model.draft_sequence
});
}
const composer = this.controllerFor('composer');
if (composer.get('model.action') === Composer.CREATE_TOPIC &&
composer.get('model.draftKey') === model.draft_key) {
composer.set('model.composeState', Composer.OPEN);
} else {
composer.open({
action: Composer.CREATE_TOPIC,
draft: model.draft,
draftKey: model.draft_key,
draftSequence: model.draft_sequence
});
}
},

View File

@ -89,8 +89,6 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
showCategoryAdmin: model.get("can_create_category"),
canCreateTopic: model.get("can_create_topic"),
});
this.openTopicDraft(model);
},
actions: {
@ -133,7 +131,12 @@ const DiscoveryCategoriesRoute = Discourse.Route.extend(OpenComposer, {
},
createTopic() {
this.openComposer(this.controllerFor("discovery/categories"));
const model = this.controllerFor("discovery/categories").get('model');
if (model.draft) {
this.openTopicDraft(model);
} else {
this.openComposer(this.controllerFor("discovery/categories"));
}
},
didTransition() {

View File

@ -45,7 +45,12 @@ export default Discourse.Route.extend(OpenComposer, {
},
createTopic() {
this.openComposer(this.controllerFor("discovery/topics"));
const model = this.controllerFor("discovery/topics").get('model');
if (model.draft) {
this.openTopicDraft(model);
} else {
this.openComposer(this.controllerFor("discovery/topics"));
}
},
dismissReadTopics(dismissTopics) {

View File

@ -129,18 +129,22 @@ export default Discourse.Route.extend({
var controller = this.controllerFor("tags.show"),
self = this;
this.controllerFor('composer').open({
categoryId: controller.get('category.id'),
action: Composer.CREATE_TOPIC,
draftKey: controller.get('list.draft_key'),
draftSequence: controller.get('list.draft_sequence')
}).then(function() {
// Pre-fill the tags input field
if (controller.get('model.id')) {
var c = self.controllerFor('composer').get('model');
c.set('tags', _.flatten([controller.get('model.id')], controller.get('additionalTags')));
}
});
if (controller.get('list.draft')) {
this.openTopicDraft(controller.get('list'));
} else {
this.controllerFor('composer').open({
categoryId: controller.get('category.id'),
action: Composer.CREATE_TOPIC,
draftKey: controller.get('list.draft_key'),
draftSequence: controller.get('list.draft_sequence')
}).then(function() {
// Pre-fill the tags input field
if (controller.get('model.id')) {
var c = self.controllerFor('composer').get('model');
c.set('tags', _.flatten([controller.get('model.id')], controller.get('additionalTags')));
}
});
}
},
didTransition() {

View File

@ -5,5 +5,5 @@
action=action
icon="plus"
disabled=disabled
label="topic.create"}}
label=label}}
{{/if}}

View File

@ -15,7 +15,9 @@
{{create-topic-button
canCreateTopic=canCreateTopic
action=createTopic
disabled=createTopicDisabled}}
disabled=createTopicDisabled
label=createTopicLabel
}}
{{#if showCategoryEdit}}
{{d-button

View File

@ -5,5 +5,6 @@
createCategory=(route-action "createCategory")
reorderCategories=(route-action "reorderCategories")
canCreateTopic=canCreateTopic
hasDraft=draft
createTopic=(route-action "createTopic")}}
{{/d-section}}

View File

@ -18,6 +18,7 @@
canCreateTopic=canCreateTopic
createTopic=(route-action "createTopic")
createTopicDisabled=cannotCreateTopicOnCategory
hasDraft=draft
editCategory=(route-action "editCategory" category)}}
{{plugin-outlet name="category-navigation" args=(hash category=category)}}

View File

@ -2,5 +2,6 @@
{{d-navigation
filterMode=filterMode
canCreateTopic=canCreateTopic
hasDraft=draft
createTopic=(route-action "createTopic")}}
{{/d-section}}

View File

@ -19,6 +19,7 @@
{{create-topic-button
canCreateTopic=canCreateTopic
disabled=createTopicDisabled
label=createTopicLabel
action=(route-action "createTopic")}}
{{#if showTagFilter}}

View File

@ -1600,6 +1600,7 @@ en:
other: "{{count}} posts in topic"
create: 'New Topic'
create_long: 'Create a new Topic'
open_draft: "Open Draft"
private_message: 'Start a message'
archive_message:
help: 'Move message to your archive'