From 8fc0cc9aaa5795aa078ec6968413d529402f2f88 Mon Sep 17 00:00:00 2001 From: Faizaan Gagan Date: Thu, 10 Oct 2019 22:32:35 +0530 Subject: [PATCH] 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 --- .../discourse/controllers/composer.js.es6 | 41 +++++++-------- .../discourse/lib/plugin-api.js.es6 | 52 ++++++++++++------- .../discourse/models/composer.js.es6 | 50 +++++++++++------- 3 files changed, 84 insertions(+), 59 deletions(-) diff --git a/app/assets/javascripts/discourse/controllers/composer.js.es6 b/app/assets/javascripts/discourse/controllers/composer.js.es6 index b96051e906f..cf295cb8707 100644 --- a/app/assets/javascripts/discourse/controllers/composer.js.es6 +++ b/app/assets/javascripts/discourse/controllers/composer.js.es6 @@ -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 || {}; diff --git a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 index 4cf670b3dea..76959bdaa6d 100644 --- a/app/assets/javascripts/discourse/lib/plugin-api.js.es6 +++ b/app/assets/javascripts/discourse/lib/plugin-api.js.es6 @@ -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. diff --git a/app/assets/javascripts/discourse/models/composer.js.es6 b/app/assets/javascripts/discourse/models/composer.js.es6 index de9d9042bc5..9ba0afe0aa0 100644 --- a/app/assets/javascripts/discourse/models/composer.js.es6 +++ b/app/assets/javascripts/discourse/models/composer.js.es6 @@ -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,