From c1ab2f44d08392960a0a71d29fb9659f6cd47639 Mon Sep 17 00:00:00 2001 From: NastiaS Date: Wed, 23 May 2018 18:29:07 +0200 Subject: [PATCH] genuine check screen, breadcrumb, disclaimer boxes --- .../Onboarding/OnboardingBreadcrumb.js | 13 +- src/components/Onboarding/helperComponents.js | 3 +- src/components/Onboarding/index.js | 5 +- src/components/Onboarding/steps/Analytics.js | 4 +- src/components/Onboarding/steps/Finish.js | 4 +- .../Onboarding/steps/GenuineCheck.js | 220 ++++++++++++++---- .../Onboarding/steps/SelectDevice.js | 4 +- src/components/Onboarding/steps/SelectPIN.js | 6 +- .../Onboarding/steps/SetPassword.js | 4 +- src/components/Onboarding/steps/WriteSeed.js | 6 +- src/icons/onboarding/LedgerNanoError.js | 78 +++++++ src/reducers/onboarding.js | 7 + static/i18n/en/onboarding.yml | 17 ++ 13 files changed, 312 insertions(+), 59 deletions(-) create mode 100644 src/icons/onboarding/LedgerNanoError.js diff --git a/src/components/Onboarding/OnboardingBreadcrumb.js b/src/components/Onboarding/OnboardingBreadcrumb.js index 8e789699..d45746fb 100644 --- a/src/components/Onboarding/OnboardingBreadcrumb.js +++ b/src/components/Onboarding/OnboardingBreadcrumb.js @@ -18,15 +18,22 @@ type Props = { function OnboardingBreadcrumb(props: Props) { const { onboarding } = props - const { stepName } = onboarding + const { stepName, isGenuineFail } = onboarding const filteredSteps = onboarding.steps .filter(step => !step.external) .map(step => ({ ...step, label: step.label })) // TODO: translate const stepIndex = findIndex(filteredSteps, s => s.name === stepName) - - return + const genuineStepIndex = findIndex(filteredSteps, s => s.name === 'genuineCheck') + + return ( + + ) } export default connect(mapStateToProps)(OnboardingBreadcrumb) diff --git a/src/components/Onboarding/helperComponents.js b/src/components/Onboarding/helperComponents.js index 0fa02e69..f7d8c312 100644 --- a/src/components/Onboarding/helperComponents.js +++ b/src/components/Onboarding/helperComponents.js @@ -73,7 +73,7 @@ export const IconOptionRow = styled(Box).attrs({ color: 'wallet', })`` -export function DisclaimerBox({ disclaimerNotes }: { disclaimerNotes: any }) { +export function DisclaimerBox({ disclaimerNotes, ...p }: { disclaimerNotes: any }) { return ( { @@ -107,6 +109,7 @@ class Onboarding extends PureComponent { const stepProps: StepProps = { t, onboarding, + setGenuineCheckFail, prevStep, nextStep, jumpStep, diff --git a/src/components/Onboarding/steps/Analytics.js b/src/components/Onboarding/steps/Analytics.js index a513d8ea..32ed6d1a 100644 --- a/src/components/Onboarding/steps/Analytics.js +++ b/src/components/Onboarding/steps/Analytics.js @@ -14,8 +14,8 @@ import type { StepProps } from '..' export default (props: StepProps) => { const { nextStep, prevStep, t } = props return ( - - + + {t('onboarding:analytics.title')} {t('onboarding:analytics.desc')} diff --git a/src/components/Onboarding/steps/Finish.js b/src/components/Onboarding/steps/Finish.js index 2e880457..de1c1f97 100644 --- a/src/components/Onboarding/steps/Finish.js +++ b/src/components/Onboarding/steps/Finish.js @@ -39,8 +39,8 @@ const socialMedia = [ export default (props: StepProps) => { const { finish, t } = props return ( - - + + diff --git a/src/components/Onboarding/steps/GenuineCheck.js b/src/components/Onboarding/steps/GenuineCheck.js index d927035e..ba10714f 100644 --- a/src/components/Onboarding/steps/GenuineCheck.js +++ b/src/components/Onboarding/steps/GenuineCheck.js @@ -1,71 +1,122 @@ // @flow import React, { PureComponent } from 'react' +import { connect } from 'react-redux' +import styled from 'styled-components' +import { radii } from 'styles/theme' +import type { T } from 'types/common' -import Box from 'components/base/Box' +import { setGenuineCheckFail } from 'reducers/onboarding' + +import Box, { Card } from 'components/base/Box' import Button from 'components/base/Button' +import IconCheck from 'icons/Check' +import IconLedgerNanoError from 'icons/onboarding/LedgerNanoError' -import { Title, Description } from '../helperComponents' +import { Title, Description, IconOptionRow } from '../helperComponents' import type { StepProps } from '..' import OnboardingFooter from '../OnboardingFooter' +const mapDispatchToProps = { setGenuineCheckFail } + type State = { - currentDevice: { - manufacturer: string, - release: number, - }, - showDeviceInfo: boolean, - showError: boolean, + pinStepPass: boolean | null, + phraseStepPass: boolean | null, } -// temp checking the release version of the device if connected - class GenuineCheck extends PureComponent { state = { - showDeviceInfo: false, - currentDevice: { manufacturer: 'Unknown', release: 0 }, - showError: false, + pinStepPass: null, + phraseStepPass: null, } - handleCheckDevice = () => { - const currentDeviceInfo = this.props.getDeviceInfo() - if (currentDeviceInfo) { - this.setState({ showError: false, currentDevice: currentDeviceInfo, showDeviceInfo: true }) - } else { - this.setState({ showError: true }) + handleStepPass = (step: string, pass: boolean | null) => { + this.setState({ [`${step}`]: pass }) + + if (typeof pass === 'boolean' && !pass) { + this.props.setGenuineCheckFail(true) } } + redoGenuineCheck = () => { + this.props.setGenuineCheckFail(false) + } + contactSupport = () => { + console.log('contact support coming later') + } + renderGenuineFail = () => ( + + ) + render() { - const { nextStep, prevStep, t } = this.props - const { showDeviceInfo, currentDevice, showError } = this.state + const { nextStep, prevStep, t, onboarding } = this.props + const { pinStepPass, phraseStepPass } = this.state + + if (onboarding.isGenuineFail) { + return this.renderGenuineFail() + } return ( - - + + {t('onboarding:genuineCheck.title')} {t('onboarding:genuineCheck.desc')} - - Coming next week - - - {showDeviceInfo && ( - - - The manufacturer is {currentDevice.manufacturer} - The release number is {currentDevice.release} - + + + + + 1. + {t('onboarding:genuineCheck.steps.step1.title')} + + {t('onboarding:genuineCheck.steps.step2.desc')} + + {!pinStepPass ? ( + + ) : ( + + )} - {showError && ( - - Connect your device please + + + + + + + 2. + {t('onboarding:genuineCheck.steps.step2.title')} + + {t('onboarding:genuineCheck.steps.step2.desc')} + + {!phraseStepPass ? ( + + ) : ( + + )} - + + + + + + + 3. + {t('onboarding:genuineCheck.steps.step3.title')} + + {t('onboarding:genuineCheck.steps.step3.desc')} + + + + + { } } -export default GenuineCheck +export default connect(null, mapDispatchToProps)(GenuineCheck) + +export function ButtonCombo({ handleStepPass, step }: { handleStepPass: any, step: string }) { + return ( + + + + + ) +} +// TODO extract to the separate file +export function GenuineCheckFail({ + redoGenuineCheck, + contactSupport, + t, +}: { + redoGenuineCheck: () => void, + contactSupport: () => void, + t: T, +}) { + return ( + + + {t('onboarding:genuineCheck.errorPage.ledgerNano.title')} + + {t('onboarding:genuineCheck.errorPage.ledgerNano.desc')} + + + + + + + + + + + ) +} +export const CardDescription = styled(Box).attrs({ + ff: 'Open Sans|Regular', + fontSize: 4, + textAlign: 'left', + color: 'grey', +})` + max-width: 400px; +` +export const CardTitle = styled(Box).attrs({ + ff: 'Open Sans|SemiBold', + fontSize: 4, + textAlign: 'left', + 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(Card).attrs({ + horizontal: true, + p: 5, +})` + border: 1px solid #d8d8d8; + max-height: 97px; + min-width: 620px; +` diff --git a/src/components/Onboarding/steps/SelectDevice.js b/src/components/Onboarding/steps/SelectDevice.js index fc5d226a..9dbca9f8 100644 --- a/src/components/Onboarding/steps/SelectDevice.js +++ b/src/components/Onboarding/steps/SelectDevice.js @@ -14,8 +14,8 @@ export default (props: StepProps) => { const { nextStep, t } = props return ( - - + + {t('onboarding:selectDevice.title')} {t('onboarding:selectDevice.desc')} diff --git a/src/components/Onboarding/steps/SelectPIN.js b/src/components/Onboarding/steps/SelectPIN.js index c4fbf93f..81736509 100644 --- a/src/components/Onboarding/steps/SelectPIN.js +++ b/src/components/Onboarding/steps/SelectPIN.js @@ -62,8 +62,8 @@ export default (props: StepProps) => { }, ] return ( - - + + {t('onboarding:selectPIN.title')} {t('onboarding:selectPIN.desc')} @@ -78,7 +78,7 @@ export default (props: StepProps) => { {steps.map(step => )} - + { const { nextStep, prevStep, t } = this.props const { isPasswordModalOpened, isPasswordEnabled } = this.state return ( - - + + {t('onboarding:setPassword.title')} {t('onboarding:setPassword.desc')} diff --git a/src/components/Onboarding/steps/WriteSeed.js b/src/components/Onboarding/steps/WriteSeed.js index c73fd947..d7378458 100644 --- a/src/components/Onboarding/steps/WriteSeed.js +++ b/src/components/Onboarding/steps/WriteSeed.js @@ -56,8 +56,8 @@ export default (props: StepProps) => { }, ] return ( - - + + {t('onboarding:writeSeed.title')} {t('onboarding:writeSeed.desc')} @@ -71,7 +71,7 @@ export default (props: StepProps) => { {steps.map(step => )} - + ( + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +) diff --git a/src/reducers/onboarding.js b/src/reducers/onboarding.js index 8091a7b4..97993271 100644 --- a/src/reducers/onboarding.js +++ b/src/reducers/onboarding.js @@ -17,11 +17,13 @@ export type OnboardingState = { stepIndex: number, stepName: string, // TODO: specify that the string comes from Steps type steps: Step[], + isGenuineFail: boolean, } const state: OnboardingState = { stepIndex: 0, stepName: 'start', + isGenuineFail: false, steps: [ { name: 'start', @@ -138,6 +140,10 @@ const handlers = { const index = state.steps.indexOf(step) return { ...state, stepName: step.name, stepIndex: index } }, + ONBOARDING_SET_GENUINE_CHECK_FAIL: (state, { payload: isGenuineFail }) => ({ + ...state, + isGenuineFail, + }), } export default handleActions(handlers, state) @@ -145,3 +151,4 @@ export default handleActions(handlers, state) export const nextStep = createAction('ONBOARDING_NEXT_STEP') export const prevStep = createAction('ONBOARDING_PREV_STEP') export const jumpStep = createAction('ONBOARDING_JUMP_STEP') +export const setGenuineCheckFail = createAction('ONBOARDING_SET_GENUINE_CHECK_FAIL') diff --git a/static/i18n/en/onboarding.yml b/static/i18n/en/onboarding.yml index 25aad1eb..882b2993 100644 --- a/static/i18n/en/onboarding.yml +++ b/static/i18n/en/onboarding.yml @@ -51,6 +51,23 @@ writeSeed: genuineCheck: title: Check PIN / Seed / Authenticity desc: Your Ledger Nano S should now display Your device is now ready. Before getting started, please confirm that + steps: + step1: + title: You alone have chosen your PIN code + desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor + step2: + title: You alone have initialized your recovery phrase + desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor + step3: + title: Your device is a genuine Ledger device + desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor + buttons: + genuineCheck: Genuine check + contactSupport: Contact Support + errorPage: + ledgerNano: + title: Something is wrong with your Ledger Nano S + desc: Your Ledger Nano S should now display Your device is now ready. Before getting started, please confirm that setPassword: title: This is the title of the screen. 1 line is the maximum desc: This is a long text, please replace it with the final wording once it’s done. Lorem ipsum dolor amet ledger lorem dolor ipsum amet