Convert flash results component to React

Change-type: minor
Changelog-entry: Added React component for the Flash Results button
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzoa@balena.io>
This commit is contained in:
Lorenzo Alberto Maria Ambrosi 2018-12-19 16:02:38 +01:00
parent cf722427ab
commit 64ec6d0e58
No known key found for this signature in database
GPG Key ID: 0D424CCA84D4C9D4
15 changed files with 289 additions and 117 deletions

View File

@ -298,9 +298,6 @@ rules:
# ECMAScript 6
arrow-body-style:
- error
- always
arrow-parens:
- error
- always

View File

@ -1,5 +1,5 @@
/*
* Copyright 2016 resin.io
* Copyright 2018 resin.io
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@ -17,20 +17,27 @@
'use strict'
const React = require('react')
const propTypes = require('prop-types')
const PropTypes = require('prop-types')
const styled = require('styled-components').default
const { position, right } = require('styled-system')
const Div = styled.div `
${position}
${right}
`
const FlashAnother = (props) => {
return (
<div>
<Div position='absolute' right='152px'>
<button className="button button-primary button-brick" onClick={props.onClick.bind(null, { preserveImage: true })}>
<b>Flash Another</b>
</button>
</div>
</Div>
)
}
FlashAnother.propTypes = {
onClick: propTypes.func
onClick: PropTypes.func
}
module.exports = FlashAnother

View File

@ -0,0 +1,66 @@
/*
* Copyright 2018 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 React = require('react')
const PropTypes = require('prop-types')
const _ = require('lodash')
const styled = require('styled-components').default
const { position, left, top, space } = require('styled-system')
const { Underline } = require('./../../styled-components')
const Div = styled.div `
${position}
${top}
${left}
${space}
`
/* eslint-disable no-inline-comments */
const FlashResults = (props) => {
return (
<Div position='absolute' left='153px' top='66px'>
<div className="inline-flex title">
<span className="tick tick--success space-right-medium"></span>
<h3>Flash Complete!</h3>
</div>
<Div className="results" mt='11px' mr='0' mb='0' ml='40px'>
<Underline
tooltip={props.errors()}>
{_.map(props.results.devices, (quantity, type) => {
return (quantity) ? (
<div key={type} className={`target-status-line target-status-${type}`}>
<span className="target-status-dot"></span>
<span className="target-status-quantity">{ quantity }</span>
<span className="target-status-message">{ props.message[type](quantity) }</span>
</div>
) : null
})}
</Underline>
</Div>
</Div>
)
}
FlashResults.propTypes = {
results: PropTypes.object,
message: PropTypes.object,
errors: PropTypes.func
}
module.exports = FlashResults

View File

@ -0,0 +1,34 @@
/*
* Copyright 2018 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.FlashResults
*/
const angular = require('angular')
const { react2angular } = require('react2angular')
const MODULE_NAME = 'Etcher.Components.FlashResults'
const FlashResults = angular.module(MODULE_NAME, [])
FlashResults.component(
'flashResults',
react2angular(require('./flash-results.jsx'))
)
module.exports = MODULE_NAME

View File

@ -19,6 +19,7 @@
const React = require('react')
const propTypes = require('prop-types')
const styled = require('styled-components').default
const { color } = require('styled-system')
const SvgIcon = require('../svg-icon/svg-icon.jsx')
const Div = styled.div `
@ -48,19 +49,23 @@ const Div = styled.div `
}
`
const Span = styled.span `
${color}
`
const ReducedFlashingInfos = (props) => {
return (props.shouldShow) ? (
<Div>
<span className="step-name">
<Span className="step-name">
<SvgIcon disabled contents={[ props.imageLogo ]} paths={[ '../../assets/image.svg' ]} width='20px'></SvgIcon>
<span>{ props.imageName }</span>
<span style={{ color: '#7e8085' }}>{ props.imageSize }</span>
</span>
<Span>{ props.imageName }</Span>
<Span color='#7e8085'>{ props.imageSize }</Span>
</Span>
<span className="step-name">
<Span className="step-name">
<SvgIcon disabled paths={[ '../../assets/drive.svg' ]} width='20px'></SvgIcon>
<span>{ props.driveTitle }</span>
</span>
<Span>{ props.driveTitle }</Span>
</Span>
</Div>
) : null
}

View File

@ -35,7 +35,7 @@
<main class="wrapper" ui-view></main>
<footer class="section-footer" ng-controller="StateController as state"
<footer class="section-footer-main" ng-controller="StateController as state"
ng-hide="state.currentName === 'success'">
<span os-open-external="https://www.balena.io/etcher?ref=etcher_footer"
tabindex="100">

View File

@ -43,6 +43,8 @@ module.exports = function ($state) {
this.progressMessage = messages.progress
this.results = this.flash.getFlashResults().results || {}
/**
* @summary Restart the flashing process
* @function

View File

@ -15,8 +15,12 @@
*/
.page-finish {
margin-top: -25px;
margin-top: -15px;
flex: 1;
.col-xs-5.inline-flex.items-baseline > span, .col-xs-5.inline-flex.items-baseline > div {
margin-bottom: -10px;
}
}
.page-finish .button-label {
@ -30,7 +34,8 @@
min-width: $btn-min-width;
}
.page-finish .title {
.page-finish .title,
.page-finish .title h3 {
color: $palette-theme-dark-foreground;
font-weight: bold;
}
@ -65,12 +70,8 @@
justify-content: center;
}
.page-finish .box > div {
margin-bottom: 20px;
> button {
margin-right: 20px;
}
.page-finish .box > div > button {
margin-right: 20px;
}
.page-finish webview {
@ -83,46 +84,58 @@
}
.page-finish .fallback-banner {
padding-top: 35px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 300px;
flex-direction: column;
position: absolute;
top: 125px;
left: 0;
background-color: $palette-theme-dark-background;
color: $palette-theme-dark-foreground;
font-weight: 300;
bottom: 0;
color: white;
height: 320px;
width: 100vw;
> * {
display: flex;
justify-content: center;
align-items: center;
}
.caption {
display: flex;
font-weight: normal;
font-weight: 500;
}
.caption-big {
font-size: 30px;
font-size: 28px;
font-weight: bold;
position: absolute;
top: 75px;
}
.caption-small {
font-size: 20px;
padding: 15px;
font-size: 12px;
}
.footer-right {
padding: 0;
border-bottom: 1px dashed;
.fallback-footer {
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
position: absolute;
bottom: 0;
max-height: 21px;
margin-bottom: 17px;
}
.svg-icon {
margin-left: 0.3em;
margin-right: 0.3em
margin: 0 10px;
}
.section-footer {
border-top: none;
height: 39px;
position: absolute;
right: 0;
bottom: 0;
}
}
@ -136,7 +149,15 @@
.page-finish .tick--success {
/* hack(Shou): for some reason the height is stretched */
height: 28.9px;
height: 24px;
width: 24px;
border: none;
padding: 0;
margin: 0 15px 0 0;
justify-content: center;
align-items: center;
display: flex;
font-size: 16px;
}
.title-wrap {

View File

@ -1,19 +1,11 @@
<div class="page-finish row around-xs">
<div class="col-xs">
<div class="box center">
<div class="col-xs-5 inline-flex items-baseline">
<span class="tick tick--success space-right-tiny"></span>
<div uib-tooltip="{{ finish.formattedErrors() }}" tooltip-placement="bottom" class="title-wrap">
<h3 class="title">Flash Complete!</h3>
<div class="target-status-line target-status-{{ type }}"
ng-repeat="(type, quantity) in finish.flash.getFlashResults().results.devices"
ng-if="quantity">
<span class="target-status-dot"></span>
<span class="target-status-quantity">{{ quantity }}</span>
<span class="target-status-message">{{ finish.progressMessage[type](quantity) }}</span>
</div>
</div>
</div>
<flash-results
results="finish.results"
message="finish.progressMessage"
errors="finish.formattedErrors">
</flash-results>
<flash-another on-click="finish.restart">
</flash-another>
@ -29,23 +21,23 @@
</svg-icon>
</span>
</div>
<div class="caption caption-small">
<div class="caption caption-small fallback-footer">
made with
<svg-icon paths="[ '../../assets/love.svg' ]"
width="'20px'"
height="'auto'"></svg-icon>
width="'auto'"
height="'20px'"></svg-icon>
by
<span os-open-external="https://resin.io?ref=etcher_success">
<svg-icon paths="[ '../../assets/balena.svg' ]"
width="'100px'"
height="'auto'">
width="'auto'"
height="'20px'">
</svg-icon>
</span>
</div>
<div class="section-footer">
<span class="caption footer-right"
manifest-bind="version"
os-open-external="https://github.com/resin-io/etcher/blob/master/CHANGELOG.md"></span>
<div class="section-footer">
<span class="caption footer-right"
manifest-bind="version"
os-open-external="https://github.com/resin-io/etcher/blob/master/CHANGELOG.md"></span>
</div>
</div>
</div>
</div>

View File

@ -43,6 +43,7 @@ const MainPage = angular.module(MODULE_NAME, [
require('../../components/featured-project'),
require('../../components/reduced-flashing-infos'),
require('../../components/flash-another'),
require('../../components/flash-results'),
require('../../os/open-external/open-external'),
require('../../os/dropzone/dropzone'),

View File

@ -189,14 +189,14 @@ svg-icon > img[disabled] {
.target-status-line {
display: flex;
align-items: baseline;
font-size: 11px;
font-size: 14px;
font-family: inherit;
> .target-status-dot {
width: 8px;
height: 8px;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 6px;
margin-right: 10px;
}
&.target-status-successful > .target-status-dot {
@ -213,7 +213,7 @@ svg-icon > img[disabled] {
> .target-status-message {
color: gray;
margin-left: 6px;
margin-left: 10px;
}
}

View File

@ -106,7 +106,7 @@ body,
font-family: Roboto;
}
.section-footer {
.section-footer-main {
display: flex;
align-items: center;
justify-content: center;

View File

@ -6541,13 +6541,13 @@ svg-icon > img[disabled] {
.target-status-line {
display: flex;
align-items: baseline;
font-size: 11px;
font-size: 14px;
font-family: inherit; }
.target-status-line > .target-status-dot {
width: 8px;
height: 8px;
width: 12px;
height: 12px;
border-radius: 50%;
margin-right: 6px; }
margin-right: 10px; }
.target-status-line.target-status-successful > .target-status-dot {
background-color: #5fb835; }
.target-status-line.target-status-failed > .target-status-dot {
@ -6557,7 +6557,7 @@ svg-icon > img[disabled] {
font-weight: bold; }
.target-status-line > .target-status-message {
color: gray;
margin-left: 6px; }
margin-left: 10px; }
.tooltip-inner {
white-space: pre-line; }
@ -6605,8 +6605,10 @@ svg-icon > img[disabled] {
* limitations under the License.
*/
.page-finish {
margin-top: -25px;
margin-top: -15px;
flex: 1; }
.page-finish .col-xs-5.inline-flex.items-baseline > span, .page-finish .col-xs-5.inline-flex.items-baseline > div {
margin-bottom: -10px; }
.page-finish .button-label {
margin: 0 auto 15px;
@ -6615,7 +6617,8 @@ svg-icon > img[disabled] {
.page-finish .button-primary {
min-width: 170px; }
.page-finish .title {
.page-finish .title,
.page-finish .title h3 {
color: #fff;
font-weight: bold; }
@ -6642,10 +6645,8 @@ svg-icon > img[disabled] {
align-items: center;
justify-content: center; }
.page-finish .box > div {
margin-bottom: 20px; }
.page-finish .box > div > button {
margin-right: 20px; }
.page-finish .box > div > button {
margin-right: 20px; }
.page-finish webview {
width: 800px;
@ -6656,35 +6657,45 @@ svg-icon > img[disabled] {
z-index: 9001; }
.page-finish .fallback-banner {
padding-top: 35px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
height: 300px;
flex-direction: column;
position: absolute;
top: 125px;
left: 0;
background-color: #4d5057;
color: #fff;
font-weight: 300; }
bottom: 0;
color: white;
height: 320px;
width: 100vw; }
.page-finish .fallback-banner > * {
display: flex;
justify-content: center;
align-items: center; }
.page-finish .fallback-banner .caption {
display: flex;
font-weight: normal; }
font-weight: 500; }
.page-finish .fallback-banner .caption-big {
font-size: 30px; }
font-size: 28px;
font-weight: bold;
position: absolute;
top: 75px; }
.page-finish .fallback-banner .caption-small {
font-size: 20px;
padding: 15px; }
.page-finish .fallback-banner .footer-right {
padding: 0;
border-bottom: 1px dashed; }
font-size: 12px; }
.page-finish .fallback-banner .fallback-footer {
font-size: 12px;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
position: absolute;
bottom: 0;
max-height: 21px;
margin-bottom: 17px; }
.page-finish .fallback-banner .svg-icon {
margin-left: 0.3em;
margin-right: 0.3em; }
margin: 0 10px; }
.page-finish .fallback-banner .section-footer {
border-top: none;
height: 39px; }
position: absolute;
right: 0;
bottom: 0; }
.inline-flex {
display: inline-flex; }
@ -6694,7 +6705,15 @@ svg-icon > img[disabled] {
.page-finish .tick--success {
/* hack(Shou): for some reason the height is stretched */
height: 28.9px; }
height: 24px;
width: 24px;
border: none;
padding: 0;
margin: 0 15px 0 0;
justify-content: center;
align-items: center;
display: flex;
font-size: 16px; }
.title-wrap {
margin-left: 5px; }
@ -9915,7 +9934,7 @@ body,
.popover {
font-family: Roboto; }
.section-footer {
.section-footer-main {
display: flex;
align-items: center;
justify-content: center;
@ -9925,20 +9944,20 @@ body,
padding-top: 15px;
border-top: 2px solid #64686a;
text-align: center; }
.section-footer .col-xs {
.section-footer-main .col-xs {
padding: 0; }
.section-footer .svg-icon {
.section-footer-main .svg-icon {
margin: 0 13px; }
.section-footer .caption[os-open-external] {
.section-footer-main .caption[os-open-external] {
border-bottom: 1px dashed;
padding-bottom: 2px; }
.section-footer .caption[os-open-external]:hover {
.section-footer-main .caption[os-open-external]:hover {
color: #85898c; }
.section-footer .footer-right {
.section-footer-main .footer-right {
font-size: 10px;
position: absolute;
right: 0; }
.section-footer > span[os-open-external] {
.section-footer-main > span[os-open-external] {
display: flex; }
.section-loader webview {

34
npm-shrinkwrap.json generated
View File

@ -2,9 +2,29 @@
"name": "balena-etcher",
"version": "1.4.8",
"dependencies": {
"@babel/runtime": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.2.0.tgz",
"dependencies": {
"regenerator-runtime": {
"version": "0.12.1",
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz"
}
}
},
"@balena/grid-styled": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/@balena/grid-styled/-/grid-styled-3.1.1.tgz"
"resolved": "https://registry.npmjs.org/@balena/grid-styled/-/grid-styled-3.1.1.tgz",
"dependencies": {
"prop-types": {
"version": "15.6.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz"
},
"styled-system": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/styled-system/-/styled-system-1.1.7.tgz"
}
}
},
"@fortawesome/fontawesome-free-webfonts": {
"version": "1.0.9",
@ -6727,6 +6747,14 @@
"version": "4.41.1",
"resolved": "https://registry.npmjs.org/rendition/-/rendition-4.41.1.tgz",
"dependencies": {
"prop-types": {
"version": "15.6.2",
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.6.2.tgz"
},
"styled-system": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/styled-system/-/styled-system-1.1.7.tgz"
},
"uuid": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz"
@ -7645,8 +7673,8 @@
}
},
"styled-system": {
"version": "1.1.7",
"resolved": "https://registry.npmjs.org/styled-system/-/styled-system-1.1.7.tgz",
"version": "3.1.11",
"resolved": "https://registry.npmjs.org/styled-system/-/styled-system-3.1.11.tgz",
"dependencies": {
"prop-types": {
"version": "15.6.2",

View File

@ -92,7 +92,7 @@
"semver": "5.1.1",
"speedometer": "1.0.0",
"styled-components": "3.2.3",
"styled-system": "1.1.7",
"styled-system": "3.1.11",
"sudo-prompt": "8.2.3",
"udif": "0.13.0",
"unbzip2-stream": "github:resin-io-modules/unbzip2-stream#core-streams",