diff --git a/ghost/admin/app/components/modal-upgrade-host-limit-custom-theme.hbs b/ghost/admin/app/components/modal-upgrade-host-limit-custom-theme.hbs
index e8d3e26f22..3f4344d10b 100644
--- a/ghost/admin/app/components/modal-upgrade-host-limit-custom-theme.hbs
+++ b/ghost/admin/app/components/modal-upgrade-host-limit-custom-theme.hbs
@@ -6,7 +6,11 @@
- Your current plan only supports official themes. You can install them from the Ghost theme marketplace.
+ {{#if this.model.limitErrorMessage}}
+ {{html-safe this.model.limitErrorMessage}}
+ {{else}}
+ Your current plan only supports official themes. You can install them from the Ghost theme marketplace.
+ {{/if}}
diff --git a/ghost/admin/app/controllers/settings/theme.js b/ghost/admin/app/controllers/settings/theme.js
index f387cf38b2..6e0463889a 100644
--- a/ghost/admin/app/controllers/settings/theme.js
+++ b/ghost/admin/app/controllers/settings/theme.js
@@ -55,6 +55,7 @@ export default Controller.extend({
themes: null,
themeToDelete: null,
displayUpgradeModal: false,
+ limitErrorMessage: null,
init() {
this._super(...arguments);
@@ -73,6 +74,17 @@ export default Controller.extend({
async activateTheme(theme) {
const isOverLimit = await this.limit.checkWouldGoOverLimit('customThemes', {value: theme.name});
if (isOverLimit) {
+ try {
+ await this.limit.limiter.errorIfWouldGoOverLimit('customThemes', {value: theme.name});
+ this.limitErrorMessage = null;
+ } catch (error) {
+ if (error.errorType !== 'HostLimitError') {
+ throw error;
+ }
+
+ this.limitErrorMessage = error.message;
+ }
+
this.set('displayUpgradeModal', true);
return;
}
diff --git a/ghost/admin/app/routes/settings/theme/uploadtheme.js b/ghost/admin/app/routes/settings/theme/uploadtheme.js
index 027b4e5126..cf9de857ab 100644
--- a/ghost/admin/app/routes/settings/theme/uploadtheme.js
+++ b/ghost/admin/app/routes/settings/theme/uploadtheme.js
@@ -1,18 +1,42 @@
import AuthenticatedRoute from 'ghost-admin/routes/authenticated';
+import {inject as service} from '@ember/service';
-export default AuthenticatedRoute.extend({
+export default class UploadthemeRouter extends AuthenticatedRoute {
+ @service limit;
- model() {
- return this.store.findAll('theme');
- },
+ limitErrorMessage = null
+
+ async model() {
+ // TODO: The "Upload a theme" button may welcome a spinner in case the limiter introduces
+ // an actual async operation. Without a spinner the UI may seem unresponsive after a click.
+ const [themes] = await Promise.all([
+ this.store.findAll('theme'),
+ // Sending a bad string to make sure it fails (empty string isn't valid)
+ this.limit.limiter.errorIfWouldGoOverLimit('customThemes', {value: '.'})
+ .then(() => {
+ this.limitErrorMessage = null;
+ })
+ .catch((error) => {
+ if (error.errorType === 'HostLimitError') {
+ this.limitErrorMessage = error.message;
+ return;
+ }
+
+ throw error;
+ })
+ ]);
+
+ return themes;
+ }
setupController(controller, model) {
controller.set('themes', model);
- },
+ controller.set('limitErrorMessage', this.limitErrorMessage);
+ }
- actions: {
+ actions = {
cancel() {
this.transitionTo('settings.theme');
}
}
-});
+}
diff --git a/ghost/admin/app/templates/settings/theme.hbs b/ghost/admin/app/templates/settings/theme.hbs
index 8aa7332bc8..474cea4c3d 100644
--- a/ghost/admin/app/templates/settings/theme.hbs
+++ b/ghost/admin/app/templates/settings/theme.hbs
@@ -104,6 +104,9 @@
{{#if this.displayUpgradeModal}}