Refactor UI grid to use rendition

Change-type: patch
Changelog-entry: Refactor UI grid to use rendition
Signed-off-by: Lorenzo Alberto Maria Ambrosi <lorenzothunder.ambrosi@gmail.com>
This commit is contained in:
Lorenzo Alberto Maria Ambrosi 2020-06-12 13:14:16 +02:00
parent 72e5631167
commit 9b71772e35
7 changed files with 195 additions and 221 deletions

View File

@ -84,7 +84,9 @@ export class ProgressButton extends React.PureComponent<ProgressButtonProps> {
return ( return (
<> <>
<Flex <Flex
alignItems="baseline"
justifyContent="space-between" justifyContent="space-between"
width="100%"
style={{ style={{
marginTop: 42, marginTop: 42,
marginBottom: '6px', marginBottom: '6px',

View File

@ -22,7 +22,14 @@ import * as _ from 'lodash';
import { GPTPartition, MBRPartition } from 'partitioninfo'; import { GPTPartition, MBRPartition } from 'partitioninfo';
import * as path from 'path'; import * as path from 'path';
import * as React from 'react'; import * as React from 'react';
import { ButtonProps, Card as BaseCard, Input, Modal, Txt } from 'rendition'; import {
ButtonProps,
Card as BaseCard,
Input,
Modal,
Txt,
Flex,
} from 'rendition';
import styled from 'styled-components'; import styled from 'styled-components';
import * as errors from '../../../../shared/errors'; import * as errors from '../../../../shared/errors';
@ -464,61 +471,55 @@ export class SourceSelector extends React.Component<
return ( return (
<> <>
<div <Flex
className="box text-center relative" flexDirection="column"
alignItems="center"
onDrop={this.onDrop} onDrop={this.onDrop}
onDragEnter={this.onDragEnter} onDragEnter={this.onDragEnter}
onDragOver={this.onDragOver} onDragOver={this.onDragOver}
> >
<div className="center-block"> <SVGIcon
<SVGIcon contents={imageLogo}
contents={imageLogo} fallback={<ImageSvg width="40px" />}
fallback={<ImageSvg width="40px" height="40px" />} />
/>
</div>
<div className="space-vertical-large"> {hasImage ? (
{hasImage ? ( <>
<> <StepNameButton
<StepNameButton plain
plain onClick={this.showSelectedImageDetails}
fontSize={16} tooltip={imageName || imageBasename}
onClick={this.showSelectedImageDetails} >
tooltip={imageName || imageBasename} {middleEllipsis(imageName || imageBasename, 20)}
> </StepNameButton>
{middleEllipsis(imageName || imageBasename, 20)} {!flashing && (
</StepNameButton> <ChangeButton plain mb={14} onClick={this.reselectImage}>
{!flashing && ( Remove
<ChangeButton plain mb={14} onClick={this.reselectImage}> </ChangeButton>
Remove )}
</ChangeButton> <DetailsText>{shared.bytesToClosestUnit(imageSize)}</DetailsText>
)} </>
<DetailsText> ) : (
{shared.bytesToClosestUnit(imageSize)} <>
</DetailsText> <FlowSelector
</> key="Flash from file"
) : ( flow={{
<> onClick: this.openImageSelector,
<FlowSelector label: 'Flash from file',
key="Flash from file" icon: <FontAwesomeIcon icon={faFile} />,
flow={{ }}
onClick: this.openImageSelector, />
label: 'Flash from file', <FlowSelector
icon: <FontAwesomeIcon icon={faFile} />, key="Flash from URL"
}} flow={{
/> onClick: this.openURLSelector,
<FlowSelector label: 'Flash from URL',
key="Flash from URL" icon: <FontAwesomeIcon icon={faLink} />,
flow={{ }}
onClick: this.openURLSelector, />
label: 'Flash from URL', </>
icon: <FontAwesomeIcon icon={faLink} />, )}
}} </Flex>
/>
</>
)}
</div>
</div>
{this.state.warning != null && ( {this.state.warning != null && (
<Modal <Modal

View File

@ -118,7 +118,7 @@ export function TargetSelector(props: TargetSelectorProps) {
} }
return ( return (
<> <>
<StepNameButton plain tooltip={props.tooltip} fontSize={16}> <StepNameButton plain tooltip={props.tooltip}>
{targets.length} Targets {targets.length} Targets
</StepNameButton> </StepNameButton>
{!props.flashing && ( {!props.flashing && (

View File

@ -16,8 +16,7 @@
import { scanner } from 'etcher-sdk'; import { scanner } from 'etcher-sdk';
import * as React from 'react'; import * as React from 'react';
import styled from 'styled-components'; import { Flex } from 'rendition';
import { TargetSelector } from '../../components/target-selector/target-selector-button'; import { TargetSelector } from '../../components/target-selector/target-selector-button';
import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal'; import { TargetSelectorModal } from '../../components/target-selector/target-selector-modal';
import { import {
@ -30,27 +29,8 @@ import {
import * as settings from '../../models/settings'; import * as settings from '../../models/settings';
import { observe } from '../../models/store'; import { observe } from '../../models/store';
import * as analytics from '../../modules/analytics'; import * as analytics from '../../modules/analytics';
import DriveSvg from '../../../assets/drive.svg'; import DriveSvg from '../../../assets/drive.svg';
const StepBorder = styled.div<{
disabled: boolean;
left?: boolean;
right?: boolean;
}>`
height: 2px;
background-color: ${(props) =>
props.disabled
? props.theme.colors.dark.disabled.foreground
: props.theme.colors.dark.foreground};
position: absolute;
width: 124px;
top: 19px;
left: ${(props) => (props.left ? '-67px' : undefined)};
right: ${(props) => (props.right ? '-67px' : undefined)};
`;
const getDriveListLabel = () => { const getDriveListLabel = () => {
return getSelectedDrives() return getSelectedDrives()
.map((drive: any) => { .map((drive: any) => {
@ -100,17 +80,13 @@ export const selectAllTargets = (
}; };
interface DriveSelectorProps { interface DriveSelectorProps {
webviewShowing: boolean;
disabled: boolean; disabled: boolean;
nextStepDisabled: boolean;
hasDrive: boolean; hasDrive: boolean;
flashing: boolean; flashing: boolean;
} }
export const DriveSelector = ({ export const DriveSelector = ({
webviewShowing,
disabled, disabled,
nextStepDisabled,
hasDrive, hasDrive,
flashing, flashing,
}: DriveSelectorProps) => { }: DriveSelectorProps) => {
@ -129,38 +105,25 @@ export const DriveSelector = ({
}); });
}, []); }, []);
const showStepConnectingLines = !webviewShowing || !flashing;
return ( return (
<div className="box text-center relative"> <Flex flexDirection="column" alignItems="center">
{showStepConnectingLines && ( <DriveSvg className={disabled ? 'disabled' : ''} width="40px" />
<>
<StepBorder disabled={disabled} left />
<StepBorder disabled={nextStepDisabled} right />
</>
)}
<div className="center-block"> <TargetSelector
<DriveSvg className={disabled ? 'disabled' : ''} width="40px" /> disabled={disabled}
</div> show={!hasDrive && showDrivesButton}
tooltip={driveListLabel}
<div className="space-vertical-large"> openDriveSelector={() => {
<TargetSelector setShowTargetSelectorModal(true);
disabled={disabled} }}
show={!hasDrive && showDrivesButton} reselectDrive={() => {
tooltip={driveListLabel} analytics.logEvent('Reselect drive');
openDriveSelector={() => { setShowTargetSelectorModal(true);
setShowTargetSelectorModal(true); }}
}} flashing={flashing}
reselectDrive={() => { targets={targets}
analytics.logEvent('Reselect drive'); image={image}
setShowTargetSelectorModal(true); />
}}
flashing={flashing}
targets={targets}
image={image}
/>
</div>
{showTargetSelectorModal && ( {showTargetSelectorModal && (
<TargetSelectorModal <TargetSelectorModal
@ -171,6 +134,6 @@ export const DriveSelector = ({
}} }}
></TargetSelectorModal> ></TargetSelectorModal>
)} )}
</div> </Flex>
); );
}; };

View File

@ -234,62 +234,59 @@ export class FlashStep extends React.PureComponent<
public render() { public render() {
return ( return (
<> <>
<div className="box text-center"> <Flex flexDirection="column" alignItems="center">
<div className="center-block"> <FlashSvg
<FlashSvg width="40px"
width="40px" className={this.props.shouldFlashStepBeDisabled ? 'disabled' : ''}
className={this.props.shouldFlashStepBeDisabled ? 'disabled' : ''} />
/>
</div>
<div className="space-vertical-large"> <ProgressButton
<ProgressButton type={this.props.step}
type={this.props.step} active={this.props.isFlashing}
active={this.props.isFlashing} percentage={this.props.percentage}
percentage={this.props.percentage} position={this.props.position}
position={this.props.position} disabled={this.props.shouldFlashStepBeDisabled}
disabled={this.props.shouldFlashStepBeDisabled} cancel={imageWriter.cancel}
cancel={imageWriter.cancel} warning={this.hasListWarnings(
warning={this.hasListWarnings( selection.getSelectedDrives(),
selection.getSelectedDrives(), selection.getImage(),
selection.getImage(),
)}
callback={() => {
this.tryFlash();
}}
/>
{!_.isNil(this.props.speed) &&
this.props.percentage !== COMPLETED_PERCENTAGE && (
<Flex
justifyContent="space-between"
fontSize="14px"
color="#7e8085"
>
{!_.isNil(this.props.speed) && (
<Txt>{this.props.speed.toFixed(SPEED_PRECISION)} MB/s</Txt>
)}
{!_.isNil(this.props.eta) && (
<Txt>ETA: {formatSeconds(this.props.eta)}</Txt>
)}
</Flex>
)}
{Boolean(this.props.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">
{this.props.failed}
</span>
<span className="target-status-message">
{messages.progress.failed(this.props.failed)}{' '}
</span>
</div>
</div>
)} )}
</div> callback={() => {
</div> this.tryFlash();
}}
/>
{!_.isNil(this.props.speed) &&
this.props.percentage !== COMPLETED_PERCENTAGE && (
<Flex
justifyContent="space-between"
fontSize="14px"
color="#7e8085"
width="100%"
>
{!_.isNil(this.props.speed) && (
<Txt>{this.props.speed.toFixed(SPEED_PRECISION)} MB/s</Txt>
)}
{!_.isNil(this.props.eta) && (
<Txt>ETA: {formatSeconds(this.props.eta)}</Txt>
)}
</Flex>
)}
{Boolean(this.props.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">
{this.props.failed}
</span>
<span className="target-status-message">
{messages.progress.failed(this.props.failed)}{' '}
</span>
</div>
</div>
)}
</Flex>
{this.state.warningMessages.length > 0 && ( {this.state.warningMessages.length > 0 && (
<Modal <Modal

View File

@ -78,6 +78,26 @@ function getImageBasename() {
return selectionImageName || imageBasename; return selectionImageName || imageBasename;
} }
const StepBorder = styled.div<{
disabled: boolean;
left?: boolean;
right?: boolean;
}>`
position: relative;
height: 2px;
background-color: ${(props) =>
props.disabled
? props.theme.colors.dark.disabled.foreground
: props.theme.colors.dark.foreground};
width: 120px;
top: 19px;
left: ${(props) => (props.left ? '-67px' : undefined)};
margin-right: ${(props) => (props.left ? '-120px' : undefined)};
right: ${(props) => (props.right ? '-67px' : undefined)};
margin-left: ${(props) => (props.right ? '-120px' : undefined)};
`;
interface MainPageStateFromStore { interface MainPageStateFromStore {
isFlashing: boolean; isFlashing: boolean;
hasImage: boolean; hasImage: boolean;
@ -193,73 +213,65 @@ export class MainPage extends React.Component<
/> />
)} )}
<Flex <Flex m="110px 55px" justifyContent="space-between">
className="page-main row around-xs" <SourceSelector
style={{ margin: '110px 50px' }} flashing={this.state.isFlashing}
> afterSelected={(source: SourceOptions) => this.setState({ source })}
<div className="col-xs"> />
<SourceSelector
flashing={this.state.isFlashing}
afterSelected={(source: SourceOptions) =>
this.setState({ source })
}
/>
</div>
<div className="col-xs"> {(!this.state.isWebviewShowing || !this.state.isFlashing) && (
<DriveSelector <Flex>
webviewShowing={this.state.isWebviewShowing} <StepBorder disabled={shouldDriveStepBeDisabled} left />
disabled={shouldDriveStepBeDisabled} </Flex>
nextStepDisabled={shouldFlashStepBeDisabled} )}
hasDrive={this.state.hasDrive}
flashing={this.state.isFlashing}
/>
</div>
{this.state.isFlashing && ( <DriveSelector
<div disabled={shouldDriveStepBeDisabled}
className={`featured-project ${ hasDrive={this.state.hasDrive}
this.state.isFlashing && this.state.isWebviewShowing flashing={this.state.isFlashing}
? 'fp-visible' />
: ''
}`} {(!this.state.isWebviewShowing || !this.state.isFlashing) && (
> <Flex>
<StepBorder disabled={shouldFlashStepBeDisabled} right />
</Flex>
)}
{this.state.isFlashing && this.state.isWebviewShowing && (
<>
<FeaturedProject <FeaturedProject
onWebviewShow={(isWebviewShowing: boolean) => { onWebviewShow={(isWebviewShowing: boolean) => {
this.setState({ isWebviewShowing }); this.setState({ isWebviewShowing });
}} }}
/> />
</div> <ReducedFlashingInfos
imageLogo={this.state.imageLogo}
imageName={middleEllipsis(this.state.imageName, 16)}
imageSize={
_.isNumber(this.state.imageSize)
? (bytesToClosestUnit(this.state.imageSize) as string)
: ''
}
driveTitle={middleEllipsis(this.state.driveTitle, 16)}
shouldShow={
this.state.isFlashing && this.state.isWebviewShowing
}
/>
</>
)} )}
<div> <FlashStep
<ReducedFlashingInfos goToSuccess={() => this.setState({ current: 'success' })}
imageLogo={this.state.imageLogo} shouldFlashStepBeDisabled={shouldFlashStepBeDisabled}
imageName={middleEllipsis(this.state.imageName, 16)} source={this.state.source}
imageSize={ isFlashing={flashState.isFlashing()}
_.isNumber(this.state.imageSize) step={state.type}
? (bytesToClosestUnit(this.state.imageSize) as string) percentage={state.percentage}
: '' position={state.position}
} failed={state.failed}
driveTitle={middleEllipsis(this.state.driveTitle, 16)} speed={state.speed}
shouldShow={this.state.isFlashing && this.state.isWebviewShowing} eta={state.eta}
/> />
</div>
<div className="col-xs">
<FlashStep
goToSuccess={() => this.setState({ current: 'success' })}
shouldFlashStepBeDisabled={shouldFlashStepBeDisabled}
source={this.state.source}
isFlashing={flashState.isFlashing()}
step={state.type}
percentage={state.percentage}
position={state.position}
failed={state.failed}
speed={state.speed}
eta={state.eta}
/>
</div>
</Flex> </Flex>
</> </>
); );

View File

@ -54,7 +54,6 @@ export const StepButton = styled((props: ButtonProps) => (
<BaseButton {...props}></BaseButton> <BaseButton {...props}></BaseButton>
))` ))`
color: #ffffff; color: #ffffff;
margin: auto;
`; `;
export const ChangeButton = styled(Button)` export const ChangeButton = styled(Button)`