mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-24 03:36:36 +00:00
feat(GUI): rich image extensions (#597)
The following PRs add support for a custom `_info` directory containing metadata such an image URL, display name, logo, etc in `etcher-image-stream`: - https://github.com/resin-io-modules/etcher-image-stream/pull/16 - https://github.com/resin-io-modules/etcher-image-stream/pull/14 - https://github.com/resin-io-modules/etcher-image-stream/pull/13 Now that this module supports such metadata, we make use of it in the GUI as follows: - The file name is replaced with the display name. - The file name links to the image URL. - The "Select Image" logo is replaced with the image logo. Some miscellaneous changes introduces in this PR to support the changes described above: - Implement `SelectionStateModel.getImageUrl()`. - Implement `SelectionStateModel.getImageLogo()`. - Implement `SelectionStateModel.getImageName()`. - Ignore the "logo" image property when displaying the "Select image" event, in order to not fill the console with SVG contents. - Make `svg-icon` understand SVG strings as paths. - Make `svg-icon` react to changes to the `path` attribute. - Extract the core functionality of `openExternal` into `OSOpenExternalService`. - Upgrade `etcher-image-stream` to v3.0.1. Change-Type: minor Changelog-Entry: Support rich image extensions. Fixes: https://github.com/resin-io/etcher/issues/470 Signed-off-by: Juan Cruz Viotti <jviottidc@gmail.com>
This commit is contained in:
parent
ce9093625b
commit
7e0f54e7d6
@ -146,7 +146,8 @@ app.controller('AppController', function(
|
||||
TooltipModalService,
|
||||
OSWindowProgressService,
|
||||
OSNotificationService,
|
||||
OSDialogService
|
||||
OSDialogService,
|
||||
OSOpenExternalService
|
||||
) {
|
||||
this.formats = SupportedFormatsModel;
|
||||
this.selection = SelectionStateModel;
|
||||
@ -205,7 +206,15 @@ app.controller('AppController', function(
|
||||
}
|
||||
|
||||
this.selection.setImage(image);
|
||||
AnalyticsService.logEvent('Select image', image);
|
||||
AnalyticsService.logEvent('Select image', _.omit(image, 'logo'));
|
||||
};
|
||||
|
||||
this.openImageUrl = () => {
|
||||
const imageUrl = this.selection.getImageUrl();
|
||||
|
||||
if (imageUrl) {
|
||||
OSOpenExternalService.open(imageUrl);
|
||||
}
|
||||
};
|
||||
|
||||
this.openImageSelector = () => {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const _ = require('lodash');
|
||||
const path = require('path');
|
||||
const fs = require('fs');
|
||||
|
||||
@ -45,21 +46,30 @@ module.exports = () => {
|
||||
height: '@'
|
||||
},
|
||||
link: (scope, element) => {
|
||||
|
||||
// This means the path to the icon should be
|
||||
// relative to *this directory*.
|
||||
// TODO: There might be a way to compute the path
|
||||
// relatively to the `index.html`.
|
||||
const imagePath = path.join(__dirname, scope.path);
|
||||
|
||||
const contents = fs.readFileSync(imagePath, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
element.html(contents);
|
||||
|
||||
element.css('width', scope.width || '40px');
|
||||
element.css('height', scope.height || '40px');
|
||||
|
||||
scope.$watch('path', (value) => {
|
||||
|
||||
// The path contains SVG contents
|
||||
if (_.first(value) === '<') {
|
||||
element.html(value);
|
||||
|
||||
} else {
|
||||
|
||||
// This means the path to the icon should be
|
||||
// relative to *this directory*.
|
||||
// TODO: There might be a way to compute the path
|
||||
// relatively to the `index.html`.
|
||||
const imagePath = path.join(__dirname, value);
|
||||
|
||||
const contents = fs.readFileSync(imagePath, {
|
||||
encoding: 'utf8'
|
||||
});
|
||||
|
||||
element.html(contents);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
|
@ -220,6 +220,48 @@ SelectionStateModel.service('SelectionStateModel', function() {
|
||||
return _.get(Store.getState().toJS(), 'selection.image.size');
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get image url
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @returns {String} image url
|
||||
*
|
||||
* @example
|
||||
* const imageUrl = SelectionStateModel.getImageUrl();
|
||||
*/
|
||||
this.getImageUrl = () => {
|
||||
return _.get(Store.getState().toJS(), 'selection.image.url');
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get image name
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @returns {String} image name
|
||||
*
|
||||
* @example
|
||||
* const imageName = SelectionStateModel.getImageName();
|
||||
*/
|
||||
this.getImageName = () => {
|
||||
return _.get(Store.getState().toJS(), 'selection.image.name');
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Get image logo
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @returns {String} image logo
|
||||
*
|
||||
* @example
|
||||
* const imageLogo = SelectionStateModel.getImageLogo();
|
||||
*/
|
||||
this.getImageLogo = () => {
|
||||
return _.get(Store.getState().toJS(), 'selection.image.logo');
|
||||
};
|
||||
|
||||
/**
|
||||
* @summary Check if there is a selected drive
|
||||
* @function
|
||||
|
@ -274,6 +274,18 @@ const storeReducer = (state, action) => {
|
||||
throw new Error(`Invalid image size: ${action.data.size}`);
|
||||
}
|
||||
|
||||
if (action.data.url && !_.isString(action.data.url)) {
|
||||
throw new Error(`Invalid image url: ${action.data.url}`);
|
||||
}
|
||||
|
||||
if (action.data.name && !_.isString(action.data.name)) {
|
||||
throw new Error(`Invalid image name: ${action.data.name}`);
|
||||
}
|
||||
|
||||
if (action.data.logo && !_.isString(action.data.logo)) {
|
||||
throw new Error(`Invalid image logo: ${action.data.logo}`);
|
||||
}
|
||||
|
||||
return state.setIn([ 'selection', 'image' ], Immutable.fromJS(action.data));
|
||||
}
|
||||
|
||||
|
@ -71,10 +71,13 @@ module.exports = function($q, SupportedFormatsModel) {
|
||||
return resolve();
|
||||
}
|
||||
|
||||
imageStream.getEstimatedFinalSize(imagePath).then((estimatedSize) => {
|
||||
imageStream.getImageMetadata(imagePath).then((metadata) => {
|
||||
return resolve({
|
||||
path: imagePath,
|
||||
size: estimatedSize
|
||||
size: metadata.estimatedSize,
|
||||
name: metadata.name,
|
||||
url: metadata.url,
|
||||
logo: metadata.logo
|
||||
});
|
||||
}).catch(reject);
|
||||
});
|
||||
|
@ -16,8 +16,6 @@
|
||||
|
||||
'use strict';
|
||||
|
||||
const electron = require('electron');
|
||||
|
||||
/**
|
||||
* @summary OsOpenExternal directive
|
||||
* @function
|
||||
@ -27,12 +25,13 @@ const electron = require('electron');
|
||||
* This directive provides an attribute to open an external
|
||||
* resource with the default operating system action.
|
||||
*
|
||||
* @param {Object} OSOpenExternalService - OSOpenExternalService
|
||||
* @returns {Object} directive
|
||||
*
|
||||
* @example
|
||||
* <button os-open-external="https://resin.io">Resin.io</button>
|
||||
*/
|
||||
module.exports = () => {
|
||||
module.exports = (OSOpenExternalService) => {
|
||||
return {
|
||||
restrict: 'A',
|
||||
scope: false,
|
||||
@ -43,7 +42,7 @@ module.exports = () => {
|
||||
element.css('cursor', 'pointer');
|
||||
|
||||
element.on('click', () => {
|
||||
electron.shell.openExternal(attributes.osOpenExternal);
|
||||
OSOpenExternalService.open(attributes.osOpenExternal);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -23,6 +23,7 @@
|
||||
const angular = require('angular');
|
||||
const MODULE_NAME = 'Etcher.OS.OpenExternal';
|
||||
const OSOpenExternal = angular.module(MODULE_NAME, []);
|
||||
OSOpenExternal.service('OSOpenExternalService', require('./services/open-external'));
|
||||
OSOpenExternal.directive('osOpenExternal', require('./directives/open-external'));
|
||||
|
||||
module.exports = MODULE_NAME;
|
||||
|
35
lib/gui/os/open-external/services/open-external.js
Normal file
35
lib/gui/os/open-external/services/open-external.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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');
|
||||
|
||||
module.exports = function() {
|
||||
|
||||
/**
|
||||
* @summary Open an external resource
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @param {String} url - url
|
||||
*
|
||||
* @example
|
||||
* OSOpenExternalService.open('https://www.google.com');
|
||||
*/
|
||||
this.open = electron.shell.openExternal;
|
||||
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
<div class="row around-xs">
|
||||
<div class="col-xs">
|
||||
<div class="box text-center" os-dropzone="app.selectImage($file)">
|
||||
<svg-icon class="center-block" path="../../../assets/image.svg"></svg-icon>
|
||||
<svg-icon class="center-block" path="{{ app.selection.getImageLogo() || '../../../assets/image.svg' }}"></svg-icon>
|
||||
<span class="icon-caption">SELECT IMAGE</span>
|
||||
<span class="badge space-top-medium">1</span>
|
||||
|
||||
@ -16,7 +16,8 @@
|
||||
</p>
|
||||
</div>
|
||||
<div ng-if="app.selection.hasImage()">
|
||||
<div ng-bind="app.selection.getImagePath() | basename | middleEllipses:25"></div>
|
||||
<div ng-click="app.openImageUrl()"
|
||||
ng-bind="app.selection.getImageName() || app.selection.getImagePath() | basename | middleEllipses:25"></div>
|
||||
|
||||
<button class="btn btn-link step-tooltip"
|
||||
ng-click="app.tooltipModal.show({
|
||||
|
257
npm-shrinkwrap.json
generated
257
npm-shrinkwrap.json
generated
@ -123,6 +123,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.0.4",
|
||||
"from": "aproba@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aproba/-/aproba-1.0.4.tgz"
|
||||
},
|
||||
"archive-type": {
|
||||
"version": "3.2.0",
|
||||
"from": "archive-type@>=3.2.0 <4.0.0",
|
||||
@ -172,6 +177,23 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"are-we-there-yet": {
|
||||
"version": "1.1.2",
|
||||
"from": "are-we-there-yet@>=1.1.2 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz",
|
||||
"dependencies": {
|
||||
"isarray": {
|
||||
"version": "1.0.0",
|
||||
"from": "isarray@~1.0.0",
|
||||
"resolved": "http://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz"
|
||||
},
|
||||
"readable-stream": {
|
||||
"version": "2.1.4",
|
||||
"from": "readable-stream@^2.0.0 || ^1.1.13",
|
||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.1.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"argparse": {
|
||||
"version": "1.0.7",
|
||||
"from": "argparse@>=1.0.7 <2.0.0",
|
||||
@ -207,6 +229,11 @@
|
||||
"from": "array-find-index@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.1.tgz"
|
||||
},
|
||||
"array-index": {
|
||||
"version": "1.0.0",
|
||||
"from": "array-index@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/array-index/-/array-index-1.0.0.tgz"
|
||||
},
|
||||
"array-map": {
|
||||
"version": "0.0.0",
|
||||
"from": "array-map@>=0.0.0 <0.1.0",
|
||||
@ -316,6 +343,11 @@
|
||||
"from": "async@>=2.0.0-rc.2 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-2.0.0.tgz"
|
||||
},
|
||||
"async-foreach": {
|
||||
"version": "0.1.3",
|
||||
"from": "async-foreach@>=0.1.3 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/async-foreach/-/async-foreach-0.1.3.tgz"
|
||||
},
|
||||
"autolinker": {
|
||||
"version": "0.15.3",
|
||||
"from": "autolinker@>=0.15.0 <0.16.0",
|
||||
@ -326,6 +358,11 @@
|
||||
"from": "aws-sign2@>=0.5.0 <0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.5.0.tgz"
|
||||
},
|
||||
"aws4": {
|
||||
"version": "1.4.1",
|
||||
"from": "aws4@>=1.2.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz"
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "0.4.1",
|
||||
"from": "balanced-match@>=0.4.1 <0.5.0",
|
||||
@ -346,6 +383,11 @@
|
||||
"from": "bl@>=0.9.0 <0.10.0",
|
||||
"resolved": "https://registry.npmjs.org/bl/-/bl-0.9.5.tgz"
|
||||
},
|
||||
"block-stream": {
|
||||
"version": "0.0.9",
|
||||
"from": "block-stream@*",
|
||||
"resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz"
|
||||
},
|
||||
"bluebird": {
|
||||
"version": "3.4.1",
|
||||
"from": "bluebird@>=3.0.5 <4.0.0",
|
||||
@ -743,6 +785,11 @@
|
||||
"from": "console-browserify@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.1.0.tgz"
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"from": "console-control-strings@>=1.1.0 <1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz"
|
||||
},
|
||||
"constants-browserify": {
|
||||
"version": "1.0.0",
|
||||
"from": "constants-browserify@>=1.0.0 <1.1.0",
|
||||
@ -819,6 +866,11 @@
|
||||
"from": "create-hmac@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.4.tgz"
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "3.0.1",
|
||||
"from": "cross-spawn@>=3.0.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-3.0.1.tgz"
|
||||
},
|
||||
"cross-spawn-async": {
|
||||
"version": "2.2.4",
|
||||
"from": "cross-spawn-async@>=2.1.1 <3.0.0",
|
||||
@ -864,6 +916,18 @@
|
||||
"from": "d@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/d/-/d-0.1.1.tgz"
|
||||
},
|
||||
"dashdash": {
|
||||
"version": "1.14.0",
|
||||
"from": "dashdash@>=1.12.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.0.tgz",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"date-now": {
|
||||
"version": "0.1.4",
|
||||
"from": "date-now@>=0.1.4 <0.2.0",
|
||||
@ -962,6 +1026,11 @@
|
||||
"from": "delayed-stream@0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-0.0.5.tgz"
|
||||
},
|
||||
"delegates": {
|
||||
"version": "1.0.0",
|
||||
"from": "delegates@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz"
|
||||
},
|
||||
"denymount": {
|
||||
"version": "2.2.0",
|
||||
"from": "denymount@>=2.1.0 <3.0.0",
|
||||
@ -1075,6 +1144,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"ecc-jsbn": {
|
||||
"version": "0.1.1",
|
||||
"from": "ecc-jsbn@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.1.tgz"
|
||||
},
|
||||
"electron-download": {
|
||||
"version": "1.4.1",
|
||||
"from": "electron-download@>=1.4.1 <2.0.0",
|
||||
@ -1280,9 +1354,9 @@
|
||||
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz"
|
||||
},
|
||||
"etcher-image-stream": {
|
||||
"version": "2.6.1",
|
||||
"from": "etcher-image-stream@2.6.1",
|
||||
"resolved": "https://registry.npmjs.org/etcher-image-stream/-/etcher-image-stream-2.6.1.tgz",
|
||||
"version": "3.0.1",
|
||||
"from": "etcher-image-stream@3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/etcher-image-stream/-/etcher-image-stream-3.0.1.tgz",
|
||||
"dependencies": {
|
||||
"yauzl": {
|
||||
"version": "2.6.0",
|
||||
@ -1370,6 +1444,11 @@
|
||||
"from": "expand-tilde@>=1.2.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-1.2.2.tgz"
|
||||
},
|
||||
"extend": {
|
||||
"version": "3.0.0",
|
||||
"from": "extend@>=3.0.0 <3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.0.tgz"
|
||||
},
|
||||
"extend-shallow": {
|
||||
"version": "2.0.1",
|
||||
"from": "extend-shallow@>=2.0.1 <3.0.0",
|
||||
@ -1412,6 +1491,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"extsprintf": {
|
||||
"version": "1.0.2",
|
||||
"from": "extsprintf@1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.0.2.tgz"
|
||||
},
|
||||
"eyes": {
|
||||
"version": "0.1.8",
|
||||
"from": "eyes@>=0.1.0 <0.2.0",
|
||||
@ -1666,11 +1750,33 @@
|
||||
"from": "fs.realpath@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz"
|
||||
},
|
||||
"fstream": {
|
||||
"version": "1.0.10",
|
||||
"from": "fstream@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.10.tgz",
|
||||
"dependencies": {
|
||||
"graceful-fs": {
|
||||
"version": "4.1.4",
|
||||
"from": "graceful-fs@^4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.0",
|
||||
"from": "function-bind@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.0.tgz"
|
||||
},
|
||||
"gauge": {
|
||||
"version": "2.6.0",
|
||||
"from": "gauge@>=2.6.0 <2.7.0",
|
||||
"resolved": "https://registry.npmjs.org/gauge/-/gauge-2.6.0.tgz"
|
||||
},
|
||||
"gaze": {
|
||||
"version": "1.1.0",
|
||||
"from": "gaze@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.0.tgz"
|
||||
},
|
||||
"generate-function": {
|
||||
"version": "2.0.0",
|
||||
"from": "generate-function@>=2.0.0 <3.0.0",
|
||||
@ -1701,6 +1807,18 @@
|
||||
"from": "get-value@>=2.0.6 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz"
|
||||
},
|
||||
"getpass": {
|
||||
"version": "0.1.6",
|
||||
"from": "getpass@>=0.1.1 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.6.tgz",
|
||||
"dependencies": {
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"git-config-path": {
|
||||
"version": "0.2.0",
|
||||
"from": "git-config-path@>=0.2.0 <0.3.0",
|
||||
@ -1767,6 +1885,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"globule": {
|
||||
"version": "1.0.0",
|
||||
"from": "globule@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/globule/-/globule-1.0.0.tgz",
|
||||
"dependencies": {
|
||||
"lodash": {
|
||||
"version": "4.9.0",
|
||||
"from": "lodash@>=4.9.0 <4.10.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.9.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gm": {
|
||||
"version": "1.22.0",
|
||||
"from": "gm@>=1.21.1 <2.0.0",
|
||||
@ -1848,6 +1978,16 @@
|
||||
"from": "has-ansi@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz"
|
||||
},
|
||||
"has-color": {
|
||||
"version": "0.1.7",
|
||||
"from": "has-color@>=0.1.7 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/has-color/-/has-color-0.1.7.tgz"
|
||||
},
|
||||
"has-unicode": {
|
||||
"version": "2.0.1",
|
||||
"from": "has-unicode@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz"
|
||||
},
|
||||
"has-values": {
|
||||
"version": "0.1.4",
|
||||
"from": "has-values@>=0.1.4 <0.2.0",
|
||||
@ -1974,6 +2114,11 @@
|
||||
"from": "imurmurhash@>=0.1.4 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz"
|
||||
},
|
||||
"in-publish": {
|
||||
"version": "2.0.0",
|
||||
"from": "in-publish@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/in-publish/-/in-publish-2.0.0.tgz"
|
||||
},
|
||||
"indent-string": {
|
||||
"version": "2.1.0",
|
||||
"from": "indent-string@>=2.1.0 <3.0.0",
|
||||
@ -2251,6 +2396,11 @@
|
||||
"from": "is-stream@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz"
|
||||
},
|
||||
"is-typedarray": {
|
||||
"version": "1.0.0",
|
||||
"from": "is-typedarray@>=1.0.0 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz"
|
||||
},
|
||||
"is-unc-path": {
|
||||
"version": "0.1.1",
|
||||
"from": "is-unc-path@>=0.1.1 <0.2.0",
|
||||
@ -2313,6 +2463,11 @@
|
||||
"from": "jju@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jju/-/jju-1.3.0.tgz"
|
||||
},
|
||||
"jodid25519": {
|
||||
"version": "1.0.2",
|
||||
"from": "jodid25519@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz"
|
||||
},
|
||||
"js-tokens": {
|
||||
"version": "1.0.3",
|
||||
"from": "js-tokens@>=1.0.1 <2.0.0",
|
||||
@ -2323,11 +2478,21 @@
|
||||
"from": "js-yaml@>=3.4.1 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.6.1.tgz"
|
||||
},
|
||||
"jsbn": {
|
||||
"version": "0.1.0",
|
||||
"from": "jsbn@>=0.1.0 <0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.0.tgz"
|
||||
},
|
||||
"json-parse-helpfulerror": {
|
||||
"version": "1.0.3",
|
||||
"from": "json-parse-helpfulerror@>=1.0.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/json-parse-helpfulerror/-/json-parse-helpfulerror-1.0.3.tgz"
|
||||
},
|
||||
"json-schema": {
|
||||
"version": "0.2.2",
|
||||
"from": "json-schema@0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.2.tgz"
|
||||
},
|
||||
"json-stable-stringify": {
|
||||
"version": "0.0.1",
|
||||
"from": "json-stable-stringify@>=0.0.0 <0.1.0",
|
||||
@ -2363,6 +2528,11 @@
|
||||
"from": "JSONStream@>=1.0.3 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.1.2.tgz"
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.3.0",
|
||||
"from": "jsprim@>=1.2.2 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.3.0.tgz"
|
||||
},
|
||||
"kind-of": {
|
||||
"version": "3.0.3",
|
||||
"from": "kind-of@>=3.0.2 <4.0.0",
|
||||
@ -2467,6 +2637,11 @@
|
||||
"from": "lodash.assigninwith@>=4.0.0 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assigninwith/-/lodash.assigninwith-4.0.7.tgz"
|
||||
},
|
||||
"lodash.clonedeep": {
|
||||
"version": "4.4.0",
|
||||
"from": "lodash.clonedeep@>=4.3.2 <5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.4.0.tgz"
|
||||
},
|
||||
"lodash.escape": {
|
||||
"version": "4.0.0",
|
||||
"from": "lodash.escape@>=4.0.0 <5.0.0",
|
||||
@ -3405,6 +3580,18 @@
|
||||
"from": "nested-error-stacks@>=1.0.1 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/nested-error-stacks/-/nested-error-stacks-1.0.2.tgz"
|
||||
},
|
||||
"node-gyp": {
|
||||
"version": "3.4.0",
|
||||
"from": "node-gyp@>=3.3.1 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.4.0.tgz",
|
||||
"dependencies": {
|
||||
"graceful-fs": {
|
||||
"version": "4.1.4",
|
||||
"from": "graceful-fs@^4.1.2",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"node-int64": {
|
||||
"version": "0.4.0",
|
||||
"from": "node-int64@>=0.4.0 <0.5.0",
|
||||
@ -3435,6 +3622,18 @@
|
||||
"from": "npm-run-path@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-1.0.0.tgz"
|
||||
},
|
||||
"npmlog": {
|
||||
"version": "3.1.2",
|
||||
"from": "npmlog@>=0.0.0 <1.0.0||>=1.0.0 <2.0.0||>=2.0.0 <3.0.0||>=3.0.0 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-3.1.2.tgz",
|
||||
"dependencies": {
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"from": "set-blocking@>=2.0.0 <2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"nugget": {
|
||||
"version": "1.6.2",
|
||||
"from": "nugget@>=1.5.1 <2.0.0",
|
||||
@ -3596,6 +3795,11 @@
|
||||
"from": "parse-json@>=2.2.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz"
|
||||
},
|
||||
"path-array": {
|
||||
"version": "1.0.1",
|
||||
"from": "path-array@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-array/-/path-array-1.0.1.tgz"
|
||||
},
|
||||
"path-browserify": {
|
||||
"version": "0.0.0",
|
||||
"from": "path-browserify@>=0.0.0 <0.1.0",
|
||||
@ -4129,6 +4333,11 @@
|
||||
"from": "samsam@1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/samsam/-/samsam-1.1.2.tgz"
|
||||
},
|
||||
"sass-graph": {
|
||||
"version": "2.1.2",
|
||||
"from": "sass-graph@>=2.1.1 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sass-graph/-/sass-graph-2.1.2.tgz"
|
||||
},
|
||||
"sax": {
|
||||
"version": "1.2.1",
|
||||
"from": "sax@>=0.6.0",
|
||||
@ -4288,6 +4497,23 @@
|
||||
"from": "sprintf-js@>=1.0.2 <1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz"
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.8.3",
|
||||
"from": "sshpk@>=1.7.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.8.3.tgz",
|
||||
"dependencies": {
|
||||
"asn1": {
|
||||
"version": "0.2.3",
|
||||
"from": "asn1@>=0.2.3 <0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.3.tgz"
|
||||
},
|
||||
"assert-plus": {
|
||||
"version": "1.0.0",
|
||||
"from": "assert-plus@>=1.0.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz"
|
||||
}
|
||||
}
|
||||
},
|
||||
"stack-trace": {
|
||||
"version": "0.0.9",
|
||||
"from": "stack-trace@>=0.0.0 <0.1.0",
|
||||
@ -4529,6 +4755,11 @@
|
||||
"from": "tail@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tail/-/tail-1.1.0.tgz"
|
||||
},
|
||||
"tar": {
|
||||
"version": "2.2.1",
|
||||
"from": "tar@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz"
|
||||
},
|
||||
"tar-stream": {
|
||||
"version": "1.5.2",
|
||||
"from": "tar-stream@>=1.5.0 <2.0.0",
|
||||
@ -4714,6 +4945,11 @@
|
||||
"from": "tv4@>=1.2.7 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/tv4/-/tv4-1.2.7.tgz"
|
||||
},
|
||||
"tweetnacl": {
|
||||
"version": "0.13.3",
|
||||
"from": "tweetnacl@>=0.13.0 <0.14.0",
|
||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.13.3.tgz"
|
||||
},
|
||||
"type-check": {
|
||||
"version": "0.3.2",
|
||||
"from": "type-check@>=0.3.2 <0.4.0",
|
||||
@ -4842,6 +5078,11 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"user-home": {
|
||||
"version": "2.0.0",
|
||||
"from": "user-home@>=2.0.0 <3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/user-home/-/user-home-2.0.0.tgz"
|
||||
},
|
||||
"username": {
|
||||
"version": "2.2.2",
|
||||
"from": "username@>=2.1.0 <3.0.0",
|
||||
@ -4884,6 +5125,11 @@
|
||||
"from": "validate-npm-package-license@>=3.0.1 <4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.1.tgz"
|
||||
},
|
||||
"verror": {
|
||||
"version": "1.3.6",
|
||||
"from": "verror@1.3.6",
|
||||
"resolved": "https://registry.npmjs.org/verror/-/verror-1.3.6.tgz"
|
||||
},
|
||||
"vm-browserify": {
|
||||
"version": "0.0.4",
|
||||
"from": "vm-browserify@>=0.0.1 <0.1.0",
|
||||
@ -4899,6 +5145,11 @@
|
||||
"from": "which@>=1.2.8 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.2.10.tgz"
|
||||
},
|
||||
"wide-align": {
|
||||
"version": "1.1.0",
|
||||
"from": "wide-align@>=1.1.0 <2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.0.tgz"
|
||||
},
|
||||
"window-size": {
|
||||
"version": "0.2.0",
|
||||
"from": "window-size@>=0.2.0 <0.3.0",
|
||||
|
@ -65,7 +65,7 @@
|
||||
"chalk": "^1.1.3",
|
||||
"drivelist": "^3.2.2",
|
||||
"electron-is-running-in-asar": "^1.0.0",
|
||||
"etcher-image-stream": "^2.6.1",
|
||||
"etcher-image-stream": "^3.0.1",
|
||||
"etcher-image-write": "^6.0.0",
|
||||
"etcher-latest-version": "^1.0.0",
|
||||
"file-tail": "^0.3.0",
|
||||
|
@ -47,6 +47,29 @@ describe('Browser: SVGIcon', function() {
|
||||
m.chai.expect(element.html()).to.equal(iconContents);
|
||||
});
|
||||
|
||||
it('should inline raw svg contents in the element', function() {
|
||||
const svg = '<svg><text>Raspbian</text></svg>';
|
||||
const element = $compile(`<svg-icon path="${svg}"></svg-icon>`)($rootScope);
|
||||
$rootScope.$digest();
|
||||
m.chai.expect(element.html()).to.equal(svg);
|
||||
});
|
||||
|
||||
it('should react to external updates', function() {
|
||||
const scope = $rootScope.$new();
|
||||
scope.name = 'Raspbian';
|
||||
scope.getSvg = () => {
|
||||
return `<svg><text>${scope.name}</text></svg>`;
|
||||
};
|
||||
|
||||
const element = $compile('<svg-icon path="{{ getSvg() }}"></svg-icon>')(scope);
|
||||
$rootScope.$digest();
|
||||
m.chai.expect(element.html()).to.equal('<svg><text>Raspbian</text></svg>');
|
||||
|
||||
scope.name = 'Resin.io';
|
||||
$rootScope.$digest();
|
||||
m.chai.expect(element.html()).to.equal('<svg><text>Resin.io</text></svg>');
|
||||
});
|
||||
|
||||
it('should default the size to 40x40 pixels', function() {
|
||||
const icon = '../../../../../lib/gui/assets/etcher.svg';
|
||||
const element = $compile(`<svg-icon path="${icon}">Resin.io</svg-icon>`)($rootScope);
|
||||
@ -55,7 +78,7 @@ describe('Browser: SVGIcon', function() {
|
||||
m.chai.expect(element.css('height')).to.equal('40px');
|
||||
});
|
||||
|
||||
it('should be able to set a custom height', function() {
|
||||
it('should be able to set a custom width', function() {
|
||||
const icon = '../../../../../lib/gui/assets/etcher.svg';
|
||||
const element = $compile(`<svg-icon path="${icon}" width="20px">Resin.io</svg-icon>`)($rootScope);
|
||||
$rootScope.$digest();
|
||||
|
@ -37,6 +37,18 @@ describe('Browser: SelectionState', function() {
|
||||
m.chai.expect(SelectionStateModel.getImageSize()).to.be.undefined;
|
||||
});
|
||||
|
||||
it('getImageUrl() should return undefined', function() {
|
||||
m.chai.expect(SelectionStateModel.getImageUrl()).to.be.undefined;
|
||||
});
|
||||
|
||||
it('getImageName() should return undefined', function() {
|
||||
m.chai.expect(SelectionStateModel.getImageName()).to.be.undefined;
|
||||
});
|
||||
|
||||
it('getImageLogo() should return undefined', function() {
|
||||
m.chai.expect(SelectionStateModel.getImageLogo()).to.be.undefined;
|
||||
});
|
||||
|
||||
it('hasDrive() should return false', function() {
|
||||
const hasDrive = SelectionStateModel.hasDrive();
|
||||
m.chai.expect(hasDrive).to.be.false;
|
||||
@ -303,7 +315,10 @@ describe('Browser: SelectionState', function() {
|
||||
beforeEach(function() {
|
||||
SelectionStateModel.setImage({
|
||||
path: 'foo.img',
|
||||
size: 999999999
|
||||
size: 999999999,
|
||||
url: 'https://www.raspbian.org',
|
||||
name: 'Raspbian',
|
||||
logo: '<svg><text fill="red">Raspbian</text></svg>'
|
||||
});
|
||||
});
|
||||
|
||||
@ -425,6 +440,33 @@ describe('Browser: SelectionState', function() {
|
||||
|
||||
});
|
||||
|
||||
describe('.getImageUrl()', function() {
|
||||
|
||||
it('should return the image url', function() {
|
||||
const imageUrl = SelectionStateModel.getImageUrl();
|
||||
m.chai.expect(imageUrl).to.equal('https://www.raspbian.org');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('.getImageName()', function() {
|
||||
|
||||
it('should return the image name', function() {
|
||||
const imageName = SelectionStateModel.getImageName();
|
||||
m.chai.expect(imageName).to.equal('Raspbian');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('.getImageLogo()', function() {
|
||||
|
||||
it('should return the image logo', function() {
|
||||
const imageLogo = SelectionStateModel.getImageLogo();
|
||||
m.chai.expect(imageLogo).to.equal('<svg><text fill="red">Raspbian</text></svg>');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe('.hasImage()', function() {
|
||||
|
||||
it('should return true', function() {
|
||||
@ -529,6 +571,36 @@ describe('Browser: SelectionState', function() {
|
||||
}).to.throw('Invalid image size: 999999999');
|
||||
});
|
||||
|
||||
it('should throw if url is defined but its not a string', function() {
|
||||
m.chai.expect(function() {
|
||||
SelectionStateModel.setImage({
|
||||
path: 'foo.img',
|
||||
size: 999999999,
|
||||
url: 1234
|
||||
});
|
||||
}).to.throw('Invalid image url: 1234');
|
||||
});
|
||||
|
||||
it('should throw if name is defined but its not a string', function() {
|
||||
m.chai.expect(function() {
|
||||
SelectionStateModel.setImage({
|
||||
path: 'foo.img',
|
||||
size: 999999999,
|
||||
name: 1234
|
||||
});
|
||||
}).to.throw('Invalid image name: 1234');
|
||||
});
|
||||
|
||||
it('should throw if logo is defined but its not a string', function() {
|
||||
m.chai.expect(function() {
|
||||
SelectionStateModel.setImage({
|
||||
path: 'foo.img',
|
||||
size: 999999999,
|
||||
logo: 1234
|
||||
});
|
||||
}).to.throw('Invalid image logo: 1234');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -17,7 +17,6 @@
|
||||
'use strict';
|
||||
|
||||
const m = require('mochainon');
|
||||
const os = require('os');
|
||||
const angular = require('angular');
|
||||
const electron = require('electron');
|
||||
require('angular-mocks');
|
||||
@ -44,26 +43,13 @@ describe('Browser: OSOpenExternal', function() {
|
||||
m.chai.expect(element.css('cursor')).to.equal('pointer');
|
||||
});
|
||||
|
||||
describe('given non linux', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
this.osPlatformStub = m.sinon.stub(os, 'platform');
|
||||
this.osPlatformStub.returns('darwin');
|
||||
});
|
||||
|
||||
afterEach(function() {
|
||||
this.osPlatformStub.restore();
|
||||
});
|
||||
|
||||
it('should call Electron shell.openExternal with the attribute value', function() {
|
||||
const shellExternalStub = m.sinon.stub(electron.shell, 'openExternal');
|
||||
const element = $compile('<span os-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();
|
||||
});
|
||||
|
||||
it('should call Electron shell.openExternal with the attribute value', function() {
|
||||
const shellExternalStub = m.sinon.stub(electron.shell, 'openExternal');
|
||||
const element = $compile('<span os-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();
|
||||
});
|
||||
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user