Browse Source

no device screen added to onboarding, minor polishes

master
Anastasia Poupeney 7 years ago
parent
commit
a79b900f1f
  1. 17
      src/components/Onboarding/OnboardingFooter.js
  2. 6
      src/components/Onboarding/helperComponents.js
  3. 2
      src/components/Onboarding/index.js
  4. 4
      src/components/Onboarding/steps/Finish.js
  5. 46
      src/components/Onboarding/steps/GenuineCheck.js
  6. 19
      src/components/Onboarding/steps/Init.js
  7. 71
      src/components/Onboarding/steps/NoDevice.js
  8. 4
      src/components/Onboarding/steps/SelectDevice.js
  9. 26
      src/components/Onboarding/steps/SetPassword.js
  10. 16
      src/icons/Cart.js
  11. 16
      src/icons/Truck.js
  12. 9
      src/reducers/onboarding.js
  13. 8
      static/i18n/en/onboarding.yml

17
src/components/Onboarding/OnboardingFooter.js

@ -1,22 +1,11 @@
// @flow
import React from 'react'
import styled from 'styled-components'
import { radii } from 'styles/theme'
import type { T } from 'types/common'
import Button from 'components/base/Button'
import Box from 'components/base/Box'
const Wrapper = styled(Box).attrs({
px: 5,
py: 3,
})`
border-top: 1px solid ${p => p.theme.colors.lightFog};
border-bottom-left-radius: ${radii[1]}px;
border-bottom-right-radius: ${radii[1]}px;
`
import { OnboardingFooterWrapper } from './helperComponents'
type Props = {
t: T,
@ -33,13 +22,13 @@ const OnboardingFooter = ({
...props
}: Props) => (
<Wrapper {...props}>
<OnboardingFooterWrapper {...props}>
<Button padded outlineGrey onClick={() => prevStep()}>
{t('app:common.back')}
</Button>
<Button padded disabled={isContinueDisabled} primary onClick={() => nextStep()} ml="auto">
{t('app:common.continue')}
</Button>
</Wrapper>
</OnboardingFooterWrapper>
)
export default OnboardingFooter

6
src/components/Onboarding/helperComponents.js

@ -38,11 +38,13 @@ export const FixedTopContainer = styled(Box).attrs({
backgroundColor: 'red',
})``
// FOOTER
export const OnboardingFooter = styled(Box).attrs({
export const OnboardingFooterWrapper = styled(Box).attrs({
px: 5,
py: 3,
horizontal: true,
})`
border-top: 2px solid ${p => p.theme.colors.lightGrey};
border-top: 2px solid ${p => p.theme.colors.lightFog};
border-bottom-left-radius: ${radii[1]}px;
border-bottom-right-radius: ${radii[1]}px;
`

2
src/components/Onboarding/index.js

@ -27,6 +27,7 @@ import Box from 'components/base/Box'
import Start from './steps/Start'
import InitStep from './steps/Init'
import NoDeviceStep from './steps/NoDevice'
import OnboardingBreadcrumb from './OnboardingBreadcrumb'
import SelectDevice from './steps/SelectDevice'
import SelectPIN from './steps/SelectPIN/index'
@ -46,6 +47,7 @@ const STEPS = {
analytics: Analytics,
finish: Finish,
start: Start,
noDevice: NoDeviceStep,
}
const mapStateToProps = state => ({

4
src/components/Onboarding/steps/Finish.js

@ -39,8 +39,8 @@ const socialMedia = [
export default (props: StepProps) => {
const { finish, t } = props
return (
<Box sticky pt={200}>
<Box grow alignItems="center">
<Box sticky justifyContent="center">
<Box alignItems="center">
<Box color="positiveGreen">
<IconCheckCircle size={44} />
</Box>

46
src/components/Onboarding/steps/GenuineCheck.js

@ -4,7 +4,7 @@ import React, { PureComponent, Fragment } from 'react'
import { shell } from 'electron'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { radii, colors } from 'styles/theme'
import { colors } from 'styles/theme'
import type { T } from 'types/common'
@ -19,7 +19,13 @@ import IconLedgerNanoError from 'icons/illustrations/LedgerNanoError'
import IconLedgerBlueError from 'icons/illustrations/LedgerBlueError'
import IconCheck from 'icons/Check'
import { Title, Description, IconOptionRow, FixedTopContainer } from '../helperComponents'
import {
Title,
Description,
IconOptionRow,
FixedTopContainer,
OnboardingFooterWrapper,
} from '../helperComponents'
import type { StepProps } from '..'
import OnboardingFooter from '../OnboardingFooter'
@ -145,7 +151,7 @@ class GenuineCheck extends PureComponent<StepProps, State> {
<CardWrapper isDisabled={!genuine.pinStepPass}>
<Box justify="center">
<Box horizontal>
<IconOptionRow>2.</IconOptionRow>
<IconOptionRow color={!genuine.pinStepPass ? 'grey' : 'wallet'}>2.</IconOptionRow>
<CardTitle>{t('onboarding:genuineCheck.steps.step2.title')}</CardTitle>
</Box>
</Box>
@ -164,7 +170,9 @@ class GenuineCheck extends PureComponent<StepProps, State> {
<CardWrapper isDisabled={!genuine.recoveryStepPass}>
<Box justify="center">
<Box horizontal>
<IconOptionRow>3.</IconOptionRow>
<IconOptionRow color={!genuine.recoveryStepPass ? 'grey' : 'wallet'}>
3.
</IconOptionRow>
<CardTitle>{t('onboarding:genuineCheck.steps.step3.title')}</CardTitle>
</Box>
</Box>
@ -250,27 +258,14 @@ export function GenuineCheckFail({
</Fragment>
)}
</Box>
<Wrapper horizontal>
<Button
padded
outlineGrey
onClick={() => {
redoGenuineCheck()
}}
>
<OnboardingFooterWrapper>
<Button padded outlineGrey onClick={() => redoGenuineCheck()}>
{t('app:common.back')}
</Button>
<Button
padded
danger
onClick={() => {
contactSupport()
}}
ml="auto"
>
<Button padded danger onClick={() => contactSupport()} ml="auto">
{t('onboarding:genuineCheck.buttons.contactSupport')}
</Button>
</Wrapper>
</OnboardingFooterWrapper>
</Box>
)
}
@ -285,14 +280,6 @@ export const CardTitle = styled(Box).attrs({
pl: 2,
})``
const Wrapper = styled(Box).attrs({
px: 5,
py: 3,
})`
border-top: 2px solid ${p => p.theme.colors.lightGrey};
border-bottom-left-radius: ${radii[1]}px;
border-bottom-right-radius: ${radii[1]}px;
`
const CardWrapper = styled(Box).attrs({
horizontal: true,
p: 5,
@ -302,6 +289,7 @@ const CardWrapper = styled(Box).attrs({
width: 580px;
height: 74px;
transition: all ease-in-out 0.2s;
color: ${p => (p.isDisabled ? p.theme.colors.grey : p.theme.colors.black)};
border: ${p => `1px ${p.isDisabled ? 'dashed' : 'solid'} ${p.theme.colors.fog}`};
pointer-events: ${p => (p.isDisabled ? 'none' : 'auto')};
background-color: ${p => (p.isDisabled ? p.theme.colors.lightGrey : p.theme.colors.white)};

19
src/components/Onboarding/steps/Init.js

@ -1,7 +1,6 @@
// @flow
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import { connect } from 'react-redux'
import { colors } from 'styles/theme'
@ -22,7 +21,7 @@ const mapDispatchToProps = { flowType }
class Init extends PureComponent<StepProps, *> {
render() {
const { nextStep, t } = this.props
const { t, flowType, jumpStep } = this.props
const optionCards = [
{
@ -30,8 +29,8 @@ class Init extends PureComponent<StepProps, *> {
icon: <IconPlus size={20} />,
title: t('onboarding:init.newDevice.title'),
onClick: () => {
nextStep()
this.props.flowType('newDevice')
jumpStep('selectDevice')
flowType('newDevice')
},
},
{
@ -39,8 +38,8 @@ class Init extends PureComponent<StepProps, *> {
icon: <IconRecover size={20} />,
title: t('onboarding:init.restoreDevice.title'),
onClick: () => {
nextStep()
this.props.flowType('restoreDevice')
jumpStep('selectDevice')
flowType('restoreDevice')
},
},
{
@ -48,8 +47,8 @@ class Init extends PureComponent<StepProps, *> {
icon: <IconCheck size={20} />,
title: t('onboarding:init.initializedDevice.title'),
onClick: () => {
nextStep()
this.props.flowType('initializedDevice')
jumpStep('selectDevice')
flowType('initializedDevice')
},
},
{
@ -57,8 +56,8 @@ class Init extends PureComponent<StepProps, *> {
icon: <IconExternalLink size={20} />,
title: t('onboarding:init.noDevice.title'),
onClick: () => {
shell.openExternal('https://www.ledger.fr/')
this.props.flowType('noDevice')
jumpStep('noDevice')
flowType('noDevice')
},
},
]

71
src/components/Onboarding/steps/NoDevice.js

@ -0,0 +1,71 @@
// @flow
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import Box from 'components/base/Box'
import IconUser from 'icons/User'
import IconCart from 'icons/Cart'
import IconTruck from 'icons/Truck'
import IconInfoCircle from 'icons/InfoCircle'
import Button from '../../base/Button/index'
import { Title, OnboardingFooterWrapper } from '../helperComponents'
import { OptionFlowCard } from './Init'
import type { StepProps } from '..'
class NoDevice extends PureComponent<StepProps, *> {
render() {
const { t, prevStep } = this.props
const optionCards = [
{
key: 'buyNew',
icon: <IconCart size={20} />,
title: t('onboarding:noDevice.buyNew.title'),
onClick: () => {
shell.openExternal('https://www.ledgerwallet.com/')
},
},
{
key: 'trackOrder',
icon: <IconTruck size={20} />,
title: t('onboarding:noDevice.trackOrder.title'),
onClick: () => {
shell.openExternal('http://order.ledgerwallet.com/')
},
},
{
key: 'learnMore',
icon: <IconInfoCircle size={20} />,
title: t('onboarding:noDevice.learnMore.title'),
onClick: () => {
shell.openExternal('https://www.ledgerwallet.com/')
},
},
]
return (
<Box sticky pt={130}>
<Box grow alignItems="center">
<Box color="wallet">
<IconUser size={36} />
</Box>
<Box m={5} style={{ maxWidth: 480 }}>
<Title>{t('onboarding:noDevice.title')}</Title>
</Box>
<Box pt={4} flow={4}>
{optionCards.map(card => <OptionFlowCard key={card.key} card={card} />)}
</Box>
</Box>
<OnboardingFooterWrapper>
<Button padded outlineGrey onClick={() => prevStep()} mr="auto">
{t('app:common.back')}
</Button>
</OnboardingFooterWrapper>
</Box>
)
}
}
export default NoDevice

4
src/components/Onboarding/steps/SelectDevice.js

@ -32,7 +32,7 @@ class SelectDevice extends PureComponent<StepProps, {}> {
}
}
render() {
const { t, onboarding, prevStep } = this.props
const { t, onboarding, jumpStep } = this.props
return (
<FixedTopContainer>
<Box grow alignItems="center">
@ -68,7 +68,7 @@ class SelectDevice extends PureComponent<StepProps, {}> {
horizontal
t={t}
nextStep={this.handleContinue}
prevStep={prevStep}
prevStep={() => jumpStep('init')}
isContinueDisabled={onboarding.isLedgerNano === null}
/>
</FixedTopContainer>

26
src/components/Onboarding/steps/SetPassword.js

@ -2,8 +2,7 @@
import React, { PureComponent, Fragment } from 'react'
import bcrypt from 'bcryptjs'
import { colors, radii } from 'styles/theme'
import styled from 'styled-components'
import { colors } from 'styles/theme'
import { setEncryptionKey } from 'helpers/db'
@ -15,7 +14,13 @@ import IconChevronRight from 'icons/ChevronRight'
import PasswordForm from '../../SettingsPage/PasswordForm'
import type { StepProps } from '..'
import { Title, Description, DisclaimerBox, FixedTopContainer } from '../helperComponents'
import {
Title,
Description,
DisclaimerBox,
FixedTopContainer,
OnboardingFooterWrapper,
} from '../helperComponents'
type State = {
currentPassword: string,
@ -117,7 +122,7 @@ class SetPassword extends PureComponent<StepProps, State> {
</Fragment>
</Box>
<CustomFooter>
<OnboardingFooterWrapper>
<Button padded outlineGrey onClick={() => prevStep()}>
{t('app:common.back')}
</Button>
@ -134,21 +139,10 @@ class SetPassword extends PureComponent<StepProps, State> {
{t('app:common.continue')}
</Button>
</Box>
</CustomFooter>
</OnboardingFooterWrapper>
</FixedTopContainer>
)
}
}
export default SetPassword
const CustomFooter = styled(Box).attrs({
px: 5,
py: 3,
horizontal: true,
align: 'center',
})`
border-top: 1px solid ${p => p.theme.colors.lightFog};
border-bottom-left-radius: ${radii[1]}px;
border-bottom-right-radius: ${radii[1]}px;
`

16
src/icons/Cart.js

@ -0,0 +1,16 @@
// @flow
import React from 'react'
const path = (
<path
fill="currentColor"
d="M15.333 2.375H4.008l-.243-1.307A.677.677 0 0 0 3.111.5H.333A.343.343 0 0 0 0 .852v.703c0 .194.15.351.333.351h2.23l1.932 10.421A1.923 1.923 0 0 0 4 13.625c0 1.036.796 1.875 1.778 1.875s1.778-.84 1.778-1.875c0-.33-.082-.653-.239-.938h4.033a1.945 1.945 0 0 0-.239.938c0 1.036.796 1.875 1.778 1.875s1.778-.84 1.778-1.875c0-.531-.21-1.01-.547-1.352l.029-.14c.09-.437-.226-.852-.652-.852H5.66L5.4 9.875h8.677c.314 0 .585-.23.652-.554l1.256-6.094c.09-.438-.227-.852-.652-.852zM5.778 14.328c-.368 0-.667-.315-.667-.703 0-.388.3-.703.667-.703.367 0 .666.315.666.703 0 .388-.299.703-.666.703zm7.11 0c-.367 0-.666-.315-.666-.703 0-.388.3-.703.667-.703.368 0 .667.315.667.703 0 .388-.3.703-.667.703zm.652-5.86H5.138l-.87-4.687h10.238L13.54 8.47z"
/>
)
export default ({ size, ...p }: { size: number }) => (
<svg viewBox="0 0 16 16" height={size} width={size} {...p}>
{path}
</svg>
)

16
src/icons/Truck.js

@ -0,0 +1,16 @@
// @flow
import React from 'react'
const path = (
<path
fill="currentColor"
d="M14.8 1.5h-8c-.663 0-1.2.546-1.2 1.219v1.219H4.497a1.19 1.19 0 0 0-.848.356L1.15 6.831a1.228 1.228 0 0 0-.351.861v3.152H.5c-.166 0-.3.136-.3.304v.61c0 .168.134.305.3.305h1.1C1.6 13.409 2.675 14.5 4 14.5s2.4-1.091 2.4-2.438h3.2c0 1.347 1.075 2.438 2.4 2.438s2.4-1.091 2.4-2.438h.4c.663 0 1.2-.545 1.2-1.218V2.719A1.21 1.21 0 0 0 14.8 1.5zM4 13.281a1.21 1.21 0 0 1-1.2-1.219A1.21 1.21 0 0 1 4 10.845c.662 0 1.2.546 1.2 1.219A1.21 1.21 0 0 1 4 13.28zm1.6-3.035A2.37 2.37 0 0 0 4 9.625c-.835 0-1.57.433-2 1.09V7.692l2.497-2.536H5.6v5.09zM12 13.28a1.21 1.21 0 0 1-1.2-1.219 1.21 1.21 0 0 1 1.2-1.218c.662 0 1.2.546 1.2 1.219A1.21 1.21 0 0 1 12 13.28zm2.8-2.437h-.721A2.393 2.393 0 0 0 12 9.625c-.888 0-1.664.49-2.079 1.219H6.8V2.719h8v8.125zM2.8 8l2-2.031V8h-2z"
/>
)
export default ({ size, ...p }: { size: number }) => (
<svg viewBox="0 0 16 16" height={size} width={size} {...p}>
{path}
</svg>
)

9
src/reducers/onboarding.js

@ -57,6 +57,15 @@ const state: OnboardingState = {
showBreadcrumb: false,
},
},
{
name: 'noDevice',
external: true,
options: {
showFooter: false,
showBackground: true,
showBreadcrumb: false,
},
},
{
name: 'selectDevice',
label: 'Select Device',

8
static/i18n/en/onboarding.yml

@ -15,6 +15,14 @@ init:
noDevice:
title: Do not have a Ledger device yet?
desc: Please replace it with the final wording once it’s done.
noDevice:
title: Do not have a Ledger device yet?
buyNew:
title: Buy a Ledger device
trackOrder:
title: Track your order
learnMore:
title: Learn about Ledger Live
selectDevice:
title: To get started, select your device
ledgerNanoCard:

Loading…
Cancel
Save