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}}