mirror of
https://github.com/balena-io/etcher.git
synced 2025-07-25 12:16:37 +00:00
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:
parent
3c77800b1d
commit
6584cef774
@ -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
|
||||||
|
@ -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>
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user