mirror of
https://github.com/balena-io/etcher.git
synced 2025-04-24 15:27:17 +00:00
feat(GUI): display succeeded and failed devices on finish screen (#2206)
We display the quantity of succeeded and failed devices using status dots on the finish screen. Change-Type: patch Changelog-Entry: Display succeeded and failed device quantities on the finish screen.
This commit is contained in:
parent
a044d2fe86
commit
32bc615e78
@ -126,16 +126,25 @@ exports.performWrite = (image, drives, onProgress) => {
|
||||
console.log(message)
|
||||
})
|
||||
|
||||
const flashResults = {
|
||||
devices: {
|
||||
succeeded: 0,
|
||||
failed: 0
|
||||
}
|
||||
}
|
||||
ipc.server.on('fail', (error) => {
|
||||
console.log('Fail:', error)
|
||||
})
|
||||
|
||||
const flashResults = {}
|
||||
ipc.server.on('done', (results) => {
|
||||
_.merge(flashResults, results)
|
||||
})
|
||||
|
||||
ipc.server.on('state', onProgress)
|
||||
ipc.server.on('state', (progress) => {
|
||||
flashResults.devices.succeeded = progress.succeeded
|
||||
flashResults.devices.failed = progress.failed
|
||||
onProgress(progress)
|
||||
})
|
||||
|
||||
ipc.server.on('ready', (data, socket) => {
|
||||
ipc.server.emit(socket, 'write', {
|
||||
|
@ -16,10 +16,12 @@
|
||||
|
||||
'use strict'
|
||||
|
||||
const _ = require('lodash')
|
||||
const settings = require('../../../models/settings')
|
||||
const flashState = require('../../../../../shared/models/flash-state')
|
||||
const selectionState = require('../../../../../shared/models/selection-state')
|
||||
const analytics = require('../../../modules/analytics')
|
||||
const messages = require('../../../../../shared/messages')
|
||||
|
||||
module.exports = function ($state) {
|
||||
/**
|
||||
@ -30,11 +32,13 @@ module.exports = function ($state) {
|
||||
this.settings = settings
|
||||
|
||||
/**
|
||||
* @summary Source checksum
|
||||
* @type {String}
|
||||
* @summary Flash state
|
||||
* @type {Object}
|
||||
* @public
|
||||
*/
|
||||
this.checksum = flashState.getLastFlashSourceChecksum()
|
||||
this.flash = flashState
|
||||
|
||||
this.progressMessage = messages.progress
|
||||
|
||||
/**
|
||||
* @summary Restart the flashing process
|
||||
@ -55,4 +59,22 @@ module.exports = function ($state) {
|
||||
analytics.logEvent('Restart', options)
|
||||
$state.go('main')
|
||||
}
|
||||
|
||||
/**
|
||||
* @summary Format the result errors with newlines
|
||||
* @function
|
||||
* @public
|
||||
*
|
||||
* @returns {String} formatted errors
|
||||
*
|
||||
* @example
|
||||
* const errors = FinishController.formattedErrors()
|
||||
* console.log(errors)
|
||||
*/
|
||||
this.formattedErrors = () => {
|
||||
const errors = _.map(_.get(flashState.getFlashResults(), [ 'results', 'errors' ]), (error) => {
|
||||
return `${error.device}: ${error.message || error.code}`
|
||||
})
|
||||
return errors.join('\n')
|
||||
}
|
||||
}
|
||||
|
@ -124,3 +124,24 @@
|
||||
height: 39px;
|
||||
}
|
||||
}
|
||||
|
||||
.inline-flex {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.items-baseline {
|
||||
align-items: baseline;
|
||||
}
|
||||
|
||||
.page-finish .tick--success {
|
||||
/* hack(Shou): for some reason the height is stretched */
|
||||
height: 28.9px;
|
||||
}
|
||||
|
||||
.title-wrap {
|
||||
margin-left: 5px;
|
||||
|
||||
> .title {
|
||||
margin-bottom: 3px;
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,17 @@
|
||||
<div class="page-finish row around-xs">
|
||||
<div class="col-xs">
|
||||
<div class="box center">
|
||||
<div class="col-xs-5">
|
||||
<h3 class="title"><span class="tick tick--success space-right-tiny"></span> Flash Complete!</h3>
|
||||
<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().devices">
|
||||
<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>
|
||||
|
||||
<div class="col-xs-4">
|
||||
|
@ -130,15 +130,15 @@ svg-icon > img[disabled] {
|
||||
|
||||
.target-status-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
align-items: baseline;
|
||||
font-size: 11px;
|
||||
font-family: inherit;
|
||||
|
||||
> .target-status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px;
|
||||
margin-right: 6px;
|
||||
}
|
||||
|
||||
&.target-status-succeeded > .target-status-dot {
|
||||
@ -151,11 +151,11 @@ svg-icon > img[disabled] {
|
||||
> .target-status-quantity {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
min-width: 32px;
|
||||
}
|
||||
|
||||
> .target-status-message {
|
||||
color: gray;
|
||||
margin-left: 6px;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6595,24 +6595,24 @@ svg-icon > img[disabled] {
|
||||
|
||||
.target-status-line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
font-size: 10px;
|
||||
align-items: baseline;
|
||||
font-size: 11px;
|
||||
font-family: inherit; }
|
||||
.target-status-line > .target-status-dot {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
margin-right: 5px; }
|
||||
margin-right: 6px; }
|
||||
.target-status-line.target-status-succeeded > .target-status-dot {
|
||||
background-color: #5fb835; }
|
||||
.target-status-line.target-status-failed > .target-status-dot {
|
||||
background-color: #d9534f; }
|
||||
.target-status-line > .target-status-quantity {
|
||||
color: white;
|
||||
font-weight: bold;
|
||||
min-width: 32px; }
|
||||
font-weight: bold; }
|
||||
.target-status-line > .target-status-message {
|
||||
color: gray; }
|
||||
color: gray;
|
||||
margin-left: 6px; }
|
||||
|
||||
.tooltip-inner {
|
||||
white-space: pre-line; }
|
||||
@ -6740,6 +6740,21 @@ svg-icon > img[disabled] {
|
||||
border-top: none;
|
||||
height: 39px; }
|
||||
|
||||
.inline-flex {
|
||||
display: inline-flex; }
|
||||
|
||||
.items-baseline {
|
||||
align-items: baseline; }
|
||||
|
||||
.page-finish .tick--success {
|
||||
/* hack(Shou): for some reason the height is stretched */
|
||||
height: 28.9px; }
|
||||
|
||||
.title-wrap {
|
||||
margin-left: 5px; }
|
||||
.title-wrap > .title {
|
||||
margin-bottom: 3px; }
|
||||
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("../../../node_modules/roboto-fontface/fonts/roboto/Roboto-Thin.woff");
|
||||
|
@ -636,7 +636,13 @@ class ImageWriter extends EventEmitter {
|
||||
this.emit('finish', {
|
||||
bytesRead: this.bytesRead,
|
||||
bytesWritten: this.bytesWritten,
|
||||
checksum: this.checksum
|
||||
checksum: this.checksum,
|
||||
errors: Array.from(this.destinations).filter(([ device, dest ]) => {
|
||||
return dest.error
|
||||
}).map(([ device, dest ]) => {
|
||||
dest.error.device = device
|
||||
return dest.error
|
||||
})
|
||||
})
|
||||
})
|
||||
}
|
||||
|
@ -345,7 +345,8 @@ exports.toJSON = (error) => {
|
||||
syscall: errorObject.syscall,
|
||||
errno: errorObject.errno,
|
||||
stdout: errorObject.stdout,
|
||||
stderr: errorObject.stderr
|
||||
stderr: errorObject.stderr,
|
||||
device: errorObject.device
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,13 +34,13 @@ module.exports = {
|
||||
|
||||
succeeded: (quantity) => {
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
const plural = quantity > 1 ? 's' : ''
|
||||
const plural = quantity === 1 ? '' : 's'
|
||||
return `Succeeded device${plural}`
|
||||
},
|
||||
|
||||
failed: (quantity) => {
|
||||
// eslint-disable-next-line no-magic-numbers
|
||||
const plural = quantity > 1 ? 's' : ''
|
||||
const plural = quantity === 1 ? '' : 's'
|
||||
return `Failed device${plural}`
|
||||
}
|
||||
},
|
||||
|
@ -35,7 +35,8 @@ angularValidate.validate(
|
||||
// External
|
||||
'hide-if-state',
|
||||
'show-if-state',
|
||||
'uib-tooltip'
|
||||
'uib-tooltip',
|
||||
'tooltip-placement'
|
||||
|
||||
],
|
||||
angular: true,
|
||||
|
@ -651,7 +651,8 @@ describe('Shared: Errors', function () {
|
||||
stdout: undefined,
|
||||
syscall: undefined,
|
||||
name: 'Error',
|
||||
errno: undefined
|
||||
errno: undefined,
|
||||
device: undefined
|
||||
})
|
||||
})
|
||||
|
||||
@ -669,7 +670,8 @@ describe('Shared: Errors', function () {
|
||||
stdout: undefined,
|
||||
syscall: undefined,
|
||||
name: 'Error',
|
||||
errno: undefined
|
||||
errno: undefined,
|
||||
device: undefined
|
||||
})
|
||||
})
|
||||
|
||||
@ -687,7 +689,8 @@ describe('Shared: Errors', function () {
|
||||
stdout: undefined,
|
||||
syscall: undefined,
|
||||
name: 'Error',
|
||||
errno: undefined
|
||||
errno: undefined,
|
||||
device: undefined
|
||||
})
|
||||
})
|
||||
|
||||
@ -706,7 +709,8 @@ describe('Shared: Errors', function () {
|
||||
stdout: undefined,
|
||||
syscall: undefined,
|
||||
name: 'Error',
|
||||
errno: undefined
|
||||
errno: undefined,
|
||||
device: undefined
|
||||
})
|
||||
})
|
||||
|
||||
@ -724,7 +728,8 @@ describe('Shared: Errors', function () {
|
||||
stdout: undefined,
|
||||
syscall: undefined,
|
||||
name: 'Error',
|
||||
errno: undefined
|
||||
errno: undefined,
|
||||
device: undefined
|
||||
})
|
||||
})
|
||||
|
||||
@ -741,7 +746,8 @@ describe('Shared: Errors', function () {
|
||||
stdout: undefined,
|
||||
syscall: undefined,
|
||||
name: 'Error',
|
||||
errno: undefined
|
||||
errno: undefined,
|
||||
device: undefined
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user