From d9cafc686e54b49b0922a4670d7372f0e45d86b4 Mon Sep 17 00:00:00 2001 From: jaden <noreply@example.com> Date: Wed, 24 May 2017 16:13:49 +0200 Subject: [PATCH] add errorService to handle user-facing errors --- .../static/reports/app/directives/error.js | 78 +++++++++++++++++++ .../static/reports/app/directives/lock.js | 9 ++- .../static/reports/app/directives/publish.js | 6 +- .../static/reports/app/directives/save.js | 5 +- .../reports/app/services/errorService.js | 71 +++++++++++++++++ .../web/reports/templates/reports/report.html | 2 + 6 files changed, 165 insertions(+), 6 deletions(-) create mode 100644 beat/web/reports/static/reports/app/directives/error.js create mode 100644 beat/web/reports/static/reports/app/services/errorService.js diff --git a/beat/web/reports/static/reports/app/directives/error.js b/beat/web/reports/static/reports/app/directives/error.js new file mode 100644 index 000000000..673449b70 --- /dev/null +++ b/beat/web/reports/static/reports/app/directives/error.js @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ + * Contact: beat.support@idiap.ch + * + * This file is part of the beat.web module of the BEAT platform. + * + * Commercial License Usage + * Licensees holding valid commercial BEAT licenses may use this file in + * accordance with the terms contained in a written agreement between you + * and Idiap. For further information contact tto@idiap.ch + * + * Alternatively, this file may be used under the terms of the GNU Affero + * Public License version 3 as published by the Free Software and appearing + * in the file LICENSE.AGPL included in the packaging of this file. + * The BEAT platform is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero Public License along + * with the BEAT platform. If not, see http://www.gnu.org/licenses/. + */ + +/* + * reportError + * Desc: + * Watches the ErrorService's error list and processes an error if + * its not empty. + * 'Processing': showing a modal to the user about the error. + * + */ +angular.module('reportApp') +.directive("reportError", ['ErrorService', '$timeout', function(ErrorService, $timeout){ + return { + scope: { + }, + restrict: 'E', + link: function(scope){ + scope.error = null; + + const processError = () => { + // if theres no error, return + if(!ErrorService._hasError){ + return; + } + + // save our error + scope.error = ErrorService._getError(); + + // pop up the modal + $('#errorReportModal').modal(); + }; + + $timeout(() => { + $('#errorReportModal').on('hidden.bs.modal', () => { + // finished processing the last error + scope.error = null; + + // process the next one, if there is one + processError(); + }); + }, 0); + + scope.$watch(ErrorService._hasError, processError); + }, + template: ` +<bootstrap-modal dom-id='errorReportModal' button-cancel-text='Continue'> + <b-title> + Error + </b-title> + <b-content> + <p>There was an error:</p> + <p>{{ error.message }}</p> + <pre>{{ error.error.message }}</pre> + </b-content> +</bootstrap-modal> +` + }; +}]); diff --git a/beat/web/reports/static/reports/app/directives/lock.js b/beat/web/reports/static/reports/app/directives/lock.js index ad02cd8d8..804acc148 100644 --- a/beat/web/reports/static/reports/app/directives/lock.js +++ b/beat/web/reports/static/reports/app/directives/lock.js @@ -26,14 +26,19 @@ * Displays a modal for locking the current report. */ angular.module('reportApp') -.directive("reportLock", ['ReportService', function(ReportService){ +.directive("reportLock", ['ReportService', 'ErrorService', function(ReportService, ErrorService){ return { scope: { }, restrict: 'E', link: function(scope, el){ // sends the request to lock the report - scope.lockReport = ReportService.lockReport; + scope.lockReport = () => { + return ReportService.lockReport() + .catch(e, () => { + ErrorService.logError(e, `Could not lock the report.`); + }); + } }, template: ` <bootstrap-modal dom-id='lockReportModal' button-submit-text='Lock' button-submit-func='lockReport'> diff --git a/beat/web/reports/static/reports/app/directives/publish.js b/beat/web/reports/static/reports/app/directives/publish.js index 4d20ca09b..8833a3445 100644 --- a/beat/web/reports/static/reports/app/directives/publish.js +++ b/beat/web/reports/static/reports/app/directives/publish.js @@ -28,7 +28,7 @@ * Visible or Public. */ angular.module('reportApp') -.directive("reportPublish", ['reportFactory', 'ReportService', '$timeout', function(reportFactory, ReportService, $timeout){ +.directive("reportPublish", ['reportFactory', 'ReportService', '$timeout', 'ErrorService', function(reportFactory, ReportService, $timeout, ErrorService){ return { scope: { }, @@ -49,8 +49,8 @@ angular.module('reportApp') res.data.forEach(a => scope.algorithms.push(a)); scope.algorithms.forEach(a => { scope.radios[a] = ''; }); }) - .catch(error => { - console.error(error); + .catch(e => { + ErrorService.logError(e, `Could not publish the report.`); }) ; }; diff --git a/beat/web/reports/static/reports/app/directives/save.js b/beat/web/reports/static/reports/app/directives/save.js index 0a2a40c53..a2f5b9605 100644 --- a/beat/web/reports/static/reports/app/directives/save.js +++ b/beat/web/reports/static/reports/app/directives/save.js @@ -26,7 +26,7 @@ * saves the current report */ angular.module('reportApp') -.directive("reportSave", ['GroupsService', 'ReportService', 'reportFactory', function(GroupsService, ReportService, reportFactory){ +.directive("reportSave", ['GroupsService', 'ReportService', 'reportFactory', 'ErrorService', function(GroupsService, ReportService, reportFactory, ErrorService){ return { scope: { }, @@ -42,6 +42,9 @@ angular.module('reportApp') }; return reportFactory.updateReport(ReportService.author, ReportService.name, saveData, '') + .catch(e => { + ErrorService.logError(e, `Could not save the report.`); + }); }; el.bind('click', saveReport); diff --git a/beat/web/reports/static/reports/app/services/errorService.js b/beat/web/reports/static/reports/app/services/errorService.js new file mode 100644 index 000000000..3343054bb --- /dev/null +++ b/beat/web/reports/static/reports/app/services/errorService.js @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016 Idiap Research Institute, http://www.idiap.ch/ + * Contact: beat.support@idiap.ch + * + * This file is part of the beat.web module of the BEAT platform. + * + * Commercial License Usage + * Licensees holding valid commercial BEAT licenses may use this file in + * accordance with the terms contained in a written agreement between you + * and Idiap. For further information contact tto@idiap.ch + * + * Alternatively, this file may be used under the terms of the GNU Affero + * Public License version 3 as published by the Free Software and appearing + * in the file LICENSE.AGPL included in the packaging of this file. + * The BEAT platform is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero Public License along + * with the BEAT platform. If not, see http://www.gnu.org/licenses/. + */ + +/* + * ErrorService + * Desc: + * Centralizes user-facing error-handling in the reports app. + * Other parts of the app can register errors (i.e. 404s, server errors, + * invalid input, etc.) with the ErrorService. + * The ErrorService will (one at a time & synchronously!) pop up an error + * modal (directives/error.js, "report-error") to let the user know. + */ +angular.module('reportApp').factory('ErrorService', [function(){ + const es = { + _errors: [], + _hasError: false + }; + + class ReportError { + constructor (errorObj, message) { + this._error = errorObj; + this._message = message || ''; + } + + get error () { + return this._error; + } + + get message () { + return this._message; + } + } + + es.logError = (error, message) => { + const newErr = new ReportError(error, message); + + es._errors.push(newErr); + _hasError = true; + }; + + es._getError = () => { + const err = es._errors.shift(); + + if(es._errors.length === 0){ + es._hasError = false; + } + + return err; + } + + return es; +}]); diff --git a/beat/web/reports/templates/reports/report.html b/beat/web/reports/templates/reports/report.html index 408849d16..80aa697e3 100644 --- a/beat/web/reports/templates/reports/report.html +++ b/beat/web/reports/templates/reports/report.html @@ -90,6 +90,7 @@ <script src="{% fingerprint "reports/app/services/urlService.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% fingerprint "reports/app/services/reportService.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% fingerprint "reports/app/services/plotService.js" %}" type="text/javascript" charset="utf-8"></script> + <script src="{% fingerprint "reports/app/services/errorService.js" %}" type="text/javascript" charset="utf-8"></script> <!-- directives --> @@ -100,6 +101,7 @@ <script src="{% fingerprint "reports/app/directives/publish.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% fingerprint "reports/app/directives/lock.js" %}" type="text/javascript" charset="utf-8"></script> <script src="{% fingerprint "reports/app/directives/save.js" %}" type="text/javascript" charset="utf-8"></script> + <script src="{% fingerprint "reports/app/directives/error.js" %}" type="text/javascript" charset="utf-8"></script> <!-- edit view --> {% if not report_number and report.get_status_display == 'Editable' and owner %} -- GitLab