upgrade: angular to v1.6.1; angular-ui-bootstrap to v2.5.0 (#1083)

Angular 1.5 has a bug that causes angular's `$exceptionHandler`
to be called for rejected `$q` promises even if they have
a rejection handler. This bug caused duplicate error messages
in Etcher.

A consequence of upgrading to Angular 1.6 is that `$q` promises
without a rejection handler will throw `Possibly unhandled rejection`
errors. To avoid these errors, this commit moves code responsible
for opening a tooltip from the template to the controller and handles
the rejection.

Other packages upgraded:
- angular-moment to v1.0.1
- angular-ui-router to v0.4.2
- angular-mocks to v1.6.1

Change-type: patch
Changelog-Entry: Fix duplicate error messages
Fixes: https://github.com/resin-io/etcher/issues/1082
See: https://github.com/angular/angular.js/issues/7992
See: https://github.com/angular/angular.js/pull/13662
This commit is contained in:
Ștefan Daniel Mihăilă 2017-02-08 01:12:32 +02:00 committed by Juan Cruz Viotti
parent f4c6597b3d
commit 92fdba3642
7 changed files with 51 additions and 29 deletions

View File

@ -21,6 +21,7 @@
*/ */
const angular = require('angular'); const angular = require('angular');
const _ = require('lodash');
const MODULE_NAME = 'Etcher.Modules.Error'; const MODULE_NAME = 'Etcher.Modules.Error';
const error = angular.module(MODULE_NAME, [ const error = angular.module(MODULE_NAME, [
@ -41,6 +42,10 @@ error.service('ErrorService', function(AnalyticsService, OSDialogService) {
* ErrorService.reportException(new Error('Something happened')); * ErrorService.reportException(new Error('Something happened'));
*/ */
this.reportException = (exception) => { this.reportException = (exception) => {
if (_.isUndefined(exception)) {
return;
}
OSDialogService.showError(exception, exception.description); OSDialogService.showError(exception, exception.description);
AnalyticsService.logException(exception); AnalyticsService.logException(exception);
}; };

View File

@ -22,6 +22,7 @@ module.exports = function(
FlashStateModel, FlashStateModel,
SettingsModel, SettingsModel,
TooltipModalService, TooltipModalService,
ErrorService,
OSOpenExternalService OSOpenExternalService
) { ) {
@ -31,7 +32,6 @@ module.exports = function(
this.state = FlashStateModel; this.state = FlashStateModel;
this.settings = SettingsModel; this.settings = SettingsModel;
this.external = OSOpenExternalService; this.external = OSOpenExternalService;
this.tooltipModal = TooltipModalService;
/** /**
* @summary Determine if the image step should be disabled * @summary Determine if the image step should be disabled
@ -65,4 +65,21 @@ module.exports = function(
return !SelectionStateModel.hasImage() || this.shouldImageStepBeDisabled(); return !SelectionStateModel.hasImage() || this.shouldImageStepBeDisabled();
}; };
/**
* @summary Display a tooltip with the selected image details
* @function
* @public
*
* @returns {Promise}
*
* @example
* MainController.showSelectedImageDetails()
*/
this.showSelectedImageDetails = () => {
return TooltipModalService.show({
title: 'Image File Name',
message: SelectionStateModel.getImagePath()
}).catch(ErrorService.reportException);
};
}; };

View File

@ -25,9 +25,12 @@
const angular = require('angular'); const angular = require('angular');
const MODULE_NAME = 'Etcher.Pages.Main'; const MODULE_NAME = 'Etcher.Pages.Main';
require('angular-moment');
const MainPage = angular.module(MODULE_NAME, [ const MainPage = angular.module(MODULE_NAME, [
'angularMoment',
require('angular-ui-router'), require('angular-ui-router'),
require('angular-moment'),
require('angular-middle-ellipses'), require('angular-middle-ellipses'),
require('angular-seconds-to-date'), require('angular-seconds-to-date'),

View File

@ -62,10 +62,7 @@
<div ng-if="main.selection.hasImage()"> <div ng-if="main.selection.hasImage()">
<div class="step-selection-text"> <div class="step-selection-text">
<span <span
ng-click="main.tooltipModal.show({ ng-click="main.showSelectedImageDetails()"
title: 'Image File Name',
message: main.selection.getImagePath()
})"
class="step-image step-name" class="step-image step-name"
ng-class="{ 'text-disabled': main.shouldImageStepBeDisabled() }" ng-class="{ 'text-disabled': main.shouldImageStepBeDisabled() }"
ng-bind="main.selection.getImageName() || main.selection.getImagePath() | basename | middleEllipses:20" ng-bind="main.selection.getImageName() || main.selection.getImagePath() | basename | middleEllipses:20"

30
npm-shrinkwrap.json generated
View File

@ -3,9 +3,9 @@
"version": "1.0.0-beta.18", "version": "1.0.0-beta.18",
"dependencies": { "dependencies": {
"angular": { "angular": {
"version": "1.5.7", "version": "1.6.1",
"from": "angular@>=1.5.3 <2.0.0", "from": "angular@>=1.6.1 <2.0.0",
"resolved": "https://registry.npmjs.org/angular/-/angular-1.5.7.tgz" "resolved": "https://registry.npmjs.org/angular/-/angular-1.6.1.tgz"
}, },
"angular-if-state": { "angular-if-state": {
"version": "1.0.0", "version": "1.0.0",
@ -13,9 +13,9 @@
"resolved": "https://registry.npmjs.org/angular-if-state/-/angular-if-state-1.0.0.tgz", "resolved": "https://registry.npmjs.org/angular-if-state/-/angular-if-state-1.0.0.tgz",
"dependencies": { "dependencies": {
"angular-ui-router": { "angular-ui-router": {
"version": "0.3.1", "version": "0.4.2",
"from": "angular-ui-router@>=0.3.1 <0.4.0", "from": "angular-ui-router@>=0.4.2 <0.5.0",
"resolved": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.3.1.tgz" "resolved": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.4.2.tgz"
} }
} }
}, },
@ -25,9 +25,9 @@
"resolved": "https://registry.npmjs.org/angular-middle-ellipses/-/angular-middle-ellipses-1.0.0.tgz" "resolved": "https://registry.npmjs.org/angular-middle-ellipses/-/angular-middle-ellipses-1.0.0.tgz"
}, },
"angular-moment": { "angular-moment": {
"version": "1.0.0-beta.6", "version": "1.0.1",
"from": "angular-moment@>=1.0.0-beta.6 <2.0.0", "from": "angular-moment@1.0.1",
"resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.0.0-beta.6.tgz" "resolved": "https://registry.npmjs.org/angular-moment/-/angular-moment-1.0.1.tgz"
}, },
"angular-seconds-to-date": { "angular-seconds-to-date": {
"version": "1.0.0", "version": "1.0.0",
@ -35,14 +35,14 @@
"resolved": "https://registry.npmjs.org/angular-seconds-to-date/-/angular-seconds-to-date-1.0.0.tgz" "resolved": "https://registry.npmjs.org/angular-seconds-to-date/-/angular-seconds-to-date-1.0.0.tgz"
}, },
"angular-ui-bootstrap": { "angular-ui-bootstrap": {
"version": "1.3.3", "version": "2.5.0",
"from": "angular-ui-bootstrap@>=1.3.2 <2.0.0", "from": "angular-ui-bootstrap@>=2.5.0 <2.6.0",
"resolved": "https://registry.npmjs.org/angular-ui-bootstrap/-/angular-ui-bootstrap-1.3.3.tgz" "resolved": "https://registry.npmjs.org/angular-ui-bootstrap/-/angular-ui-bootstrap-2.5.0.tgz"
}, },
"angular-ui-router": { "angular-ui-router": {
"version": "0.2.18", "version": "0.4.2",
"from": "angular-ui-router@>=0.2.18 <0.3.0", "from": "angular-ui-router@>=0.4.2 <0.5.0",
"resolved": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.2.18.tgz" "resolved": "https://registry.npmjs.org/angular-ui-router/-/angular-ui-router-0.4.2.tgz"
}, },
"ansi-escapes": { "ansi-escapes": {
"version": "1.4.0", "version": "1.4.0",

View File

@ -61,13 +61,13 @@
"removedrive": "^1.1.1" "removedrive": "^1.1.1"
}, },
"dependencies": { "dependencies": {
"angular": "^1.5.3", "angular": "^1.6.1",
"angular-if-state": "^1.0.0", "angular-if-state": "^1.0.0",
"angular-middle-ellipses": "^1.0.0", "angular-middle-ellipses": "^1.0.0",
"angular-moment": "^1.0.0-beta.6", "angular-moment": "^1.0.1",
"angular-seconds-to-date": "^1.0.0", "angular-seconds-to-date": "^1.0.0",
"angular-ui-bootstrap": "^1.3.2", "angular-ui-bootstrap": "^2.5.0",
"angular-ui-router": "^0.2.18", "angular-ui-router": "^0.4.2",
"archive-type": "^3.2.0", "archive-type": "^3.2.0",
"bluebird": "^3.0.5", "bluebird": "^3.0.5",
"bootstrap-sass": "^3.3.5", "bootstrap-sass": "^3.3.5",
@ -104,7 +104,7 @@
"yauzl": "^2.6.0" "yauzl": "^2.6.0"
}, },
"devDependencies": { "devDependencies": {
"angular-mocks": "^1.4.7", "angular-mocks": "^1.6.1",
"browserify": "^13.0.1", "browserify": "^13.0.1",
"electron-builder": "^2.6.0", "electron-builder": "^2.6.0",
"electron-mocha": "^3.1.1", "electron-mocha": "^3.1.1",

View File

@ -62,7 +62,7 @@ describe('Browser: ImageWriter', function() {
}); });
ImageWriterService.flash('foo.img', '/dev/disk2'); ImageWriterService.flash('foo.img', '/dev/disk2');
ImageWriterService.flash('foo.img', '/dev/disk2'); ImageWriterService.flash('foo.img', '/dev/disk2').catch(angular.noop);
$rootScope.$apply(); $rootScope.$apply();
m.chai.expect(this.performWriteStub).to.have.been.calledOnce; m.chai.expect(this.performWriteStub).to.have.been.calledOnce;
}); });
@ -97,13 +97,13 @@ describe('Browser: ImageWriter', function() {
}); });
it('should set flashing to false when done', function() { it('should set flashing to false when done', function() {
ImageWriterService.flash('foo.img', '/dev/disk2'); ImageWriterService.flash('foo.img', '/dev/disk2').catch(angular.noop);
$rootScope.$apply(); $rootScope.$apply();
m.chai.expect(FlashStateModel.isFlashing()).to.be.false; m.chai.expect(FlashStateModel.isFlashing()).to.be.false;
}); });
it('should set the error code in the flash results', function() { it('should set the error code in the flash results', function() {
ImageWriterService.flash('foo.img', '/dev/disk2'); ImageWriterService.flash('foo.img', '/dev/disk2').catch(angular.noop);
$rootScope.$apply(); $rootScope.$apply();
const flashResults = FlashStateModel.getFlashResults(); const flashResults = FlashStateModel.getFlashResults();
m.chai.expect(flashResults.errorCode).to.equal('FOO'); m.chai.expect(flashResults.errorCode).to.equal('FOO');