From b5af691a6187501fc39f4e0cec85f74cb05d5f3a Mon Sep 17 00:00:00 2001 From: Matt Enlow Date: Mon, 3 Nov 2014 20:31:10 -0700 Subject: [PATCH] Save meta title and meta desc on post save Closes #4369 - Renamed `editor-route-base` -> `editor-base-route` to bring it in alignment with the view and controller mixins - Consolidated editor route code into editor-base-route - Removed `serialize` from EditorEditRoute, as it reimplemented the ember default --- core/client/mixins/editor-base-controller.js | 4 +- ...tor-route-base.js => editor-base-route.js} | 63 ++++++++++++++++++- core/client/routes/editor/edit.js | 55 +--------------- core/client/routes/editor/new.js | 53 +--------------- core/client/utils/codemirror-shortcuts.js | 2 +- 5 files changed, 67 insertions(+), 110 deletions(-) rename core/client/mixins/{editor-route-base.js => editor-base-route.js} (51%) diff --git a/core/client/mixins/editor-base-controller.js b/core/client/mixins/editor-base-controller.js index f5630bf272..70bad996e3 100644 --- a/core/client/mixins/editor-base-controller.js +++ b/core/client/mixins/editor-base-controller.js @@ -66,7 +66,7 @@ EditorControllerMixin = Ember.Mixin.create(MarkerManager, { return hashCurrent === hashPrevious; }, - // a hook created in editor-route-base's setupController + // a hook created in editor-base-route's setupController modelSaved: function () { var model = this.get('model'); @@ -231,6 +231,8 @@ EditorControllerMixin = Ember.Mixin.create(MarkerManager, { } this.set('title', this.get('titleScratch')); + this.set('meta_title', psmController.get('metaTitleScratch')); + this.set('meta_description', psmController.get('metaDescriptionScratch')); if (!this.get('slug')) { // Cancel any pending slug generation that may still be queued in the diff --git a/core/client/mixins/editor-route-base.js b/core/client/mixins/editor-base-route.js similarity index 51% rename from core/client/mixins/editor-route-base.js rename to core/client/mixins/editor-base-route.js index 38c8a731ab..26bc1b3dbf 100644 --- a/core/client/mixins/editor-route-base.js +++ b/core/client/mixins/editor-base-route.js @@ -3,7 +3,9 @@ import styleBody from 'ghost/mixins/style-body'; import loadingIndicator from 'ghost/mixins/loading-indicator'; import editorShortcuts from 'ghost/utils/editor-shortcuts'; -var EditorRouteBase = Ember.Mixin.create(styleBody, ShortcutsRoute, loadingIndicator, { +var EditorBaseRoute = Ember.Mixin.create(styleBody, ShortcutsRoute, loadingIndicator, { + classNames: ['editor'], + actions: { save: function () { this.get('controller').send('save'); @@ -26,11 +28,47 @@ var EditorRouteBase = Ember.Mixin.create(styleBody, ShortcutsRoute, loadingIndic if (Ember.$('.CodeMirror.CodeMirror-focused').length > 0) { this.get('controller.codemirror').shortcut(options.type); } + }, + + willTransition: function (transition) { + var controller = this.get('controller'), + isDirty = controller.get('isDirty'), + + model = controller.get('model'), + isNew = model.get('isNew'), + isSaving = model.get('isSaving'), + isDeleted = model.get('isDeleted'), + modelIsDirty = model.get('isDirty'); + + this.send('closeSettingsMenu'); + + // when `isDeleted && isSaving`, model is in-flight, being saved + // to the server. when `isDeleted && !isSaving && !modelIsDirty`, + // the record has already been deleted and the deletion persisted. + // + // in either case we can probably just transition now. + // in the former case the server will return the record, thereby updating it. + // @TODO: this will break if the model fails server-side validation. + if (!(isDeleted && isSaving) && !(isDeleted && !isSaving && !modelIsDirty) && isDirty) { + transition.abort(); + this.send('openModal', 'leave-editor', [controller, transition]); + return; + } + + if (isNew) { + model.deleteRecord(); + } + + // since the transition is now certain to complete.. + window.onbeforeunload = null; + + // remove model-related listeners created in editor-base-route + this.detachModelHooks(controller, model); } }, renderTemplate: function (controller, model) { - this._super(); + this._super(controller, model); this.render('post-settings-menu', { into: 'application', @@ -59,7 +97,26 @@ var EditorRouteBase = Ember.Mixin.create(styleBody, ShortcutsRoute, loadingIndic detachModelHooks: function (controller, model) { model.off('didCreate', controller, controller.get('modelSaved')); model.off('didUpdate', controller, controller.get('modelSaved')); + }, + + setupController: function (controller, model) { + this._super(controller, model); + var tags = model.get('tags'); + + controller.set('scratch', model.get('markdown')); + + controller.set('titleScratch', model.get('title')); + + if (tags) { + // used to check if anything has changed in the editor + controller.set('previousTagNames', tags.mapBy('name')); + } else { + controller.set('previousTagNames', []); + } + + // attach model-related listeners created in editor-base-route + this.attachModelHooks(controller, model); } }); -export default EditorRouteBase; +export default EditorBaseRoute; diff --git a/core/client/routes/editor/edit.js b/core/client/routes/editor/edit.js index f98005214f..871a8b5ecc 100644 --- a/core/client/routes/editor/edit.js +++ b/core/client/routes/editor/edit.js @@ -1,11 +1,9 @@ import AuthenticatedRoute from 'ghost/routes/authenticated'; -import base from 'ghost/mixins/editor-route-base'; +import base from 'ghost/mixins/editor-base-route'; import isNumber from 'ghost/utils/isNumber'; import isFinite from 'ghost/utils/isFinite'; var EditorEditRoute = AuthenticatedRoute.extend(base, { - classNames: ['editor'], - model: function (params) { var self = this, post, @@ -50,57 +48,6 @@ var EditorEditRoute = AuthenticatedRoute.extend(base, { return self.transitionTo('posts.index'); }); }); - }, - - serialize: function (model) { - return {post_id: model.get('id')}; - }, - - setupController: function (controller, model) { - this._super(controller, model); - - controller.set('scratch', model.get('markdown')); - - controller.set('titleScratch', model.get('title')); - - // used to check if anything has changed in the editor - controller.set('previousTagNames', model.get('tags').mapBy('name')); - - // attach model-related listeners created in editor-route-base - this.attachModelHooks(controller, model); - }, - - actions: { - willTransition: function (transition) { - var controller = this.get('controller'), - isDirty = controller.get('isDirty'), - - model = controller.get('model'), - isSaving = model.get('isSaving'), - isDeleted = model.get('isDeleted'), - modelIsDirty = model.get('isDirty'); - - this.send('closeSettingsMenu'); - - // when `isDeleted && isSaving`, model is in-flight, being saved - // to the server. when `isDeleted && !isSaving && !modelIsDirty`, - // the record has already been deleted and the deletion persisted. - // - // in either case we can probably just transition now. - // in the former case the server will return the record, thereby updating it. - // @TODO: this will break if the model fails server-side validation. - if (!(isDeleted && isSaving) && !(isDeleted && !isSaving && !modelIsDirty) && isDirty) { - transition.abort(); - this.send('openModal', 'leave-editor', [controller, transition]); - return; - } - - // since the transition is now certain to complete.. - window.onbeforeunload = null; - - // remove model-related listeners created in editor-route-base - this.detachModelHooks(controller, model); - } } }); diff --git a/core/client/routes/editor/new.js b/core/client/routes/editor/new.js index ff4f6f6c99..96da4d70a6 100644 --- a/core/client/routes/editor/new.js +++ b/core/client/routes/editor/new.js @@ -1,9 +1,7 @@ import AuthenticatedRoute from 'ghost/routes/authenticated'; -import base from 'ghost/mixins/editor-route-base'; +import base from 'ghost/mixins/editor-base-route'; var EditorNewRoute = AuthenticatedRoute.extend(base, { - classNames: ['editor'], - model: function () { var self = this; return this.get('session.user').then(function (user) { @@ -14,60 +12,13 @@ var EditorNewRoute = AuthenticatedRoute.extend(base, { }, setupController: function (controller, model) { - this._super(controller, model); - var psm = this.controllerFor('post-settings-menu'); // make sure there are no titleObserver functions hanging around // from previous posts psm.removeObserver('titleScratch', psm, 'titleObserver'); - controller.set('scratch', ''); - controller.set('titleScratch', ''); - - // used to check if anything has changed in the editor - controller.set('previousTagNames', Ember.A()); - - // attach model-related listeners created in editor-route-base - this.attachModelHooks(controller, model); - }, - - actions: { - willTransition: function (transition) { - var controller = this.get('controller'), - isDirty = controller.get('isDirty'), - - model = controller.get('model'), - isNew = model.get('isNew'), - isSaving = model.get('isSaving'), - isDeleted = model.get('isDeleted'), - modelIsDirty = model.get('isDirty'); - - this.send('closeSettingsMenu'); - - // when `isDeleted && isSaving`, model is in-flight, being saved - // to the server. when `isDeleted && !isSaving && !modelIsDirty`, - // the record has already been deleted and the deletion persisted. - // - // in either case we can probably just transition now. - // in the former case the server will return the record, thereby updating it. - // @TODO: this will break if the model fails server-side validation. - if (!(isDeleted && isSaving) && !(isDeleted && !isSaving && !modelIsDirty) && isDirty) { - transition.abort(); - this.send('openModal', 'leave-editor', [controller, transition]); - return; - } - - if (isNew) { - model.deleteRecord(); - } - - // since the transition is now certain to complete.. - window.onbeforeunload = null; - - // remove model-related listeners created in editor-route-base - this.detachModelHooks(controller, model); - } + this._super(controller, model); } }); diff --git a/core/client/utils/codemirror-shortcuts.js b/core/client/utils/codemirror-shortcuts.js index 5f18d29cf6..9ee73a5934 100644 --- a/core/client/utils/codemirror-shortcuts.js +++ b/core/client/utils/codemirror-shortcuts.js @@ -2,7 +2,7 @@ // jscs:disable disallowSpacesInsideParentheses /** Set up a shortcut function to be called via router actions. - * See editor-route-base + * See editor-base-route */ import titleize from 'ghost/utils/titleize';