diff --git a/ghost/admin/app/components/gh-task-button.js b/ghost/admin/app/components/gh-task-button.js index e362fd45dd..7b2f305276 100644 --- a/ghost/admin/app/components/gh-task-button.js +++ b/ghost/admin/app/components/gh-task-button.js @@ -34,6 +34,7 @@ const GhTaskButton = Component.extend({ idleClass: '', runningClass: '', showSuccess: true, // set to false if you want the spinner to show until a transition occurs + autoReset: false, // set to false if you want don't want task button to reset after timeout successText: 'Saved', successClass: 'gh-btn-green', failureText: 'Retry', @@ -118,7 +119,6 @@ const GhTaskButton = Component.extend({ return false; } - let task = this.task; let taskName = this.get('task.name'); let lastTaskName = this.get('task.last.task.name'); @@ -128,9 +128,8 @@ const GhTaskButton = Component.extend({ if (this.isRunning && taskName === lastTaskName) { return; } - this.action(); - task.perform(this.taskArgs); + this._handleMainTask.perform(); this._restartAnimation.perform(); @@ -156,7 +155,24 @@ const GhTaskButton = Component.extend({ yield timeout(10); elem.classList.add('retry-animated'); } - }) + }), + + _handleMainTask: task(function* () { + this._resetButtonState.cancelAll(); + yield this.task.perform(this.taskArgs); + const isTaskSuccess = this.get('task.last.isSuccessful') && this.get('task.last.value'); + if (this.autoReset && this.showSuccess && isTaskSuccess) { + this._resetButtonState.perform(); + } + }), + + _resetButtonState: task(function* () { + yield timeout(2500); + if (!this.get('task.last.isRunning')) { + // Reset last task to bring button back to idle state + yield this.set('task.last', null); + } + }).restartable() }); export default GhTaskButton; diff --git a/ghost/admin/app/controllers/member.js b/ghost/admin/app/controllers/member.js index 146a101678..b43f2db5d2 100644 --- a/ghost/admin/app/controllers/member.js +++ b/ghost/admin/app/controllers/member.js @@ -6,7 +6,7 @@ import {alias} from '@ember/object/computed'; import {computed, defineProperty} from '@ember/object'; import {inject as controller} from '@ember/controller'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; const SCRATCH_PROPS = ['name', 'email', 'note']; @@ -89,7 +89,7 @@ export default Controller.extend({ } }, - save: task(function* () { + saveMember: task(function* () { let {member, scratchMember} = this; // if Cmd+S is pressed before the field loses focus make sure we're @@ -111,6 +111,15 @@ export default Controller.extend({ } }).drop(), + save: task(function* () { + yield this.saveMember.perform(); + yield timeout(2500); + if (this.get('saveMember.last.isSuccessful') && this.get('saveMember.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveMember.last', null); + } + }).drop(), + fetchMember: task(function* (memberId) { this.set('isLoading', true); diff --git a/ghost/admin/app/controllers/settings/code-injection.js b/ghost/admin/app/controllers/settings/code-injection.js index 403135582f..25b07cc1e2 100644 --- a/ghost/admin/app/controllers/settings/code-injection.js +++ b/ghost/admin/app/controllers/settings/code-injection.js @@ -1,7 +1,7 @@ /* eslint-disable ghost/ember/alias-model-in-controller */ import Controller from '@ember/controller'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; export default Controller.extend({ notifications: service(), @@ -53,7 +53,7 @@ export default Controller.extend({ }, - save: task(function* () { + saveTask: task(function* () { let notifications = this.notifications; try { @@ -62,5 +62,14 @@ export default Controller.extend({ notifications.showAPIError(error, {key: 'code-injection.save'}); throw error; } + }), + + save: task(function* () { + yield this.saveTask.perform(); + yield timeout(2500); + if (this.get('saveTask.last.isSuccessful') && this.get('saveTask.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveTask.last', null); + } }) }); diff --git a/ghost/admin/app/controllers/settings/design.js b/ghost/admin/app/controllers/settings/design.js index 2e6e7223ec..5d3e0e4964 100644 --- a/ghost/admin/app/controllers/settings/design.js +++ b/ghost/admin/app/controllers/settings/design.js @@ -8,7 +8,7 @@ import {isEmpty} from '@ember/utils'; import {isThemeValidationError} from 'ghost-admin/services/ajax'; import {notEmpty} from '@ember/object/computed'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; export default Controller.extend({ config: service(), @@ -200,7 +200,7 @@ export default Controller.extend({ } }, - save: task(function* () { + saveTask: task(function* () { let navItems = this.get('settings.navigation'); let secondaryNavItems = this.get('settings.secondaryNavigation'); @@ -235,6 +235,15 @@ export default Controller.extend({ } }), + save: task(function* () { + yield this.saveTask.perform(); + yield timeout(2500); + if (this.get('saveTask.last.isSuccessful') && this.get('saveTask.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveTask.last', null); + } + }), + addNewNavItem(item) { let navItems = item.isSecondary ? this.get('settings.secondaryNavigation') : this.get('settings.navigation'); diff --git a/ghost/admin/app/controllers/settings/general.js b/ghost/admin/app/controllers/settings/general.js index 9d5df5e47a..1b062ef436 100644 --- a/ghost/admin/app/controllers/settings/general.js +++ b/ghost/admin/app/controllers/settings/general.js @@ -11,7 +11,7 @@ import {computed} from '@ember/object'; import {htmlSafe} from '@ember/string'; import {run} from '@ember/runloop'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; const ICON_EXTENSIONS = ['ico', 'png']; @@ -321,7 +321,7 @@ export default Controller.extend({ }); }, - save: task(function* () { + saveSettings: task(function* () { let notifications = this.notifications; let config = this.config; @@ -339,5 +339,14 @@ export default Controller.extend({ } throw error; } + }), + + save: task(function* () { + yield this.saveSettings.perform(); + yield timeout(2500); + if (this.get('saveSettings.last.isSuccessful') && this.get('saveSettings.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveSettings.last', null); + } }) }); diff --git a/ghost/admin/app/controllers/settings/integration.js b/ghost/admin/app/controllers/settings/integration.js index 570a3e1222..b95478ecc7 100644 --- a/ghost/admin/app/controllers/settings/integration.js +++ b/ghost/admin/app/controllers/settings/integration.js @@ -134,10 +134,19 @@ export default Controller.extend({ }, - save: task(function* () { + saveIntegration: task(function* () { return yield this.integration.save(); }), + save: task(function* () { + yield this.saveIntegration.perform(); + yield timeout(2500); + if (this.get('saveIntegration.last.isSuccessful') && this.get('saveIntegration.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveIntegration.last', null); + } + }), + copyContentKey: task(function* () { copyTextToClipboard(this.integration.contentKey.secret); yield timeout(3000); diff --git a/ghost/admin/app/controllers/settings/integrations/amp.js b/ghost/admin/app/controllers/settings/integrations/amp.js index 1808b68757..186ee50016 100644 --- a/ghost/admin/app/controllers/settings/integrations/amp.js +++ b/ghost/admin/app/controllers/settings/integrations/amp.js @@ -2,7 +2,7 @@ import Controller from '@ember/controller'; import {alias} from '@ember/object/computed'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; export default Controller.extend({ notifications: service(), @@ -61,7 +61,7 @@ export default Controller.extend({ } }, - save: task(function* () { + saveTask: task(function* () { let amp = this.ampSettings; let settings = this.settings; @@ -73,5 +73,15 @@ export default Controller.extend({ this.notifications.showAPIError(error); throw error; } + }).drop(), + + save: task(function* () { + yield this.saveTask.perform(); + yield timeout(2500); + if (this.get('saveTask.last.isSuccessful') && this.get('saveTask.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveTask.last', null); + } }).drop() + }); diff --git a/ghost/admin/app/controllers/settings/integrations/slack.js b/ghost/admin/app/controllers/settings/integrations/slack.js index 42d6e4a9fa..a7f7be0007 100644 --- a/ghost/admin/app/controllers/settings/integrations/slack.js +++ b/ghost/admin/app/controllers/settings/integrations/slack.js @@ -4,7 +4,7 @@ import boundOneWay from 'ghost-admin/utils/bound-one-way'; import {empty} from '@ember/object/computed'; import {isInvalidError} from 'ember-ajax/errors'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; export default Controller.extend({ ghostPaths: service(), @@ -94,7 +94,7 @@ export default Controller.extend({ } }, - save: task(function* () { + saveTask: task(function* () { let slack = this.slackSettings; let settings = this.settings; let slackArray = this.slackArray; @@ -113,6 +113,15 @@ export default Controller.extend({ } }).drop(), + save: task(function* () { + yield this.saveTask.perform(); + yield timeout(2500); + if (this.get('saveTask.last.isSuccessful') && this.get('saveTask.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveTask.last', null); + } + }).drop(), + sendTestNotification: task(function* () { let notifications = this.notifications; let slackApi = this.get('ghostPaths.url').api('slack', 'test'); diff --git a/ghost/admin/app/controllers/settings/integrations/unsplash.js b/ghost/admin/app/controllers/settings/integrations/unsplash.js index c471a45d06..d65317006b 100644 --- a/ghost/admin/app/controllers/settings/integrations/unsplash.js +++ b/ghost/admin/app/controllers/settings/integrations/unsplash.js @@ -2,7 +2,7 @@ import Controller from '@ember/controller'; import {alias} from '@ember/object/computed'; import {inject as service} from '@ember/service'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; export default Controller.extend({ notifications: service(), @@ -68,7 +68,7 @@ export default Controller.extend({ } }, - save: task(function* () { + saveTask: task(function* () { let unsplash = this.unsplashSettings; let settings = this.settings; @@ -83,5 +83,14 @@ export default Controller.extend({ throw error; } } + }).drop(), + + save: task(function* () { + yield this.saveTask.perform(); + yield timeout(2500); + if (this.get('saveTask.last.isSuccessful') && this.get('saveTask.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveTask.last', null); + } }).drop() }); diff --git a/ghost/admin/app/controllers/tag.js b/ghost/admin/app/controllers/tag.js index cb8b0eb29b..fe506ba959 100644 --- a/ghost/admin/app/controllers/tag.js +++ b/ghost/admin/app/controllers/tag.js @@ -5,7 +5,7 @@ import {alias} from '@ember/object/computed'; import {computed, defineProperty} from '@ember/object'; import {inject as service} from '@ember/service'; import {slugify} from '@tryghost/string'; -import {task} from 'ember-concurrency'; +import {task, timeout} from 'ember-concurrency'; const SCRATCH_PROPS = ['name', 'slug', 'description', 'metaTitle', 'metaDescription']; @@ -74,7 +74,7 @@ export default Controller.extend({ } }, - save: task(function* () { + saveTask: task(function* () { let {tag, scratchTag} = this; // if Cmd+S is pressed before the field loses focus make sure we're @@ -96,6 +96,15 @@ export default Controller.extend({ } }), + save: task(function* () { + yield this.saveTask.perform(); + yield timeout(2500); + if (this.get('saveTask.last.isSuccessful') && this.get('saveTask.last.value')) { + // Reset last task to bring button back to idle state + yield this.set('saveTask.last', null); + } + }).drop(), + fetchTag: task(function* (slug) { this.set('isLoading', true); diff --git a/ghost/admin/app/templates/components/modal-custom-view-form.hbs b/ghost/admin/app/templates/components/modal-custom-view-form.hbs index 0277eea381..3d49bc138a 100644 --- a/ghost/admin/app/templates/components/modal-custom-view-form.hbs +++ b/ghost/admin/app/templates/components/modal-custom-view-form.hbs @@ -72,6 +72,7 @@ + @@ -55,7 +55,7 @@ {{else}} {{this.member.geolocation.country}} {{/if}} - {{else}} + {{else}} Unknown location {{/if}} – Created on {{this.subscribedAt}} diff --git a/ghost/admin/app/templates/settings/code-injection.hbs b/ghost/admin/app/templates/settings/code-injection.hbs index 55e8fce4a0..948a666a9a 100644 --- a/ghost/admin/app/templates/settings/code-injection.hbs +++ b/ghost/admin/app/templates/settings/code-injection.hbs @@ -4,7 +4,7 @@ Code injection
- +
diff --git a/ghost/admin/app/templates/settings/design.hbs b/ghost/admin/app/templates/settings/design.hbs index 76d0cd196f..4f04d00b1a 100644 --- a/ghost/admin/app/templates/settings/design.hbs +++ b/ghost/admin/app/templates/settings/design.hbs @@ -4,7 +4,7 @@ Design
- +
diff --git a/ghost/admin/app/templates/settings/general.hbs b/ghost/admin/app/templates/settings/general.hbs index 47dadf0d7c..768870601a 100644 --- a/ghost/admin/app/templates/settings/general.hbs +++ b/ghost/admin/app/templates/settings/general.hbs @@ -5,7 +5,7 @@ General settings
- +
diff --git a/ghost/admin/app/templates/settings/integration.hbs b/ghost/admin/app/templates/settings/integration.hbs index 6705b9063e..49a996b234 100644 --- a/ghost/admin/app/templates/settings/integration.hbs +++ b/ghost/admin/app/templates/settings/integration.hbs @@ -7,7 +7,7 @@ {{this.integration.name}}
- +
diff --git a/ghost/admin/app/templates/settings/integrations/amp.hbs b/ghost/admin/app/templates/settings/integrations/amp.hbs index d0243c1250..7a4795fcbc 100644 --- a/ghost/admin/app/templates/settings/integrations/amp.hbs +++ b/ghost/admin/app/templates/settings/integrations/amp.hbs @@ -6,7 +6,7 @@ AMP
- +
diff --git a/ghost/admin/app/templates/settings/integrations/slack.hbs b/ghost/admin/app/templates/settings/integrations/slack.hbs index 03745f7284..18e15c19dd 100644 --- a/ghost/admin/app/templates/settings/integrations/slack.hbs +++ b/ghost/admin/app/templates/settings/integrations/slack.hbs @@ -6,7 +6,7 @@ Slack
- +
diff --git a/ghost/admin/app/templates/settings/integrations/unsplash.hbs b/ghost/admin/app/templates/settings/integrations/unsplash.hbs index 5e79b27e65..4e439ab29d 100644 --- a/ghost/admin/app/templates/settings/integrations/unsplash.hbs +++ b/ghost/admin/app/templates/settings/integrations/unsplash.hbs @@ -6,7 +6,7 @@ Unsplash
- +
diff --git a/ghost/admin/app/templates/settings/labs.hbs b/ghost/admin/app/templates/settings/labs.hbs index 5f69fdc2b3..5f0041ab79 100644 --- a/ghost/admin/app/templates/settings/labs.hbs +++ b/ghost/admin/app/templates/settings/labs.hbs @@ -34,6 +34,7 @@ @task={{this.saveSettings}} @successText="Saved" @runningText="Saving" + @autoReset={{true}} @class="gh-btn gh-btn-blue gh-btn-icon" /> diff --git a/ghost/admin/app/templates/tag.hbs b/ghost/admin/app/templates/tag.hbs index 30fa660165..7ccc37ba9c 100644 --- a/ghost/admin/app/templates/tag.hbs +++ b/ghost/admin/app/templates/tag.hbs @@ -7,7 +7,7 @@ {{if this.tag.isNew "New tag" this.tag.name}}
- +