Merge pull request #236 from resin-io/refactor/open-external-directive

Implement an `openExternal` attribute directive.
This commit is contained in:
Juan Cruz Viotti 2016-04-01 11:15:26 -04:00
commit 321dca0b25
6 changed files with 136 additions and 18 deletions

View File

@ -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) {

View File

@ -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;
});

View File

@ -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:
*
* <button open-external="https://resin.io">Resin.io</button>
*/
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);
});
}
};
};

View File

@ -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'));

View File

@ -21,7 +21,7 @@
</head>
<body ng-app="Etcher" style="display: none">
<header class="section-header" ng-controller="NavigationController as navigation">
<button class="btn btn-link" ng-click="navigation.open('https://github.com/resin-io/etcher/blob/master/SUPPORT.md')">
<button class="btn btn-link" open-external="https://github.com/resin-io/etcher/blob/master/SUPPORT.md">
<span class="glyphicon glyphicon-question-sign"></span> Need Help?
</button>
@ -39,13 +39,13 @@
<footer class="section-footer row between-xs middle-xs" ng-controller="NavigationController as navigation">
<div class="col-xs">
<div class="box text-left">
<hero-icon path="images/resin.svg" width="85px" height="auto" ng-click="navigation.open('https://resin.io')"></hero-icon>
<hero-icon path="images/resin.svg" width="85px" height="auto" open-external="https://resin.io"></hero-icon>
</div>
</div>
<div class="col-xs">
<div class="box text-right">
<p class="caption"><span ng-click="navigation.open('https://github.com/resin-io/etcher')">AN OPEN SOURCE PROJECT</span> BY <span ng-click="navigation.open('https://resin.io')">RESIN.IO</span></p>
<p class="caption"><span open-external="https://github.com/resin-io/etcher">AN OPEN SOURCE PROJECT</span> BY <span open-external="https://resin.io">RESIN.IO</span></p>
</div>
</div>
</footer>

View File

@ -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('<span open-external="https://resin.io">Resin.io</span>')($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('<span open-external="https://resin.io">Resin.io</span>')($rootScope);
element.triggerHandler('click');
$rootScope.$digest();
m.chai.expect(shellExternalStub).to.have.been.calledWith('https://resin.io');
shellExternalStub.restore();
});
});
});