Make Flash component a class & rename it FlashStep

Change-type: patch
This commit is contained in:
Alexis Svinartchouk 2020-05-14 14:35:08 +02:00
parent f9cbff1eec
commit a3a9edd41a
2 changed files with 149 additions and 127 deletions

View File

@ -164,167 +164,189 @@ const formatSeconds = (totalSeconds: number) => {
return `${minutes}m${seconds}s`; return `${minutes}m${seconds}s`;
}; };
interface FlashProps { interface FlashStepProps {
shouldFlashStepBeDisabled: boolean; shouldFlashStepBeDisabled: boolean;
goToSuccess: () => void; goToSuccess: () => void;
source: SourceOptions; source: SourceOptions;
} }
export const Flash = ({ interface FlashStepState {
shouldFlashStepBeDisabled, warningMessages: string[];
goToSuccess, errorMessage: string;
source, showDriveSelectorModal: boolean;
}: FlashProps) => { }
const state: any = flashState.getFlashState();
const isFlashing = flashState.isFlashing();
const flashErrorCode = flashState.getLastFlashErrorCode();
const [warningMessages, setWarningMessages] = React.useState<string[]>([]); export class FlashStep extends React.Component<FlashStepProps, FlashStepState> {
const [errorMessage, setErrorMessage] = React.useState(''); constructor(props: FlashStepProps) {
const [showDriveSelectorModal, setShowDriveSelectorModal] = React.useState( super(props);
false, this.state = {
); warningMessages: [],
errorMessage: '',
const handleWarningResponse = async (shouldContinue: boolean) => { showDriveSelectorModal: false,
setWarningMessages([]); };
}
private async handleWarningResponse(shouldContinue: boolean) {
this.setState({ warningMessages: [] });
if (!shouldContinue) { if (!shouldContinue) {
setShowDriveSelectorModal(true); this.setState({ showDriveSelectorModal: true });
return; return;
} }
this.setState({
errorMessage: await flashImageToDrive(
this.props.goToSuccess,
this.props.source,
),
});
}
setErrorMessage(await flashImageToDrive(goToSuccess, source)); private handleFlashErrorResponse(shouldRetry: boolean) {
}; this.setState({ errorMessage: '' });
const handleFlashErrorResponse = (shouldRetry: boolean) => {
setErrorMessage('');
flashState.resetState(); flashState.resetState();
if (shouldRetry) { if (shouldRetry) {
analytics.logEvent('Restart after failure'); analytics.logEvent('Restart after failure');
} else { } else {
selection.clear(); selection.clear();
} }
}; }
const tryFlash = async () => { private async tryFlash() {
const devices = selection.getSelectedDevices(); const devices = selection.getSelectedDevices();
const image = selection.getImage(); const image = selection.getImage();
const drives = _.filter(availableDrives.getDrives(), (drive: any) => { const drives = _.filter(
return _.includes(devices, drive.device); availableDrives.getDrives(),
}); (drive: { device: string }) => {
return _.includes(devices, drive.device);
},
);
if (drives.length === 0 || flashState.isFlashing()) { if (drives.length === 0 || flashState.isFlashing()) {
return; return;
} }
const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus( const hasDangerStatus = constraints.hasListDriveImageCompatibilityStatus(
drives, drives,
image, image,
); );
if (hasDangerStatus) { if (hasDangerStatus) {
setWarningMessages(getWarningMessages(drives, image)); this.setState({ warningMessages: getWarningMessages(drives, image) });
return; return;
} }
this.setState({
errorMessage: await flashImageToDrive(
this.props.goToSuccess,
this.props.source,
),
});
}
setErrorMessage(await flashImageToDrive(goToSuccess, source)); public render() {
}; const state = flashState.getFlashState();
const isFlashing = flashState.isFlashing();
return ( const flashErrorCode = flashState.getLastFlashErrorCode();
<> return (
<div className="box text-center"> <>
<div className="center-block"> <div className="box text-center">
<SVGIcon <div className="center-block">
paths={['../../assets/flash.svg']} <SVGIcon
disabled={shouldFlashStepBeDisabled} paths={['../../assets/flash.svg']}
/> disabled={this.props.shouldFlashStepBeDisabled}
</div>
<div className="space-vertical-large">
<StepSelection>
<ProgressButton
type={state.type}
active={isFlashing}
percentage={state.percentage}
label={getProgressButtonLabel()}
disabled={Boolean(flashErrorCode) || shouldFlashStepBeDisabled}
callback={tryFlash}
/> />
</StepSelection> </div>
{isFlashing && ( <div className="space-vertical-large">
<button <StepSelection>
className="button button-link button-abort-write" <ProgressButton
onClick={imageWriter.cancel} type={state.type}
> active={isFlashing}
<span className="glyphicon glyphicon-remove-sign"></span> percentage={state.percentage}
</button> label={getProgressButtonLabel()}
)} disabled={
{!_.isNil(state.speed) && state.percentage !== COMPLETED_PERCENTAGE && ( Boolean(flashErrorCode) ||
<p className="step-footer step-footer-split"> this.props.shouldFlashStepBeDisabled
{Boolean(state.speed) && ( }
<span>{`${state.speed.toFixed(SPEED_PRECISION)} MB/s`}</span> callback={() => {
)} this.tryFlash();
{!_.isNil(state.eta) && ( }}
<span>{`ETA: ${formatSeconds(state.eta)}`}</span> />
)} </StepSelection>
</p>
)}
{Boolean(state.failed) && ( {isFlashing && (
<div className="target-status-wrap"> <button
<div className="target-status-line target-status-failed"> className="button button-link button-abort-write"
<span className="target-status-dot"></span> onClick={imageWriter.cancel}
<span className="target-status-quantity">{state.failed}</span> >
<span className="target-status-message"> <span className="glyphicon glyphicon-remove-sign"></span>
{messages.progress.failed(state.failed)}{' '} </button>
</span> )}
{!_.isNil(state.speed) &&
state.percentage !== COMPLETED_PERCENTAGE && (
<p className="step-footer step-footer-split">
{Boolean(state.speed) && (
<span>{`${state.speed.toFixed(
SPEED_PRECISION,
)} MB/s`}</span>
)}
{!_.isNil(state.eta) && (
<span>{`ETA: ${formatSeconds(state.eta)}`}</span>
)}
</p>
)}
{Boolean(state.failed) && (
<div className="target-status-wrap">
<div className="target-status-line target-status-failed">
<span className="target-status-dot"></span>
<span className="target-status-quantity">{state.failed}</span>
<span className="target-status-message">
{messages.progress.failed(state.failed)}{' '}
</span>
</div>
</div> </div>
</div> )}
)} </div>
</div> </div>
</div>
{warningMessages && warningMessages.length > 0 && ( {this.state.warningMessages.length > 0 && (
<Modal <Modal
width={400} width={400}
titleElement={'Attention'} titleElement={'Attention'}
cancel={() => handleWarningResponse(false)} cancel={() => this.handleWarningResponse(false)}
done={() => handleWarningResponse(true)} done={() => this.handleWarningResponse(true)}
cancelButtonProps={{ cancelButtonProps={{
children: 'Change', children: 'Change',
}} }}
action={'Continue'} action={'Continue'}
primaryButtonProps={{ primary: false, warning: true }} primaryButtonProps={{ primary: false, warning: true }}
> >
{_.map(warningMessages, (message, key) => ( {_.map(this.state.warningMessages, (message, key) => (
<Txt key={key} whitespace="pre-line" mt={2}> <Txt key={key} whitespace="pre-line" mt={2}>
{message} {message}
</Txt> </Txt>
))}
</Modal>
)}
{errorMessage && (
<Modal
width={400}
titleElement={'Attention'}
cancel={() => handleFlashErrorResponse(false)}
done={() => handleFlashErrorResponse(true)}
action={'Retry'}
>
<Txt>
{_.map(errorMessage.split('\n'), (message, key) => (
<p key={key}>{message}</p>
))} ))}
</Txt> </Modal>
</Modal> )}
)}
{showDriveSelectorModal && ( {this.state.errorMessage && (
<DriveSelectorModal <Modal
close={() => setShowDriveSelectorModal(false)} width={400}
></DriveSelectorModal> titleElement={'Attention'}
)} cancel={() => this.handleFlashErrorResponse(false)}
</> done={() => this.handleFlashErrorResponse(true)}
); action={'Retry'}
}; >
<Txt>
{_.map(this.state.errorMessage.split('\n'), (message, key) => (
<p key={key}>{message}</p>
))}
</Txt>
</Modal>
)}
{this.state.showDriveSelectorModal && (
<DriveSelectorModal
close={() => this.setState({ showDriveSelectorModal: false })}
/>
)}
</>
);
}
}

View File

@ -47,7 +47,7 @@ import { middleEllipsis } from '../../utils/middle-ellipsis';
import { bytesToClosestUnit } from '../../../../shared/units'; import { bytesToClosestUnit } from '../../../../shared/units';
import { DriveSelector } from './DriveSelector'; import { DriveSelector } from './DriveSelector';
import { Flash } from './Flash'; import { FlashStep } from './Flash';
const Icon = styled(BaseIcon)` const Icon = styled(BaseIcon)`
margin-right: 20px; margin-right: 20px;
@ -249,7 +249,7 @@ export class MainPage extends React.Component<
</div> </div>
<div className="col-xs"> <div className="col-xs">
<Flash <FlashStep
goToSuccess={() => this.setState({ current: 'success' })} goToSuccess={() => this.setState({ current: 'success' })}
shouldFlashStepBeDisabled={shouldFlashStepBeDisabled} shouldFlashStepBeDisabled={shouldFlashStepBeDisabled}
source={this.state.source} source={this.state.source}