Refactor topic title/category saving to support easier changing of
attributes via plugins.
This commit is contained in:
parent
9523b26af2
commit
7182767349
|
@ -1,7 +1,8 @@
|
||||||
import ObjectController from 'discourse/controllers/object';
|
import ObjectController from 'discourse/controllers/object';
|
||||||
|
import BufferedContent from 'discourse/mixins/buffered-content';
|
||||||
import { spinnerHTML } from 'discourse/helpers/loading-spinner';
|
import { spinnerHTML } from 'discourse/helpers/loading-spinner';
|
||||||
|
|
||||||
export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
export default ObjectController.extend(Discourse.SelectedPostsCount, BufferedContent, {
|
||||||
multiSelect: false,
|
multiSelect: false,
|
||||||
needs: ['header', 'modal', 'composer', 'quote-button', 'search', 'topic-progress', 'application'],
|
needs: ['header', 'modal', 'composer', 'quote-button', 'search', 'topic-progress', 'application'],
|
||||||
allPostsSelected: false,
|
allPostsSelected: false,
|
||||||
|
@ -235,11 +236,6 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||||
this.set('allPostsSelected', false);
|
this.set('allPostsSelected', false);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
Toggle a participant for filtering
|
|
||||||
|
|
||||||
@method toggleParticipant
|
|
||||||
**/
|
|
||||||
toggleParticipant: function(user) {
|
toggleParticipant: function(user) {
|
||||||
this.get('postStream').toggleParticipant(Em.get(user, 'username'));
|
this.get('postStream').toggleParticipant(Em.get(user, 'username'));
|
||||||
},
|
},
|
||||||
|
@ -247,17 +243,13 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||||
editTopic: function() {
|
editTopic: function() {
|
||||||
if (!this.get('details.can_edit')) return false;
|
if (!this.get('details.can_edit')) return false;
|
||||||
|
|
||||||
this.setProperties({
|
this.set('editingTopic', true);
|
||||||
editingTopic: true,
|
|
||||||
newTitle: this.get('title'),
|
|
||||||
newCategoryId: this.get('category_id')
|
|
||||||
});
|
|
||||||
return false;
|
return false;
|
||||||
},
|
},
|
||||||
|
|
||||||
// close editing mode
|
|
||||||
cancelEditingTopic: function() {
|
cancelEditingTopic: function() {
|
||||||
this.set('editingTopic', false);
|
this.set('editingTopic', false);
|
||||||
|
this.rollbackBuffer();
|
||||||
},
|
},
|
||||||
|
|
||||||
toggleMultiSelect: function() {
|
toggleMultiSelect: function() {
|
||||||
|
@ -265,39 +257,25 @@ export default ObjectController.extend(Discourse.SelectedPostsCount, {
|
||||||
},
|
},
|
||||||
|
|
||||||
finishedEditingTopic: function() {
|
finishedEditingTopic: function() {
|
||||||
if (this.get('editingTopic')) {
|
if (!this.get('editingTopic')) { return; }
|
||||||
|
|
||||||
var topic = this.get('model');
|
// save the modifications
|
||||||
|
var self = this,
|
||||||
|
props = this.get('buffered.buffer');
|
||||||
|
|
||||||
// Topic title hasn't been sanitized yet, so the template shouldn't trust it.
|
Discourse.Topic.update(this.get('model'), props).then(function() {
|
||||||
this.set('topicSaving', true);
|
|
||||||
|
|
||||||
// manually update the titles & category
|
|
||||||
var backup = topic.setPropertiesBackup({
|
|
||||||
title: this.get('newTitle'),
|
|
||||||
category_id: parseInt(this.get('newCategoryId'), 10),
|
|
||||||
fancy_title: this.get('newTitle')
|
|
||||||
});
|
|
||||||
|
|
||||||
// save the modifications
|
|
||||||
var self = this;
|
|
||||||
topic.save().then(function(result){
|
|
||||||
// update the title if it has been changed (cleaned up) server-side
|
|
||||||
topic.setProperties(Em.getProperties(result.basic_topic, 'title', 'fancy_title'));
|
|
||||||
self.set('topicSaving', false);
|
|
||||||
}, function(error) {
|
|
||||||
self.setProperties({ editingTopic: true, topicSaving: false });
|
|
||||||
topic.setProperties(backup);
|
|
||||||
if (error && error.responseText) {
|
|
||||||
bootbox.alert($.parseJSON(error.responseText).errors[0]);
|
|
||||||
} else {
|
|
||||||
bootbox.alert(I18n.t('generic_error'));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// close editing mode
|
|
||||||
self.set('editingTopic', false);
|
self.set('editingTopic', false);
|
||||||
}
|
}).catch(function(error) {
|
||||||
|
if (error && error.responseText) {
|
||||||
|
bootbox.alert($.parseJSON(error.responseText).errors[0]);
|
||||||
|
} else {
|
||||||
|
bootbox.alert(I18n.t('generic_error'));
|
||||||
|
}
|
||||||
|
}).finally(function() {
|
||||||
|
// Note we even roll back on success here because `update` saves
|
||||||
|
// the properties to the topic.
|
||||||
|
self.rollbackBuffer();
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
toggledSelectedPost: function(post) {
|
toggledSelectedPost: function(post) {
|
||||||
|
|
|
@ -463,13 +463,10 @@ Discourse.Composer = Discourse.Model.extend({
|
||||||
|
|
||||||
// Update the title if we've changed it
|
// Update the title if we've changed it
|
||||||
if (this.get('title') && post.get('post_number') === 1) {
|
if (this.get('title') && post.get('post_number') === 1) {
|
||||||
var topic = this.get('topic');
|
Discourse.Topic.update(this.get('topic'), {
|
||||||
topic.setProperties({
|
|
||||||
title: this.get('title'),
|
title: this.get('title'),
|
||||||
fancy_title: Handlebars.Utils.escapeExpression(this.get('title')),
|
category_id: this.get('categoryId')
|
||||||
category_id: parseInt(this.get('categoryId'), 10)
|
|
||||||
});
|
});
|
||||||
topic.save();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
post.setProperties({
|
post.setProperties({
|
||||||
|
|
|
@ -1,12 +1,4 @@
|
||||||
Discourse.Model = Ember.Object.extend(Discourse.Presence, {
|
Discourse.Model = Ember.Object.extend(Discourse.Presence);
|
||||||
// Like `setProperties` but returns the original values in case
|
|
||||||
// we want to roll back
|
|
||||||
setPropertiesBackup: function(obj) {
|
|
||||||
var backup = this.getProperties(Ember.keys(obj));
|
|
||||||
this.setProperties(obj);
|
|
||||||
return backup;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Discourse.Model.reopenClass({
|
Discourse.Model.reopenClass({
|
||||||
extractByKey: function(collection, klass) {
|
extractByKey: function(collection, klass) {
|
||||||
|
|
|
@ -202,23 +202,6 @@ Discourse.Topic = Discourse.Model.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
// Save any changes we've made to the model
|
|
||||||
save: function() {
|
|
||||||
// Don't save unless we can
|
|
||||||
if (!this.get('details.can_edit')) return;
|
|
||||||
|
|
||||||
var data = { title: this.get('title') };
|
|
||||||
|
|
||||||
if(this.get('category')){
|
|
||||||
data.category_id = this.get('category.id');
|
|
||||||
}
|
|
||||||
|
|
||||||
return Discourse.ajax(this.get('url'), {
|
|
||||||
type: 'PUT',
|
|
||||||
data: data
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Invite a user to this topic
|
Invite a user to this topic
|
||||||
|
|
||||||
|
@ -373,6 +356,17 @@ Discourse.Topic.reopenClass({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
update: function(topic, props) {
|
||||||
|
return Discourse.ajax(topic.get('url'), { type: 'PUT', data: props }).then(function(result) {
|
||||||
|
|
||||||
|
// The title can be cleaned up server side
|
||||||
|
props.title = result.basic_topic.title;
|
||||||
|
props.fancy_title = result.basic_topic.fancy_title;
|
||||||
|
|
||||||
|
topic.setProperties(props);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
create: function() {
|
create: function() {
|
||||||
var result = this._super.apply(this, arguments);
|
var result = this._super.apply(this, arguments);
|
||||||
this.createActionSummary(result);
|
this.createActionSummary(result);
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
{{#if editingTopic}}
|
{{#if editingTopic}}
|
||||||
{{#if isPrivateMessage}}
|
{{#if isPrivateMessage}}
|
||||||
<span class="private-message-glyph">{{fa-icon envelope}}</span>
|
<span class="private-message-glyph">{{fa-icon envelope}}</span>
|
||||||
{{autofocus-text-field id='edit-title' value=newTitle maxLength=maxTitleLength}}
|
{{autofocus-text-field id='edit-title' value=buffered.title maxLength=maxTitleLength}}
|
||||||
{{else}}
|
{{else}}
|
||||||
{{autofocus-text-field id='edit-title' value=newTitle maxLength=maxTitleLength}}
|
{{autofocus-text-field id='edit-title' value=buffered.title maxLength=maxTitleLength}}
|
||||||
</br>
|
</br>
|
||||||
{{category-chooser valueAttribute="id" value=newCategoryId source=category_id}}
|
{{category-chooser valueAttribute="id" value=buffered.category_id source=buffered.category_id}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<button class='btn btn-primary btn-small no-text' {{action "finishedEditingTopic"}}>{{fa-icon check}}</button>
|
<button class='btn btn-primary btn-small no-text' {{action "finishedEditingTopic"}}>{{fa-icon check}}</button>
|
||||||
|
@ -34,11 +34,7 @@
|
||||||
{{#if details.loaded}}
|
{{#if details.loaded}}
|
||||||
{{topic-status topic=model}}
|
{{topic-status topic=model}}
|
||||||
<a href='{{unbound url}}' {{action "jumpTop"}}>
|
<a href='{{unbound url}}' {{action "jumpTop"}}>
|
||||||
{{#if topicSaving}}
|
{{{fancy_title}}}
|
||||||
{{fancy_title}}
|
|
||||||
{{else}}
|
|
||||||
{{{fancy_title}}}
|
|
||||||
{{/if}}
|
|
||||||
</a>
|
</a>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ export default ComboboxView.extend({
|
||||||
overrideWidths: true,
|
overrideWidths: true,
|
||||||
dataAttributes: ['id', 'description_text'],
|
dataAttributes: ['id', 'description_text'],
|
||||||
valueBinding: Ember.Binding.oneWay('source'),
|
valueBinding: Ember.Binding.oneWay('source'),
|
||||||
|
castInteger: true,
|
||||||
|
|
||||||
content: function() {
|
content: function() {
|
||||||
var scopedCategoryId = this.get('scopedCategoryId');
|
var scopedCategoryId = this.get('scopedCategoryId');
|
||||||
|
|
|
@ -63,7 +63,7 @@ export default Discourse.View.extend({
|
||||||
this.rerender();
|
this.rerender();
|
||||||
}.observes('content.@each'),
|
}.observes('content.@each'),
|
||||||
|
|
||||||
didInsertElement: function() {
|
_initializeCombo: function() {
|
||||||
var $elem = this.$(),
|
var $elem = this.$(),
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
|
@ -75,10 +75,15 @@ export default Discourse.View.extend({
|
||||||
|
|
||||||
$elem.select2({formatResult: this.template, minimumResultsForSearch: 5, width: 'resolve'});
|
$elem.select2({formatResult: this.template, minimumResultsForSearch: 5, width: 'resolve'});
|
||||||
|
|
||||||
|
var castInteger = this.get('castInteger');
|
||||||
$elem.on("change", function (e) {
|
$elem.on("change", function (e) {
|
||||||
self.set('value', $(e.target).val());
|
var val = $(e.target).val();
|
||||||
|
if (val.length && castInteger) {
|
||||||
|
val = parseInt(val, 10);
|
||||||
|
}
|
||||||
|
self.set('value', val);
|
||||||
});
|
});
|
||||||
},
|
}.on('didInsertElement'),
|
||||||
|
|
||||||
willClearRender: function() {
|
willClearRender: function() {
|
||||||
var elementId = "s2id_" + this.$().attr('id');
|
var elementId = "s2id_" + this.$().attr('id');
|
||||||
|
|
|
@ -28,8 +28,8 @@ test("editingMode", function() {
|
||||||
topicController.set('model.details.can_edit', true);
|
topicController.set('model.details.can_edit', true);
|
||||||
topicController.send('editTopic');
|
topicController.send('editTopic');
|
||||||
ok(topicController.get('editingTopic'), "calling editTopic enables editing if the user can edit");
|
ok(topicController.get('editingTopic'), "calling editTopic enables editing if the user can edit");
|
||||||
equal(topicController.get('newTitle'), topic.get('title'));
|
equal(topicController.get('buffered.title'), topic.get('title'));
|
||||||
equal(topicController.get('newCategoryId'), topic.get('category_id'));
|
equal(topicController.get('buffered.category_id'), topic.get('category_id'));
|
||||||
|
|
||||||
topicController.send('cancelEditingTopic');
|
topicController.send('cancelEditingTopic');
|
||||||
ok(!topicController.get('editingTopic'), "cancelling edit mode reverts the property value");
|
ok(!topicController.get('editingTopic'), "cancelling edit mode reverts the property value");
|
||||||
|
|
Loading…
Reference in New Issue