From 926f0283b5f480e401e0db2efe95925c941e3b8a Mon Sep 17 00:00:00 2001 From: Kevin Ansfield Date: Wed, 24 Aug 2016 19:22:20 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20detailed=20theme=20validation=20err?= =?UTF-8?q?ors=20(#226)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit no issue - display the detailed validation errors that we get back from gscan so that users know how to fix their themes --- .../app/components/modals/upload-theme.js | 15 +++- ghost/admin/app/services/ajax.js | 24 ++++++ ghost/admin/app/styles/layouts/settings.css | 19 ++++ .../components/modals/upload-theme.hbs | 26 ++++++ .../tests/acceptance/settings/general-test.js | 86 ++++++++++++++++++- 5 files changed, 167 insertions(+), 3 deletions(-) diff --git a/ghost/admin/app/components/modals/upload-theme.js b/ghost/admin/app/components/modals/upload-theme.js index bb7a4d080f..8e606c1652 100644 --- a/ghost/admin/app/components/modals/upload-theme.js +++ b/ghost/admin/app/components/modals/upload-theme.js @@ -2,7 +2,10 @@ import ModalComponent from 'ghost-admin/components/modals/base'; import computed, {mapBy, or} from 'ember-computed'; import {invokeAction} from 'ember-invoke-action'; import ghostPaths from 'ghost-admin/utils/ghost-paths'; -import {UnsupportedMediaTypeError} from 'ghost-admin/services/ajax'; +import { + UnsupportedMediaTypeError, + isThemeValidationError +} from 'ghost-admin/services/ajax'; import {isBlank} from 'ember-utils'; import run from 'ember-runloop'; import injectService from 'ember-service/inject'; @@ -91,6 +94,12 @@ export default ModalComponent.extend({ invokeAction(this, 'model.uploadSuccess', this.get('theme')); }, + uploadFailed(error) { + if (isThemeValidationError(error)) { + this.set('validationErrors', error.errors[0].errorDetails); + } + }, + confirm() { // noop - we don't want the enter key doing anything }, @@ -104,6 +113,10 @@ export default ModalComponent.extend({ if (!this.get('closeDisabled')) { this._super(...arguments); } + }, + + reset() { + this.set('validationErrors', null); } } }); diff --git a/ghost/admin/app/services/ajax.js b/ghost/admin/app/services/ajax.js index 6929054da0..f533f6715b 100644 --- a/ghost/admin/app/services/ajax.js +++ b/ghost/admin/app/services/ajax.js @@ -88,6 +88,24 @@ export function isMaintenanceError(errorOrStatus) { } } +/* Theme validation error */ + +export function ThemeValidationError(errors) { + AjaxError.call(this, errors, 'Theme is not compatible or contains errors.'); +} + +ThemeValidationError.prototype = Object.create(AjaxError.prototype); + +export function isThemeValidationError(errorOrStatus, payload) { + if (isAjaxError(errorOrStatus)) { + return errorOrStatus instanceof ThemeValidationError; + } else if (errorOrStatus && get(errorOrStatus, 'isAdapterError')) { + return get(errorOrStatus, 'errors.firstObject.errorType') === 'ThemeValidationError'; + } else { + return get(payload || {}, 'errors.firstObject.errorType') === 'ThemeValidationError'; + } +} + /* end: custom error types */ export default AjaxService.extend({ @@ -119,6 +137,8 @@ export default AjaxService.extend({ return new UnsupportedMediaTypeError(payload.errors); } else if (this.isMaintenanceError(status, headers, payload)) { return new MaintenanceError(payload.errors); + } else if (this.isThemeValidationError(status, headers, payload)) { + return new ThemeValidationError(payload.errors); } return this._super(...arguments); @@ -160,5 +180,9 @@ export default AjaxService.extend({ isMaintenanceError(status, headers, payload) { return isMaintenanceError(status, payload); + }, + + isThemeValidationError(status, headers, payload) { + return isThemeValidationError(status, payload); } }); diff --git a/ghost/admin/app/styles/layouts/settings.css b/ghost/admin/app/styles/layouts/settings.css index 82753a3137..9343bbb477 100644 --- a/ghost/admin/app/styles/layouts/settings.css +++ b/ghost/admin/app/styles/layouts/settings.css @@ -251,3 +251,22 @@ a.theme-list-action { margin-right: 20px; } } + +.theme-validation-errors { + padding-left: 0; +} + +.theme-validation-errors p { + margin-bottom: 0; +} + +.theme-validation-errors > li { + margin-bottom: 1.2em; + list-style: none; + font-size: 15px; +} + +.theme-validation-errors > li > ul { + margin-top: 0.2em; + font-size: 13px; +} diff --git a/ghost/admin/app/templates/components/modals/upload-theme.hbs b/ghost/admin/app/templates/components/modals/upload-theme.hbs index 330bd6eb28..906824e8c7 100644 --- a/ghost/admin/app/templates/components/modals/upload-theme.hbs +++ b/ghost/admin/app/templates/components/modals/upload-theme.hbs @@ -2,6 +2,8 @@

{{#if theme}} Upload successful! + {{else if validationErrors}} + Invalid theme {{else}} Upload a theme {{/if}} @@ -19,6 +21,24 @@

"{{fileThemeName}}" will overwrite an existing theme of the same name. Are you sure?

+ {{else if validationErrors}} + {{else}} {{gh-file-uploader url=uploadUrl @@ -29,6 +49,7 @@ uploadStarted=(action "uploadStarted") uploadFinished=(action "uploadFinished") uploadSuccess=(action "uploadSuccess") + uploadFailed=(action "uploadFailed") listenTo="themeUploader"}} {{/if}} @@ -42,6 +63,11 @@ Overwrite {{/if}} + {{#if validationErrors}} + + {{/if}} {{#if canActivateTheme}}