Commit 8ceaab5f authored by Colin PUY's avatar Colin PUY

feat(assets) add error management while editing a local asset (#2044)

Display an error message when an error occurs while editing a local asset
Display a specific error message when trying to save a malformed json file

Closes [BS-15784](https://bonitasoft.atlassian.net/browse/BS-15784)
parent 7db175a8
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
// Jasmine // Jasmine
"describe": false, "describe": false,
"fail": false,
"beforeEach": false, "beforeEach": false,
"module": false, "module": false,
"inject": false, "inject": false,
......
...@@ -17,10 +17,11 @@ ...@@ -17,10 +17,11 @@
class AssetEditPopupCtrl { class AssetEditPopupCtrl {
constructor(asset, component, aceMode, $uibModalInstance, assetRepo) { constructor(asset, component, aceMode, $uibModalInstance, assetRepo, assetErrorManagement) {
this.asset = asset; this.asset = asset;
this.component = component; this.component = component;
this.$uibModalInstance = $uibModalInstance; this.$uibModalInstance = $uibModalInstance;
this.assetErrorManagement = assetErrorManagement;
this.assetRepo = assetRepo; this.assetRepo = assetRepo;
this.aceMode = aceMode; this.aceMode = aceMode;
this.content = ''; this.content = '';
...@@ -33,6 +34,7 @@ ...@@ -33,6 +34,7 @@
save() { save() {
this.assetRepo this.assetRepo
.updateLocalAssetContent(this.component.id, this.asset, this.content) .updateLocalAssetContent(this.component.id, this.asset, this.content)
.then((response) => this.assetErrorManagement.manageErrorsFromResponse(response))
.then(() => this.$uibModalInstance.close()); .then(() => this.$uibModalInstance.close());
} }
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
.module('bonitasoft.designer.assets') .module('bonitasoft.designer.assets')
.controller('AssetPopupCtrl', AssetPopupCtrl); .controller('AssetPopupCtrl', AssetPopupCtrl);
function AssetPopupCtrl($scope, $uibModalInstance, alerts, assetsService, assetRepo, asset, assets, mode, artifact, gettextCatalog) { function AssetPopupCtrl($scope, $uibModalInstance, alerts, assetsService, assetRepo, asset, assets, mode, artifact, gettextCatalog, assetErrorManagement) {
var urlPrefixForLocalAsset = 'rest/' + mode + 's/' + artifact.id + '/assets/'; var urlPrefixForLocalAsset = 'rest/' + mode + 's/' + artifact.id + '/assets/';
...@@ -63,28 +63,14 @@ ...@@ -63,28 +63,14 @@
// else nothing to do, form will be submitted as standard multipart/form-data form // else nothing to do, form will be submitted as standard multipart/form-data form
} }
function hasError(response) {
return response && response.type && response.message;
}
/** /**
* A local asset (file) is saved by the submit of the html form * A local asset (file) is saved by the submit of the html form
*/ */
function onComplete(response) { function onComplete(response) {
//Even if a problem occurs in the backend a response is sent with a message assetErrorManagement.manageErrorsFromResponse(response).then(
//If the message has a type and a message this an error (response) => $uibModalInstance.close(response),
if (hasError(response)) { () => vm.cancel()
if (response.type === 'MalformedJsonException') { );
alerts.addError({
contentUrl: 'js/assets/malformed-json-error-message.html',
context: response
}, 12000);
} else {
alerts.addError(response.message);
}
vm.cancel();
}
$uibModalInstance.close(response);
} }
/** /**
......
(() => {
class AsserErrorManagement {
/* @ngInject */
constructor(alerts, $q) {
this.alerts = alerts;
this.$q = $q;
}
displayError(response) {
if (response.type === 'MalformedJsonException') {
this.alerts.addError({
contentUrl: 'js/assets/malformed-json-error-message.html',
context: response
}, 12000);
} else {
this.alerts.addError(response.message);
}
}
hasError(response) {
return response && response.type && response.message;
}
manageErrorsFromResponse(response) {
if (this.hasError(response)) {
this.displayError(response);
return this.$q.reject(response);
} else {
return this.$q.when(response);
}
}
}
angular
.module('bonitasoft.designer.assets')
.service('assetErrorManagement', AsserErrorManagement);
})();
<p> <p>
<strong translate>Malformed json file</strong> <strong translate>Malformed json file</strong>
<div translate>Asset has not been imported</div> <div translate>Asset has not been saved</div>
<div translate>Error at line <code>{{ infos.location.line }}</code>, column <code>{{ infos.location.column }}</code></div> <div translate>Error at line <code>{{ infos.location.line }}</code>, column <code>{{ infos.location.column }}</code></div>
</p> </p>
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
// See section 5.1.1. (Multipart Media Type / Common Syntax) of rfc2046 https://www.ietf.org/rfc/rfc2046.txt // See section 5.1.1. (Multipart Media Type / Common Syntax) of rfc2046 https://www.ietf.org/rfc/rfc2046.txt
'Content-Type': undefined 'Content-Type': undefined
} }
}); }).then(response => response.data);
} }
loadLocalAssetContent(componentId, asset) { loadLocalAssetContent(componentId, asset) {
......
...@@ -9,7 +9,6 @@ describe('AssetPopupCtrl', function() { ...@@ -9,7 +9,6 @@ describe('AssetPopupCtrl', function() {
asset: asset, asset: asset,
assets: assets, assets: assets,
assetsService: assetsService, assetsService: assetsService,
alerts: alerts,
mode: mode, mode: mode,
artifact: { id: 12 }, artifact: { id: 12 },
assetRepo: assetRepo assetRepo: assetRepo
...@@ -27,7 +26,8 @@ describe('AssetPopupCtrl', function() { ...@@ -27,7 +26,8 @@ describe('AssetPopupCtrl', function() {
assetsService = $injector.get('assetsService'); assetsService = $injector.get('assetsService');
injector = $injector; injector = $injector;
$uibModalInstance = jasmine.createSpyObj('$uibModalInstance', ['dismiss', 'close']); $uibModalInstance = jasmine.createSpyObj('$uibModalInstance', ['dismiss', 'close']);
alerts = jasmine.createSpyObj('alerts', ['addError']); alerts = $injector.get('alerts');
spyOn(alerts, 'addError');
assets = []; assets = [];
asset = { asset = {
...@@ -56,21 +56,23 @@ describe('AssetPopupCtrl', function() { ...@@ -56,21 +56,23 @@ describe('AssetPopupCtrl', function() {
var response = { type: 'error', message: 'an error occured' }; var response = { type: 'error', message: 'an error occured' };
controller.onComplete(response); controller.onComplete(response);
$rootScope.$apply();
expect(alerts.addError).toHaveBeenCalledWith(response.message); expect(alerts.addError).toHaveBeenCalledWith(response.message);
expect($uibModalInstance.close).toHaveBeenCalled(); expect($uibModalInstance.dismiss).toHaveBeenCalled();
}); });
it('should display a specific error while uploading a malformed json file for json asset', function() { it('should display a specific error while uploading a malformed json file for json asset', function() {
var response = { type: 'MalformedJsonException', message: 'an error occured', infos: { location: {column: 65, line: 12}} }; var response = { type: 'MalformedJsonException', message: 'an error occured', infos: { location: {column: 65, line: 12}} };
controller.onComplete(response); controller.onComplete(response);
$rootScope.$apply();
expect(alerts.addError).toHaveBeenCalledWith({ expect(alerts.addError).toHaveBeenCalledWith({
contentUrl: 'js/assets/malformed-json-error-message.html', contentUrl: 'js/assets/malformed-json-error-message.html',
context: response context: response
}, 12000); }, 12000);
expect($uibModalInstance.close).toHaveBeenCalled(); expect($uibModalInstance.dismiss).toHaveBeenCalled();
}); });
it('should send external data to the caller when user want to save it', function() { it('should send external data to the caller when user want to save it', function() {
......
describe('AsserErrorManagement service', () => {
var assetErrorManagement, alerts, $scope;
beforeEach(angular.mock.module('bonitasoft.designer.assets'));
beforeEach(inject(function (_assetErrorManagement_, _alerts_, $rootScope) {
assetErrorManagement = _assetErrorManagement_;
alerts = _alerts_;
$scope = $rootScope;
spyOn(alerts, 'addError');
}));
it('should resolve promise when no error has occured', function () {
var response = {'id': '3fdf575e-f589-4b8e-807c-295f18bee9cc', 'name': 'localization.json', 'type': 'json', 'order': 2, 'active': true, 'external': false};
assetErrorManagement.manageErrorsFromResponse(response)
.then(
(promiseResponse) => expect(promiseResponse).toEqual(response),
() => fail('Promise should not be rejected'));
$scope.$apply();
});
it('should diplay error and reject promise when response contains error after form submit', function () {
var response = {type: 'error', message: 'an error occured'};
assetErrorManagement.manageErrorsFromResponse(response)
.then(
() => fail('Promise should not be resolved'),
(promiseResponse) => {
expect(alerts.addError).toHaveBeenCalledWith(response.message);
expect(promiseResponse).toEqual(response);
});
$scope.$apply();
});
it('should display a specific error while uploading a malformed json file for json asset', function () {
var response = {type: 'MalformedJsonException', message: 'an error occured', infos: {location: {column: 65, line: 12}}};
assetErrorManagement.manageErrorsFromResponse(response)
.then(
() => fail('Promise should not be resolved'),
(promiseResponse) => {
expect(alerts.addError).toHaveBeenCalledWith({
contentUrl: 'js/assets/malformed-json-error-message.html',
context: response
}, 12000);
expect(promiseResponse).toEqual(response);
});
$scope.$apply();
});
});
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment