diff --git a/lib/browser/app.js b/lib/browser/app.js index 252f2155..6eed3530 100644 --- a/lib/browser/app.js +++ b/lib/browser/app.js @@ -39,6 +39,7 @@ require('./browser/components/drive-selector'); require('./browser/pages/finish/finish'); require('./browser/pages/settings/settings'); require('./browser/utils/window-progress/window-progress'); +require('./browser/utils/open-external/open-external'); const app = angular.module('Etcher', [ 'ui.router', @@ -66,7 +67,8 @@ const app = angular.module('Etcher', [ 'Etcher.Pages.Settings', // Utils - 'Etcher.Utils.WindowProgress' + 'Etcher.Utils.WindowProgress', + 'Etcher.Utils.OpenExternal' ]); app.config(function($stateProvider, $urlRouterProvider) { diff --git a/lib/browser/controllers/navigation.js b/lib/browser/controllers/navigation.js index f31789d2..201a5a78 100644 --- a/lib/browser/controllers/navigation.js +++ b/lib/browser/controllers/navigation.js @@ -20,8 +20,6 @@ * @module Etcher.controllers.navigation */ -const electron = require('electron'); -const shell = electron.remote.require('shell'); const angular = require('angular'); require('angular-ui-router'); @@ -46,16 +44,4 @@ navigation.controller('NavigationController', function($state) { */ this.isState = $state.is; - /** - * @summary Open external resource - * @function - * @public - * - * @param {String} resource - resource - * - * @example - * NavigationController.open('https://google.com'); - */ - this.open = shell.openExternal; - }); diff --git a/lib/browser/utils/open-external/directives/open-external.js b/lib/browser/utils/open-external/directives/open-external.js new file mode 100644 index 00000000..5f86d75f --- /dev/null +++ b/lib/browser/utils/open-external/directives/open-external.js @@ -0,0 +1,48 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const electron = require('electron'); +const shell = electron.remote.require('shell'); + +/** + * This directive provides an attribute to open an external + * resource with the default operating system action. + * + * Example: + * + * + */ + +module.exports = function() { + return { + restrict: 'A', + scope: { + openExternal: '@' + }, + link: function(scope, element) { + + // This directive might be added to elements + // other than buttons. + element.css('cursor', 'pointer'); + + element.on('click', function() { + shell.openExternal(scope.openExternal); + }); + } + }; +}; diff --git a/lib/browser/utils/open-external/open-external.js b/lib/browser/utils/open-external/open-external.js new file mode 100644 index 00000000..821e707f --- /dev/null +++ b/lib/browser/utils/open-external/open-external.js @@ -0,0 +1,25 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +/** + * @module Etcher.Utils.OpenExternal + */ + +const angular = require('angular'); +const OpenExternal = angular.module('Etcher.Utils.OpenExternal', []); +OpenExternal.directive('openExternal', require('./directives/open-external')); diff --git a/lib/index.html b/lib/index.html index ee903519..f22fd169 100644 --- a/lib/index.html +++ b/lib/index.html @@ -21,7 +21,7 @@
- @@ -39,13 +39,13 @@ diff --git a/tests/browser/utils/open-external.spec.js b/tests/browser/utils/open-external.spec.js new file mode 100644 index 00000000..ba6b8fe9 --- /dev/null +++ b/tests/browser/utils/open-external.spec.js @@ -0,0 +1,57 @@ +/* + * Copyright 2016 Resin.io + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +'use strict'; + +const m = require('mochainon'); +const angular = require('angular'); +const electron = require('electron'); +const shell = electron.remote.require('shell'); +require('angular-mocks'); +require('../../../lib/browser/utils/open-external/open-external'); + +describe('Browser: OpenExternal', function() { + + beforeEach(angular.mock.module('Etcher.Utils.OpenExternal')); + + describe('openExternal', function() { + + let $compile; + let $rootScope; + + beforeEach(angular.mock.inject(function(_$compile_, _$rootScope_) { + $compile = _$compile_; + $rootScope = _$rootScope_; + })); + + it('should set the element cursor to pointer', function() { + const element = $compile('Resin.io')($rootScope); + $rootScope.$digest(); + m.chai.expect(element.css('cursor')).to.equal('pointer'); + }); + + it('should call Electron shell.openExternal with the attribute value', function() { + const shellExternalStub = m.sinon.stub(shell, 'openExternal'); + const element = $compile('Resin.io')($rootScope); + element.triggerHandler('click'); + $rootScope.$digest(); + m.chai.expect(shellExternalStub).to.have.been.calledWith('https://resin.io'); + shellExternalStub.restore(); + }); + + }); + +});