From 6aabb086605401f983151b3efdab99384d811dd1 Mon Sep 17 00:00:00 2001 From: Fabian Becker Date: Tue, 24 Jun 2014 10:00:28 +0000 Subject: [PATCH] Close notifications on transition or user action. closes #3012 - Inject notification object into router - Listen to didTransition / observe currentPath to close notifications - Close notifications on successful save actions --- core/client/controllers/modals/delete-post.js | 2 +- core/client/controllers/settings/general.js | 3 ++ core/client/controllers/settings/user.js | 5 +++ core/client/initializers/notifications.js | 1 + core/client/mixins/editor-base-controller.js | 7 ++- core/client/router.js | 8 +++- core/client/routes/signout.js | 4 +- core/client/utils/notifications.js | 44 +++++++++++++------ 8 files changed, 54 insertions(+), 20 deletions(-) diff --git a/core/client/controllers/modals/delete-post.js b/core/client/controllers/modals/delete-post.js index adf83064b9..c7f531aa31 100644 --- a/core/client/controllers/modals/delete-post.js +++ b/core/client/controllers/modals/delete-post.js @@ -9,8 +9,8 @@ var DeletePostController = Ember.Controller.extend({ model.destroyRecord().then(function () { self.get('popover').closePopovers(); - self.notifications.showSuccess('Your post has been deleted.'); self.transitionToRoute('posts.index'); + self.notifications.showSuccess('Your post has been deleted.', true); }, function () { self.notifications.showError('Your post could not be deleted. Please try again.'); }); diff --git a/core/client/controllers/settings/general.js b/core/client/controllers/settings/general.js index 159e03688a..c3486a5a46 100644 --- a/core/client/controllers/settings/general.js +++ b/core/client/controllers/settings/general.js @@ -31,6 +31,9 @@ var SettingsGeneralController = Ember.ObjectController.extend({ var self = this; return this.get('model').save().then(function (model) { + // @TODO This should call closePassive() to only close passive notifications + self.notifications.closeAll(); + self.notifications.showSuccess('Settings successfully saved.'); return model; }).catch(this.notifications.showErrors); diff --git a/core/client/controllers/settings/user.js b/core/client/controllers/settings/user.js index f14d82630e..4c80a1af52 100644 --- a/core/client/controllers/settings/user.js +++ b/core/client/controllers/settings/user.js @@ -21,10 +21,15 @@ var SettingsUserController = Ember.Controller.extend({ actions: { save: function () { + var self = this; + alert('@TODO: Saving user...'); if (this.user.validate().get('isValid')) { this.user.save().then(function (response) { + + // @TODO This should call closePassive() to only close passive notifications + self.notifications.closeAll(); alert('Done saving' + JSON.stringify(response)); }, function () { alert('Error saving.'); diff --git a/core/client/initializers/notifications.js b/core/client/initializers/notifications.js index f4dfaaa997..e0827b9574 100644 --- a/core/client/initializers/notifications.js +++ b/core/client/initializers/notifications.js @@ -8,6 +8,7 @@ var injectNotificationsInitializer = { application.inject('controller', 'notifications', 'notifications:main'); application.inject('component', 'notifications', 'notifications:main'); + application.inject('router', 'notifications', 'notifications:main'); application.inject('route', 'notifications', 'notifications:main'); } }; diff --git a/core/client/mixins/editor-base-controller.js b/core/client/mixins/editor-base-controller.js index e4ab90ec96..e678a3f403 100644 --- a/core/client/mixins/editor-base-controller.js +++ b/core/client/mixins/editor-base-controller.js @@ -118,11 +118,11 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, { actions: { save: function () { var status = this.get('willPublish') ? 'published' : 'draft', + isNew = this.get('isNew'), self = this; // set markdown equal to what's in the editor, minus the image markers. this.set('markdown', this.getMarkdown().withoutMarkers); - this.set('status', status); return this.get('model').save().then(function (model) { @@ -131,8 +131,11 @@ var EditorControllerMixin = Ember.Mixin.create(MarkerManager, { // for a saved model it would otherwise be false. self.set('isDirty', false); + // @TODO This should call closePassive() to only close passive notifications + self.notifications.closeAll(); + self.notifications.showSuccess('Post status saved as ' + - model.get('status') + '.'); + model.get('status') + '.', isNew ? true : false); return model; }).catch(function (errors) { self.notifications.showErrors(errors); diff --git a/core/client/router.js b/core/client/router.js index 45bcf39fd1..798f28b115 100644 --- a/core/client/router.js +++ b/core/client/router.js @@ -6,7 +6,13 @@ var Router = Ember.Router.extend(); Router.reopen({ location: 'trailing-history', // use HTML5 History API instead of hash-tag based URLs - rootURL: ghostPaths().subdir + '/ghost/ember/' // admin interface lives under sub-directory /ghost + rootURL: ghostPaths().subdir + '/ghost/ember/', // admin interface lives under sub-directory /ghost + + clearNotifications: function () { + // @TODO This should call closePassive() to only close passive notifications + this.notifications.closeAll(); + this.notifications.displayDelayed(); + }.on('didTransition') }); Router.map(function () { diff --git a/core/client/routes/signout.js b/core/client/routes/signout.js index 6d7e086b36..9b20f95446 100644 --- a/core/client/routes/signout.js +++ b/core/client/routes/signout.js @@ -16,10 +16,10 @@ var SignoutRoute = AuthenticatedRoute.extend(styleBody, loadingIndicator, { 'X-CSRF-Token': this.get('csrf') } }).then(function () { - self.notifications.showSuccess('You were successfully signed out.'); self.transitionTo('signin'); + self.notifications.showSuccess('You were successfully signed out.', true); }, function (resp) { - self.notifications.showAPIError(resp, 'There was a problem logging out, please try again.'); + self.notifications.showAPIError(resp, 'There was a problem logging out, please try again.', true); self.transitionTo('posts'); }); } diff --git a/core/client/utils/notifications.js b/core/client/utils/notifications.js index 43e4f8d044..f2e3ad30d3 100644 --- a/core/client/utils/notifications.js +++ b/core/client/utils/notifications.js @@ -1,4 +1,5 @@ var Notifications = Ember.ArrayProxy.extend({ + delayedNotifications: [], content: Ember.A(), timeout: 3000, pushObject: function (object) { @@ -9,43 +10,58 @@ var Notifications = Ember.ArrayProxy.extend({ } this._super(object); }, - showError: function (message) { - this.pushObject({ + handleNotification: function (message, delayed) { + if (!delayed) { + this.pushObject(message); + } else { + this.delayedNotifications.push(message); + } + }, + showError: function (message, delayed) { + this.handleNotification({ type: 'error', message: message - }); + }, delayed); }, showErrors: function (errors) { for (var i = 0; i < errors.length; i += 1) { this.showError(errors[i].message || errors[i]); } }, - showAPIError: function (resp, defaultErrorText) { + showAPIError: function (resp, defaultErrorText, delayed) { defaultErrorText = defaultErrorText || 'There was a problem on the server, please try again.'; if (resp && resp.jqXHR && resp.jqXHR.responseJSON && resp.jqXHR.responseJSON.error) { - this.showError(resp.jqXHR.responseJSON.error); + this.showError(resp.jqXHR.responseJSON.error, delayed); } else { - this.showError(defaultErrorText); + this.showError(defaultErrorText, delayed); } }, - showInfo: function (message) { - this.pushObject({ + showInfo: function (message, delayed) { + this.handleNotification({ type: 'info', message: message - }); + }, delayed); }, - showSuccess: function (message) { - this.pushObject({ + showSuccess: function (message, delayed) { + this.handleNotification({ type: 'success', message: message - }); + }, delayed); }, - showWarn: function (message) { - this.pushObject({ + showWarn: function (message, delayed) { + this.handleNotification({ type: 'warn', message: message + }, delayed); + }, + displayDelayed: function () { + var self = this; + + self.delayedNotifications.forEach(function (message) { + self.pushObject(message); }); + self.delayedNotifications = []; }, closeAll: function () { this.clear();