Add retry button to the errors modal in success screen

Change-type: patch
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
This commit is contained in:
Lorenzo Alberto Maria Ambrosi 2020-08-24 14:14:39 +02:00
parent 3c77800b1d
commit 6584cef774
3 changed files with 54 additions and 21 deletions

View File

@ -41,7 +41,8 @@ function restart(goToMain: () => void) {
function FinishPage({ goToMain }: { goToMain: () => void }) { function FinishPage({ goToMain }: { goToMain: () => void }) {
const [webviewShowing, setWebviewShowing] = React.useState(false); const [webviewShowing, setWebviewShowing] = React.useState(false);
let errors = flashState.getFlashResults().results?.errors; const flashResults = flashState.getFlashResults();
let errors = flashResults?.results?.errors;
if (errors === undefined) { if (errors === undefined) {
errors = (store.getState().toJS().failedDevicePaths || []).map( errors = (store.getState().toJS().failedDevicePaths || []).map(
([, error]: [string, FlashError]) => ({ ([, error]: [string, FlashError]) => ({
@ -67,7 +68,7 @@ function FinishPage({ goToMain }: { goToMain: () => void }) {
averageFlashingSpeed: averageSpeed, averageFlashingSpeed: averageSpeed,
devices: { failed, successful: 0 }, devices: { failed, successful: 0 },
}, },
} = flashState.getFlashResults(); } = flashResults;
return ( return (
<Flex height="100%" justifyContent="space-between"> <Flex height="100%" justifyContent="space-between">
<Flex <Flex
@ -89,6 +90,7 @@ function FinishPage({ goToMain }: { goToMain: () => void }) {
skip={skip} skip={skip}
errors={errors} errors={errors}
mb="32px" mb="32px"
goToMain={goToMain}
/> />
<FlashAnother <FlashAnother

View File

@ -16,6 +16,7 @@
import CircleSvg from '@fortawesome/fontawesome-free/svgs/solid/circle.svg'; import CircleSvg from '@fortawesome/fontawesome-free/svgs/solid/circle.svg';
import CheckCircleSvg from '@fortawesome/fontawesome-free/svgs/solid/check-circle.svg'; import CheckCircleSvg from '@fortawesome/fontawesome-free/svgs/solid/check-circle.svg';
import TimesCircleSvg from '@fortawesome/fontawesome-free/svgs/solid/times-circle.svg';
import * as _ from 'lodash'; import * as _ from 'lodash';
import outdent from 'outdent'; import outdent from 'outdent';
import * as React from 'react'; import * as React from 'react';
@ -26,6 +27,8 @@ import { progress } from '../../../../shared/messages';
import { bytesToMegabytes } from '../../../../shared/units'; import { bytesToMegabytes } from '../../../../shared/units';
import FlashSvg from '../../../assets/flash.svg'; import FlashSvg from '../../../assets/flash.svg';
import { resetState } from '../../models/flash-state';
import * as selection from '../../models/selection-state';
import { middleEllipsis } from '../../utils/middle-ellipsis'; import { middleEllipsis } from '../../utils/middle-ellipsis';
import { Modal } from '../../styled-components'; import { Modal } from '../../styled-components';
@ -57,6 +60,28 @@ const ErrorsTable = styled(({ refFn, ...props }) => {
} }
`; `;
const DoneIcon = (props: { allFailed: boolean; someFailed: boolean }) => {
const { allFailed, someFailed } = props;
const someOrAllFailed = allFailed || someFailed;
const svgProps = {
width: '24px',
fill: someOrAllFailed ? '#c6c8c9' : '#1ac135',
style: {
width: '28px',
height: '28px',
marginTop: '-25px',
marginLeft: '13px',
zIndex: 1,
color: someOrAllFailed ? '#c6c8c9' : '#1ac135',
},
};
return allFailed ? (
<TimesCircleSvg {...svgProps} />
) : (
<CheckCircleSvg {...svgProps} />
);
};
export interface FlashError extends Error { export interface FlashError extends Error {
description: string; description: string;
device: string; device: string;
@ -88,12 +113,14 @@ const columns: Array<TableColumn<FlashError>> = [
]; ];
export function FlashResults({ export function FlashResults({
goToMain,
image = '', image = '',
errors, errors,
results, results,
skip, skip,
...props ...props
}: { }: {
goToMain: () => void;
image?: string; image?: string;
errors: FlashError[]; errors: FlashError[];
skip: boolean; skip: boolean;
@ -108,7 +135,7 @@ export function FlashResults({
}; };
} & FlexProps) { } & FlexProps) {
const [showErrorsInfo, setShowErrorsInfo] = React.useState(false); const [showErrorsInfo, setShowErrorsInfo] = React.useState(false);
const allDevicesFailed = results.devices.successful === 0; const allFailed = results.devices.successful === 0;
const effectiveSpeed = _.round( const effectiveSpeed = _.round(
bytesToMegabytes( bytesToMegabytes(
results.sourceMetadata.size / results.sourceMetadata.size /
@ -127,17 +154,9 @@ export function FlashResults({
flexDirection="column" flexDirection="column"
> >
<FlashSvg width="40px" height="40px" className="disabled" /> <FlashSvg width="40px" height="40px" className="disabled" />
<CheckCircleSvg <DoneIcon
width="24px" allFailed={allFailed}
fill={allDevicesFailed ? '#c6c8c9' : '#1ac135'} someFailed={results.devices.failed !== 0}
style={{
width: '28px',
height: '28px',
marginTop: '-25px',
marginLeft: '13px',
zIndex: 1,
color: allDevicesFailed ? '#c6c8c9' : '#1ac135',
}}
/> />
<Txt>{middleEllipsis(image, 16)}</Txt> <Txt>{middleEllipsis(image, 16)}</Txt>
</Flex> </Flex>
@ -173,7 +192,7 @@ export function FlashResults({
</Flex> </Flex>
) : null; ) : null;
})} })}
{!allDevicesFailed && ( {!allFailed && (
<Txt <Txt
fontSize="10px" fontSize="10px"
style={{ style={{
@ -199,7 +218,19 @@ export function FlashResults({
</Txt> </Txt>
</Flex> </Flex>
} }
done={() => setShowErrorsInfo(false)} action="Retry failed targets"
cancel={() => setShowErrorsInfo(false)}
done={() => {
setShowErrorsInfo(false);
resetState();
selection
.getSelectedDrives()
.filter((drive) =>
errors.every((error) => error.device !== drive.device),
)
.forEach((drive) => selection.deselectDrive(drive.device));
goToMain();
}}
> >
<ErrorsTable columns={columns} data={errors} /> <ErrorsTable columns={columns} data={errors} />
</Modal> </Modal>

View File

@ -334,12 +334,12 @@ function storeReducer(
action.data.results.averageFlashingSpeed = state.get( action.data.results.averageFlashingSpeed = state.get(
'lastAverageFlashingSpeed', 'lastAverageFlashingSpeed',
); );
}
if (action.data.results.skip) { if (action.data.skip) {
return state return state
.set('isFlashing', false) .set('isFlashing', false)
.set('flashResults', Immutable.fromJS(action.data)); .set('flashResults', Immutable.fromJS(action.data));
}
} }
return state return state