diff --git a/lib/gui/app.js b/lib/gui/app.js index 57d3f1f6..7b4ae720 100644 --- a/lib/gui/app.js +++ b/lib/gui/app.js @@ -55,7 +55,7 @@ const app = angular.module('Etcher', [ require('./modules/drive-scanner'), // Components - require('./components/svg-icon/svg-icon'), + require('./components/svg-icon'), require('./components/warning-modal/warning-modal'), require('./components/safe-webview'), diff --git a/lib/gui/components/svg-icon.js b/lib/gui/components/svg-icon.js new file mode 100644 index 00000000..24f33b0f --- /dev/null +++ b/lib/gui/components/svg-icon.js @@ -0,0 +1,113 @@ +/* + * 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.Components.SVGIcon + */ + +const angular = require('angular'); +const react = require('react'); +const propTypes = require('prop-types'); +const react2angular = require('react2angular').react2angular; +const path = require('path'); +const fs = require('fs'); + +const MODULE_NAME = 'Etcher.Components.SVGIcon'; +const angularSVGIcon = angular.module(MODULE_NAME, []); + +const DEFAULT_SIZE = '40px'; + +/** + * @summary SVG element that takes both filepaths and file contents + * @type {Object} + * @public + */ +class SVGIcon extends react.Component { + + /** + * @summary Render the SVG + * @returns {react.Element} + */ + render() { + + // 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, this.props.path); + + const contents = fs.readFileSync(imagePath, { + encoding: 'utf8' + }); + + const width = this.props.width || DEFAULT_SIZE; + const height = this.props.height || DEFAULT_SIZE; + + return react.createElement('div', { + className: 'svg-icon', + height, + width, + style: { + width, + height + }, + disabled: this.props.disabled, + dangerouslySetInnerHTML: { + __html: contents + } + }); + } + + /** + * @summary Cause a re-render due to changed element properties + * @param {Object} nextProps - the new properties + */ + componentWillReceiveProps(nextProps) { + + // This will update the element if the properties change + this.setState(nextProps); + } + +} + +SVGIcon.propTypes = { + + /** + * @summary SVG contents or path to the resource + */ + path: propTypes.string.isRequired, + + /** + * @summary SVG image width unit + */ + width: propTypes.string, + + /** + * @summary SVG image height unit + */ + height: propTypes.string, + + /** + * @summary Should the element visually appear grayed out and disabled? + */ + disabled: propTypes.bool + +}; + +angularSVGIcon.component('svgIcon', react2angular(SVGIcon)); +module.exports = MODULE_NAME; diff --git a/lib/gui/components/svg-icon/directives/svg-icon.js b/lib/gui/components/svg-icon/directives/svg-icon.js deleted file mode 100644 index 892d9156..00000000 --- a/lib/gui/components/svg-icon/directives/svg-icon.js +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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 _ = require('lodash'); -const path = require('path'); -const fs = require('fs'); - -/** - * @summary SVGIcon directive - * @function - * @public - * - * @description - * This directive provides an easy way to load SVG icons - * by embedding the SVG contents inside the element, making - * it possible to style icons with CSS. - * - * @returns {Object} - * - * @example - * - */ -module.exports = () => { - return { - templateUrl: './components/svg-icon/templates/svg-icon.tpl.html', - replace: true, - restrict: 'E', - scope: { - path: '@', - width: '@', - height: '@' - }, - link: (scope, element) => { - 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); - } - }); - } - }; -}; diff --git a/lib/gui/components/svg-icon/styles/_svg-icon.scss b/lib/gui/components/svg-icon/styles/_svg-icon.scss new file mode 100644 index 00000000..1829c745 --- /dev/null +++ b/lib/gui/components/svg-icon/styles/_svg-icon.scss @@ -0,0 +1,9 @@ + +svg { + width: 100%; + height: 100%; +} + +svg-icon { + display: inline-block; +} diff --git a/lib/gui/components/svg-icon/svg-icon.js b/lib/gui/components/svg-icon/svg-icon.js deleted file mode 100644 index fd0bc6c6..00000000 --- a/lib/gui/components/svg-icon/svg-icon.js +++ /dev/null @@ -1,28 +0,0 @@ -/* - * 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.Components.SVGIcon - */ - -const angular = require('angular'); -const MODULE_NAME = 'Etcher.Components.SVGIcon'; -const SVGIcon = angular.module(MODULE_NAME, []); -SVGIcon.directive('svgIcon', require('./directives/svg-icon')); - -module.exports = MODULE_NAME; diff --git a/lib/gui/components/svg-icon/templates/svg-icon.tpl.html b/lib/gui/components/svg-icon/templates/svg-icon.tpl.html deleted file mode 100644 index 9d8dbeeb..00000000 --- a/lib/gui/components/svg-icon/templates/svg-icon.tpl.html +++ /dev/null @@ -1 +0,0 @@ -
diff --git a/lib/gui/css/main.css b/lib/gui/css/main.css index 5a08e03c..8a57eb2a 100644 --- a/lib/gui/css/main.css +++ b/lib/gui/css/main.css @@ -6413,6 +6413,13 @@ body { .modal-drive-selector-modal .word-keep { word-break: keep-all; } +svg { + width: 100%; + height: 100%; } + +svg-icon { + display: inline-block; } + /* * Copyright 2016 resin.io * @@ -6474,7 +6481,7 @@ body { .page-main { margin-top: 75px; } -.svg-icon[disabled] path { +svg-icon > div[disabled] path { fill: #787c7f; } .page-main .step-selection-text { @@ -6693,6 +6700,8 @@ body { position: absolute; right: 0; top: 50%; } + .section-footer > span[os-open-external] { + display: flex; } .section-loader webview { flex: 0 1; diff --git a/lib/gui/index.html b/lib/gui/index.html index f7d1e9c6..cd323434 100644 --- a/lib/gui/index.html +++ b/lib/gui/index.html @@ -32,19 +32,21 @@