A common, extensible interface for sending topic columns across the wire
This allows plugins to specify topic columns to serialize and save in the database via the composer when creating topics and editing their first posts.
This commit is contained in:
parent
97b4dec96c
commit
5667478b4d
|
@ -135,7 +135,6 @@ export default DiscourseController.extend({
|
||||||
var composer = this.get('model'),
|
var composer = this.get('model'),
|
||||||
self = this;
|
self = this;
|
||||||
|
|
||||||
|
|
||||||
// Clear the warning state if we're not showing the checkbox anymore
|
// Clear the warning state if we're not showing the checkbox anymore
|
||||||
if (!this.get('showWarning')) {
|
if (!this.get('showWarning')) {
|
||||||
this.set('model.isWarning', false);
|
this.set('model.isWarning', false);
|
||||||
|
|
|
@ -134,6 +134,7 @@ Discourse.Post = Discourse.Model.extend({
|
||||||
save: function(complete, error) {
|
save: function(complete, error) {
|
||||||
var self = this;
|
var self = this;
|
||||||
if (!this.get('newPost')) {
|
if (!this.get('newPost')) {
|
||||||
|
|
||||||
// We're updating a post
|
// We're updating a post
|
||||||
return Discourse.ajax("/posts/" + (this.get('id')), {
|
return Discourse.ajax("/posts/" + (this.get('id')), {
|
||||||
type: 'PUT',
|
type: 'PUT',
|
||||||
|
@ -155,17 +156,9 @@ Discourse.Post = Discourse.Model.extend({
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// We're saving a post
|
// We're saving a post
|
||||||
var data = {
|
var data = this.getProperties(Discourse.Composer.serializedFieldsForCreate());
|
||||||
raw: this.get('raw'),
|
data.reply_to_post_number = this.get('reply_to_post_number');
|
||||||
topic_id: this.get('topic_id'),
|
data.image_sizes = this.get('imageSizes');
|
||||||
is_warning: this.get('is_warning'),
|
|
||||||
reply_to_post_number: this.get('reply_to_post_number'),
|
|
||||||
category: this.get('category'),
|
|
||||||
archetype: this.get('archetype'),
|
|
||||||
title: this.get('title'),
|
|
||||||
image_sizes: this.get('imageSizes'),
|
|
||||||
target_usernames: this.get('target_usernames'),
|
|
||||||
};
|
|
||||||
|
|
||||||
var metaData = this.get('metaData');
|
var metaData = this.get('metaData');
|
||||||
// Put the metaData into the request
|
// Put the metaData into the request
|
||||||
|
|
|
@ -1,12 +1,3 @@
|
||||||
/**
|
|
||||||
A data model for representing the composer's current state
|
|
||||||
|
|
||||||
@class Composer
|
|
||||||
@extends Discourse.Model
|
|
||||||
@namespace Discourse
|
|
||||||
@module Discourse
|
|
||||||
**/
|
|
||||||
|
|
||||||
var CLOSED = 'closed',
|
var CLOSED = 'closed',
|
||||||
SAVING = 'saving',
|
SAVING = 'saving',
|
||||||
OPEN = 'open',
|
OPEN = 'open',
|
||||||
|
@ -17,7 +8,23 @@ var CLOSED = 'closed',
|
||||||
PRIVATE_MESSAGE = 'privateMessage',
|
PRIVATE_MESSAGE = 'privateMessage',
|
||||||
REPLY = 'reply',
|
REPLY = 'reply',
|
||||||
EDIT = 'edit',
|
EDIT = 'edit',
|
||||||
REPLY_AS_NEW_TOPIC_KEY = "reply_as_new_topic";
|
REPLY_AS_NEW_TOPIC_KEY = "reply_as_new_topic",
|
||||||
|
|
||||||
|
// When creating, these fields are moved into the post model from the composer model
|
||||||
|
_create_serializer = {
|
||||||
|
raw: 'reply',
|
||||||
|
title: 'title',
|
||||||
|
category: 'categoryId',
|
||||||
|
topic_id: 'topic.id',
|
||||||
|
is_warning: 'isWarning',
|
||||||
|
archetype: 'archetypeId',
|
||||||
|
target_usernames: 'targetUsernames'
|
||||||
|
},
|
||||||
|
|
||||||
|
_edit_topic_serializer = {
|
||||||
|
title: 'topic.title',
|
||||||
|
categoryId: 'topic.category.id'
|
||||||
|
};
|
||||||
|
|
||||||
Discourse.Composer = Discourse.Model.extend({
|
Discourse.Composer = Discourse.Model.extend({
|
||||||
|
|
||||||
|
@ -410,10 +417,11 @@ Discourse.Composer = Discourse.Model.extend({
|
||||||
|
|
||||||
// If we are editing a post, load it.
|
// If we are editing a post, load it.
|
||||||
if (opts.action === EDIT && opts.post) {
|
if (opts.action === EDIT && opts.post) {
|
||||||
this.setProperties({
|
|
||||||
title: this.get('topic.title'),
|
var topicProps = this.serialize(_edit_topic_serializer);
|
||||||
loading: true
|
topicProps.loading = true;
|
||||||
});
|
|
||||||
|
this.setProperties(topicProps);
|
||||||
|
|
||||||
Discourse.Post.load(opts.post.get('id')).then(function(result) {
|
Discourse.Post.load(opts.post.get('id')).then(function(result) {
|
||||||
composer.setProperties({
|
composer.setProperties({
|
||||||
|
@ -463,10 +471,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) {
|
||||||
Discourse.Topic.update(this.get('topic'), {
|
|
||||||
title: this.get('title'),
|
var topicProps = this.getProperties(Object.keys(_edit_topic_serializer));
|
||||||
category_id: this.get('categoryId')
|
|
||||||
});
|
Discourse.Topic.update(this.get('topic'), topicProps);
|
||||||
}
|
}
|
||||||
|
|
||||||
post.setProperties({
|
post.setProperties({
|
||||||
|
@ -494,6 +502,21 @@ Discourse.Composer = Discourse.Model.extend({
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
serialize: function(serializer, dest) {
|
||||||
|
if (!dest) {
|
||||||
|
dest = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
Object.keys(serializer).forEach(function(f) {
|
||||||
|
var val = self.get(serializer[f]);
|
||||||
|
if (typeof val !== 'undefined') {
|
||||||
|
Ember.set(dest, f, val);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return dest;
|
||||||
|
},
|
||||||
|
|
||||||
// Create a new Post
|
// Create a new Post
|
||||||
createPost: function(opts) {
|
createPost: function(opts) {
|
||||||
var post = this.get('post'),
|
var post = this.get('post'),
|
||||||
|
@ -504,11 +527,6 @@ Discourse.Composer = Discourse.Model.extend({
|
||||||
|
|
||||||
// Build the post object
|
// Build the post object
|
||||||
var createdPost = Discourse.Post.create({
|
var createdPost = Discourse.Post.create({
|
||||||
raw: this.get('reply'),
|
|
||||||
title: this.get('title'),
|
|
||||||
category: this.get('categoryId'),
|
|
||||||
topic_id: this.get('topic.id'),
|
|
||||||
is_warning: this.get('isWarning'),
|
|
||||||
imageSizes: opts.imageSizes,
|
imageSizes: opts.imageSizes,
|
||||||
cooked: this.getCookedHtml(),
|
cooked: this.getCookedHtml(),
|
||||||
reply_count: 0,
|
reply_count: 0,
|
||||||
|
@ -517,17 +535,17 @@ Discourse.Composer = Discourse.Model.extend({
|
||||||
user_id: currentUser.get('id'),
|
user_id: currentUser.get('id'),
|
||||||
uploaded_avatar_id: currentUser.get('uploaded_avatar_id'),
|
uploaded_avatar_id: currentUser.get('uploaded_avatar_id'),
|
||||||
user_custom_fields: currentUser.get('custom_fields'),
|
user_custom_fields: currentUser.get('custom_fields'),
|
||||||
archetype: this.get('archetypeId'),
|
|
||||||
post_type: Discourse.Site.currentProp('post_types.regular'),
|
post_type: Discourse.Site.currentProp('post_types.regular'),
|
||||||
target_usernames: this.get('targetUsernames'),
|
actions_summary: [],
|
||||||
actions_summary: Em.A(),
|
|
||||||
moderator: currentUser.get('moderator'),
|
moderator: currentUser.get('moderator'),
|
||||||
admin: currentUser.get('admin'),
|
admin: currentUser.get('admin'),
|
||||||
yours: true,
|
yours: true,
|
||||||
newPost: true,
|
newPost: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
if(post) {
|
this.serialize(_create_serializer, createdPost);
|
||||||
|
|
||||||
|
if (post) {
|
||||||
createdPost.setProperties({
|
createdPost.setProperties({
|
||||||
reply_to_post_number: post.get('post_number'),
|
reply_to_post_number: post.get('post_number'),
|
||||||
reply_to_user: {
|
reply_to_user: {
|
||||||
|
@ -698,6 +716,20 @@ Discourse.Composer.reopenClass({
|
||||||
return composer;
|
return composer;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
serializeToTopic: function(fieldName, property) {
|
||||||
|
if (!property) { property = fieldName; }
|
||||||
|
_edit_topic_serializer[fieldName] = property;
|
||||||
|
},
|
||||||
|
|
||||||
|
serializeOnCreate: function(fieldName, property) {
|
||||||
|
if (!property) { property = fieldName; }
|
||||||
|
_create_serializer[fieldName] = property;
|
||||||
|
},
|
||||||
|
|
||||||
|
serializedFieldsForCreate: function() {
|
||||||
|
return Object.keys(_create_serializer);
|
||||||
|
},
|
||||||
|
|
||||||
// The status the compose view can have
|
// The status the compose view can have
|
||||||
CLOSED: CLOSED,
|
CLOSED: CLOSED,
|
||||||
SAVING: SAVING,
|
SAVING: SAVING,
|
||||||
|
|
|
@ -371,6 +371,12 @@ Discourse.Topic.reopenClass({
|
||||||
update: function(topic, props) {
|
update: function(topic, props) {
|
||||||
props = JSON.parse(JSON.stringify(props)) || {};
|
props = JSON.parse(JSON.stringify(props)) || {};
|
||||||
|
|
||||||
|
// We support `category_id` and `categoryId` for compatibility
|
||||||
|
if (typeof props.categoryId !== "undefined") {
|
||||||
|
props.category_id = props.categoryId;
|
||||||
|
delete props.categoryId;
|
||||||
|
}
|
||||||
|
|
||||||
// Annoyingly, empty arrays are not sent across the wire. This
|
// Annoyingly, empty arrays are not sent across the wire. This
|
||||||
// allows us to make a distinction between arrays that were not
|
// allows us to make a distinction between arrays that were not
|
||||||
// sent and arrays that we specifically want to be empty.
|
// sent and arrays that we specifically want to be empty.
|
||||||
|
|
|
@ -78,6 +78,8 @@ class PostsController < ApplicationController
|
||||||
def create_post(params)
|
def create_post(params)
|
||||||
post_creator = PostCreator.new(current_user, params)
|
post_creator = PostCreator.new(current_user, params)
|
||||||
post = post_creator.create
|
post = post_creator.create
|
||||||
|
DiscourseEvent.trigger(:topic_saved, post.topic, params)
|
||||||
|
|
||||||
if post_creator.errors.present?
|
if post_creator.errors.present?
|
||||||
# If the post was spam, flag all the user's posts as spam
|
# If the post was spam, flag all the user's posts as spam
|
||||||
current_user.flag_linked_posts_as_spam if post_creator.spam?
|
current_user.flag_linked_posts_as_spam if post_creator.spam?
|
||||||
|
@ -400,7 +402,6 @@ class PostsController < ApplicationController
|
||||||
permitted << :embed_url
|
permitted << :embed_url
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
params.require(:raw)
|
params.require(:raw)
|
||||||
result = params.permit(*permitted).tap do |whitelisted|
|
result = params.permit(*permitted).tap do |whitelisted|
|
||||||
whitelisted[:image_sizes] = params[:image_sizes]
|
whitelisted[:image_sizes] = params[:image_sizes]
|
||||||
|
@ -414,6 +415,9 @@ class PostsController < ApplicationController
|
||||||
result[:is_warning] = (params[:is_warning] == "true")
|
result[:is_warning] = (params[:is_warning] == "true")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Enable plugins to whitelist additional parameters they might need
|
||||||
|
DiscourseEvent.trigger(:permit_post_params, result, params)
|
||||||
|
|
||||||
result
|
result
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue