diff --git a/framework/core/js/src/common/Application.js b/framework/core/js/src/common/Application.js index b9ec8fa06..871f5797b 100644 --- a/framework/core/js/src/common/Application.js +++ b/framework/core/js/src/common/Application.js @@ -324,12 +324,15 @@ export default class Application { } const isDebug = app.forum.attribute('debug'); + // contains a formatted errors if possible, response must be an JSON API array of errors + // the details property is decoded to transform escaped characters such as '\n' + const formattedError = error.response && Array.isArray(error.response.errors) && error.response.errors.map((e) => decodeURI(e.detail)); error.alert = new Alert({ type: 'error', children, controls: isDebug && [ - , ], @@ -338,6 +341,17 @@ export default class Application { try { options.errorHandler(error); } catch (error) { + if (isDebug && error.xhr) { + const { method, url } = error.options; + const { status = '' } = error.xhr; + + console.group(`${method} ${url} ${status}`); + + console.error(...(formattedError || [error])); + + console.groupEnd(); + } + this.alerts.show(error.alert); } @@ -350,12 +364,13 @@ export default class Application { /** * @param {RequestError} error + * @param {string[]} [formattedError] * @private */ - showDebug(error) { + showDebug(error, formattedError) { this.alerts.dismiss(this.requestError.alert); - this.modal.show(new RequestErrorModal({ error })); + this.modal.show(new RequestErrorModal({ error, formattedError })); } /** diff --git a/framework/core/js/src/common/components/RequestErrorModal.js b/framework/core/js/src/common/components/RequestErrorModal.js index 2a0aaa2a7..af460e91e 100644 --- a/framework/core/js/src/common/components/RequestErrorModal.js +++ b/framework/core/js/src/common/components/RequestErrorModal.js @@ -6,16 +6,26 @@ export default class RequestErrorModal extends Modal { } title() { - return this.props.error.xhr ? this.props.error.xhr.status + ' ' + this.props.error.xhr.statusText : ''; + return this.props.error.xhr ? `${this.props.error.xhr.status} ${this.props.error.xhr.statusText}` : ''; } content() { + const { error, formattedError } = this.props; + let responseText; - try { - responseText = JSON.stringify(JSON.parse(this.props.error.responseText), null, 2); - } catch (e) { - responseText = this.props.error.responseText; + // If the error is already formatted, just add line endings; + // else try to parse it as JSON and stringify it with indentation + if (formattedError) { + responseText = formattedError.join('\n\n'); + } else { + try { + const json = error.response || JSON.parse(error.responseText); + + responseText = JSON.stringify(json, null, 2); + } catch (e) { + responseText = error.responseText; + } } return (