Serialize draft (#8175)

* DEV: allow serializing data for drafts

* Various fixes

* added an alias method for 'serializeToDraft' to plugin-api

* fixed linting issues

* changed single quotes to double quotes to fix linting issue

* fixed linting issues

* fixed composer model file via prettier

* fixed composer controller file via prettier

* fixed plugin-api file via prettier
This commit is contained in:
Faizaan Gagan 2019-10-10 22:32:35 +05:30 committed by Robin Ward
parent 09021c35a3
commit 8fc0cc9aaa
3 changed files with 84 additions and 59 deletions

View File

@ -39,26 +39,21 @@ function loadDraft(store, opts) {
((draft.title && draft.title !== "") || (draft.reply && draft.reply !== ""))
) {
const composer = store.createRecord("composer");
const serializedFields = Composer.serializedFieldsForDraft();
composer.open({
let attrs = {
draftKey,
draftSequence,
action: draft.action,
title: draft.title,
categoryId: draft.categoryId || opts.categoryId,
postId: draft.postId,
archetypeId: draft.archetypeId,
reply: draft.reply,
metaData: draft.metaData,
usernames: draft.usernames,
draft: true,
composerState: Composer.DRAFT,
composerTime: draft.composerTime,
typingTime: draft.typingTime,
whisper: draft.whisper,
tags: draft.tags,
noBump: draft.noBump
composerState: Composer.DRAFT
};
serializedFields.forEach(f => {
attrs[f] = draft[f] || opts[f];
});
composer.open(attrs);
return composer;
}
}
@ -753,15 +748,15 @@ export default Ember.Controller.extend({
},
/**
Open the composer view
Open the composer view
@method open
@param {Object} opts Options for creating a post
@param {String} opts.action The action we're performing: edit, reply or createTopic
@param {Discourse.Post} [opts.post] The post we're replying to
@param {Discourse.Topic} [opts.topic] The topic we're replying to
@param {String} [opts.quote] If we're opening a reply from a quote, the quote we're making
**/
@method open
@param {Object} opts Options for creating a post
@param {String} opts.action The action we're performing: edit, reply or createTopic
@param {Discourse.Post} [opts.post] The post we're replying to
@param {Discourse.Topic} [opts.topic] The topic we're replying to
@param {String} [opts.quote] If we're opening a reply from a quote, the quote we're making
**/
open(opts) {
opts = opts || {};

View File

@ -43,6 +43,7 @@ import Sharing from "discourse/lib/sharing";
import { addComposerUploadHandler } from "discourse/components/composer-editor";
import { addCategorySortCriteria } from "discourse/components/edit-category-settings";
import { queryRegistry } from "discourse/widgets/widget";
import Composer from "discourse/models/composer";
// If you add any methods to the API ensure you bump up this number
const PLUGIN_API_VERSION = "0.8.32";
@ -424,44 +425,44 @@ class PluginApi {
}
/**
Called whenever the "page" changes. This allows us to set up analytics
and other tracking.
Called whenever the "page" changes. This allows us to set up analytics
and other tracking.
To get notified when the page changes, you can install a hook like so:
To get notified when the page changes, you can install a hook like so:
```javascript
api.onPageChange((url, title) => {
```javascript
api.onPageChange((url, title) => {
console.log('the page changed to: ' + url + ' and title ' + title);
});
```
**/
```
**/
onPageChange(fn) {
this.onAppEvent("page:changed", data => fn(data.url, data.title));
}
/**
Listen for a triggered `AppEvent` from Discourse.
Listen for a triggered `AppEvent` from Discourse.
```javascript
api.onAppEvent('inserted-custom-html', () => {
```javascript
api.onAppEvent('inserted-custom-html', () => {
console.log('a custom footer was rendered');
});
```
**/
```
**/
onAppEvent(name, fn) {
const appEvents = this._lookupContainer("service:app-events");
appEvents && appEvents.on(name, fn);
}
/**
Registers a function to generate custom avatar CSS classes
for a particular user.
Registers a function to generate custom avatar CSS classes
for a particular user.
Takes a function that will accept a user as a parameter
and return an array of CSS classes to apply.
Takes a function that will accept a user as a parameter
and return an array of CSS classes to apply.
```javascript
api.customUserAvatarClasses(user => {
```javascript
api.customUserAvatarClasses(user => {
if (Ember.get(user, 'primary_group_name') === 'managers') {
return ['managers'];
}
@ -844,6 +845,21 @@ class PluginApi {
addComposerUploadHandler(extensions, method);
}
/**
* Adds a field to draft serializer
*
* Example:
*
* api.serializeToDraft('key_set_in_model', 'field_name_in_payload');
*
* to keep both of them same
* api.serializeToDraft('field_name');
*
*/
serializeToDraft(fieldName, property) {
Composer.serialzeToDraft(fieldName, property);
}
/**
* Registers a criteria that can be used as default topic order on category
* pages.

View File

@ -57,6 +57,20 @@ const CLOSED = "closed",
tags: "topic.tags",
featuredLink: "topic.featured_link"
},
_draft_serializer = {
reply: "reply",
action: "action",
title: "title",
categoryId: "categoryId",
archetypeId: "archetypeId",
whisper: "whisper",
metaData: "metaData",
composerTime: "composerTime",
typingTime: "typingTime",
postId: "post.id",
usernames: "targetUsernames"
},
_add_draft_fields = {},
FAST_REPLY_LENGTH_THRESHOLD = 10000;
export const SAVE_LABELS = {
@ -722,6 +736,11 @@ const Composer = RestModel.extend({
composer.appEvents.trigger("composer:reply-reloaded", composer);
}
// Ensure additional draft fields are set
Object.keys(_add_draft_fields).forEach(f => {
this.set(_add_draft_fields[f], opts[f]);
});
return false;
},
@ -1019,24 +1038,7 @@ const Composer = RestModel.extend({
this._clearingStatus = null;
}
let data = this.getProperties(
"reply",
"action",
"title",
"categoryId",
"archetypeId",
"whisper",
"metaData",
"composerTime",
"typingTime",
"tags",
"noBump"
);
data = Object.assign(data, {
usernames: this.targetUsernames,
postId: this.get("post.id")
});
let data = this.serialize(_draft_serializer);
if (data.postId && !Ember.isEmpty(this.originalText)) {
data.originalText = this.originalText;
@ -1113,6 +1115,18 @@ Composer.reopenClass({
return Object.keys(_create_serializer);
},
serializeToDraft(fieldName, property) {
if (!property) {
property = fieldName;
}
_draft_serializer[fieldName] = property;
_add_draft_fields[fieldName] = property;
},
serializedFieldsForDraft() {
return Object.keys(_draft_serializer);
},
// The status the compose view can have
CLOSED,
SAVING,