Browse Source

Merge pull request #836 from NastiaS/analytics-addition-onboarding

Analytics addition onboarding
master
NastiaS 7 years ago
committed by GitHub
parent
commit
bb7438f9de
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      src/components/Onboarding/index.js
  2. 67
      src/components/Onboarding/steps/Analytics.js
  3. 3
      src/components/base/Switch/index.js
  4. 99
      src/components/modals/ShareAnalytics.js
  5. 71
      src/components/modals/TechnicalData.js
  6. 2
      src/config/constants.js
  7. 1
      static/i18n/en/app.yml
  8. 26
      static/i18n/en/onboarding.yml

2
src/components/Onboarding/index.js

@ -96,6 +96,7 @@ export type StepProps = {
savePassword: Function, savePassword: Function,
getDeviceInfo: Function, getDeviceInfo: Function,
updateGenuineCheck: Function, updateGenuineCheck: Function,
openModal: Function,
isLedgerNano: Function, isLedgerNano: Function,
flowType: Function, flowType: Function,
} }
@ -145,6 +146,7 @@ class Onboarding extends PureComponent<Props> {
onboarding, onboarding,
settings, settings,
updateGenuineCheck, updateGenuineCheck,
openModal,
isLedgerNano, isLedgerNano,
flowType, flowType,
prevStep, prevStep,

67
src/components/Onboarding/steps/Analytics.js

@ -8,12 +8,17 @@ import Box from 'components/base/Box'
import Switch from 'components/base/Switch' import Switch from 'components/base/Switch'
import TrackPage from 'analytics/TrackPage' import TrackPage from 'analytics/TrackPage'
import Track from 'analytics/Track' import Track from 'analytics/Track'
import { openModal } from 'reducers/modals'
import { MODAL_SHARE_ANALYTICS, MODAL_TECHNICAL_DATA } from 'config/constants'
import ShareAnalytics from '../../modals/ShareAnalytics'
import TechnicalData from '../../modals/TechnicalData'
import FakeLink from '../../base/FakeLink'
import { Title, Description, FixedTopContainer, StepContainerInner } from '../helperComponents' import { Title, Description, FixedTopContainer, StepContainerInner } from '../helperComponents'
import OnboardingFooter from '../OnboardingFooter' import OnboardingFooter from '../OnboardingFooter'
import type { StepProps } from '..' import type { StepProps } from '..'
const mapDispatchToProps = { saveSettings } const mapDispatchToProps = { saveSettings, openModal }
type State = { type State = {
analyticsToggle: boolean, analyticsToggle: boolean,
@ -46,7 +51,12 @@ class Analytics extends PureComponent<StepProps, State> {
savePassword(undefined) savePassword(undefined)
prevStep() prevStep()
} }
handleShareAnalyticsModal = () => {
this.props.openModal(MODAL_SHARE_ANALYTICS)
}
handleTechnicalDataModal = () => {
this.props.openModal(MODAL_TECHNICAL_DATA)
}
render() { render() {
const { nextStep, t, onboarding } = this.props const { nextStep, t, onboarding } = this.props
const { analyticsToggle, sentryLogsToggle } = this.state const { analyticsToggle, sentryLogsToggle } = this.state
@ -65,7 +75,9 @@ class Analytics extends PureComponent<StepProps, State> {
<Box mt={5}> <Box mt={5}>
<Container> <Container>
<Box> <Box>
<AnalyticsTitle>{t('onboarding:analytics.sentryLogs.title')}</AnalyticsTitle> <Box mb={1}>
<AnalyticsTitle>{t('onboarding:analytics.sentryLogs.title')}</AnalyticsTitle>
</Box>
<AnalyticsText>{t('onboarding:analytics.sentryLogs.desc')}</AnalyticsText> <AnalyticsText>{t('onboarding:analytics.sentryLogs.desc')}</AnalyticsText>
</Box> </Box>
<Box justifyContent="center"> <Box justifyContent="center">
@ -82,7 +94,19 @@ class Analytics extends PureComponent<StepProps, State> {
</Container> </Container>
<Container> <Container>
<Box> <Box>
<AnalyticsTitle>{t('onboarding:analytics.shareAnalytics.title')}</AnalyticsTitle> <Box horizontal mb={1}>
<AnalyticsTitle>{t('onboarding:analytics.shareAnalytics.title')}</AnalyticsTitle>
<FakeLink
style={{ textDecoration: 'underline' }}
fontSize={3}
color="smoke"
ml={2}
onClick={this.handleShareAnalyticsModal}
>
{t('app:common.learnMore')}
</FakeLink>
<ShareAnalytics />
</Box>
<AnalyticsText>{t('onboarding:analytics.shareAnalytics.desc')}</AnalyticsText> <AnalyticsText>{t('onboarding:analytics.shareAnalytics.desc')}</AnalyticsText>
</Box> </Box>
<Box justifyContent="center"> <Box justifyContent="center">
@ -97,6 +121,30 @@ class Analytics extends PureComponent<StepProps, State> {
<Switch isChecked={analyticsToggle} onChange={this.handleAnalyticsToggle} /> <Switch isChecked={analyticsToggle} onChange={this.handleAnalyticsToggle} />
</Box> </Box>
</Container> </Container>
<Container>
<Box>
<Box horizontal mb={1}>
<AnalyticsTitle>{t('onboarding:analytics.technicalData.title')}</AnalyticsTitle>
<FakeLink
underline
fontSize={3}
color="smoke"
ml={2}
onClick={this.handleTechnicalDataModal}
>
{t('app:common.learnMore')}
</FakeLink>
</Box>
<TechnicalData />
<AnalyticsText>{t('onboarding:analytics.technicalData.desc')}</AnalyticsText>
<MandatoryText>
{t('onboarding:analytics.technicalData.mandatoryText')}
</MandatoryText>
</Box>
<Box justifyContent="center">
<Switch disabled isChecked />
</Box>
</Container>
</Box> </Box>
</StepContainerInner> </StepContainerInner>
<OnboardingFooter <OnboardingFooter
@ -117,6 +165,13 @@ export default connect(
mapDispatchToProps, mapDispatchToProps,
)(Analytics) )(Analytics)
const MandatoryText = styled(Box).attrs({
ff: 'Open Sans|Regular',
fontSize: 2,
textAlign: 'left',
color: 'grey',
mt: 1,
})``
export const AnalyticsText = styled(Box).attrs({ export const AnalyticsText = styled(Box).attrs({
ff: 'Open Sans|Regular', ff: 'Open Sans|Regular',
fontSize: 3, fontSize: 3,
@ -129,9 +184,7 @@ export const AnalyticsTitle = styled(Box).attrs({
ff: 'Open Sans|SemiBold', ff: 'Open Sans|SemiBold',
fontSize: 4, fontSize: 4,
textAlign: 'left', textAlign: 'left',
})` })``
margin-bottom: 5px;
`
const Container = styled(Box).attrs({ const Container = styled(Box).attrs({
horizontal: true, horizontal: true,
p: 3, p: 3,

3
src/components/base/Switch/index.js

@ -15,8 +15,9 @@ const Base = styled(Tabbable).attrs({
width: 50px; width: 50px;
height: 26px; height: 26px;
border-radius: 13px; border-radius: 13px;
opacity: ${p => (p.disabled ? 0.3 : 1)};
transition: 250ms linear background-color; transition: 250ms linear background-color;
cursor: pointer; cursor: ${p => (p.disabled ? 'cursor' : 'pointer')};
&:focus { &:focus {
outline: none; outline: none;
} }

99
src/components/modals/ShareAnalytics.js

@ -0,0 +1,99 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import { MODAL_SHARE_ANALYTICS } from 'config/constants'
import Modal, { ModalBody, ModalTitle, ModalContent, ModalFooter } from 'components/base/Modal'
import Button from 'components/base/Button'
import Box from 'components/base/Box'
import type { T } from 'types/common'
type Props = {
t: T,
}
class ShareAnalytics extends PureComponent<Props, *> {
render() {
const { t } = this.props
const items = [
{
key: 'item1',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item1'),
},
{
key: 'item2',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item2'),
},
{
key: 'item3',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item3'),
},
{
key: 'item4',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item4'),
},
{
key: 'item5',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item5'),
},
{
key: 'item6',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item6'),
},
{
key: 'item7',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item7'),
},
{
key: 'item8',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item8'),
},
{
key: 'item9',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item9'),
},
{
key: 'item10',
desc: t('onboarding:analytics.shareAnalytics.mandatoryContextual.item10'),
},
]
return (
<Modal
name={MODAL_SHARE_ANALYTICS}
render={({ onClose }) => (
<ModalBody onClose={onClose}>
<ModalTitle>{t('onboarding:analytics.shareAnalytics.title')}</ModalTitle>
<InlineDesc>{t('onboarding:analytics.shareAnalytics.desc')}</InlineDesc>
<ModalContent mx={5}>
<Ul>{items.map(item => <li key={item.key}>{item.desc}</li>)}</Ul>
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end">
<Button onClick={onClose} primary>
{t('app:common.close')}
</Button>
</ModalFooter>
</ModalBody>
)}
/>
)
}
}
export default translate()(ShareAnalytics)
export const Ul = styled.ul.attrs({
ff: 'Open Sans|Regular',
})`
margin-top: 15px;
font-size: 13px;
color: ${p => p.theme.colors.graphite};
line-height: 1.69;
`
export const InlineDesc = styled(Box).attrs({
ff: 'Open Sans|SemiBold',
fontSize: 4,
color: 'dark',
mx: '45px',
})``

71
src/components/modals/TechnicalData.js

@ -0,0 +1,71 @@
// @flow
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import { MODAL_TECHNICAL_DATA } from 'config/constants'
import Modal, { ModalBody, ModalTitle, ModalContent, ModalFooter } from 'components/base/Modal'
import Button from 'components/base/Button'
import type { T } from 'types/common'
import { Ul, InlineDesc } from './ShareAnalytics'
type Props = {
t: T,
}
class TechnicalData extends PureComponent<Props, *> {
render() {
const { t } = this.props
const items = [
{
key: 'item1',
desc: t('onboarding:analytics.technicalData.mandatoryContextual.item1'),
},
{
key: 'item2',
desc: t('onboarding:analytics.technicalData.mandatoryContextual.item2'),
},
{
key: 'item3',
desc: t('onboarding:analytics.technicalData.mandatoryContextual.item3'),
},
{
key: 'item4',
desc: t('onboarding:analytics.technicalData.mandatoryContextual.item4'),
},
{
key: 'item5',
desc: t('onboarding:analytics.technicalData.mandatoryContextual.item5'),
},
{
key: 'item6',
desc: t('onboarding:analytics.technicalData.mandatoryContextual.item6'),
},
]
return (
<Modal
name={MODAL_TECHNICAL_DATA}
render={({ onClose }) => (
<ModalBody onClose={onClose}>
<ModalTitle>
{t('onboarding:analytics.technicalData.mandatoryContextual.title')}
</ModalTitle>
<InlineDesc>{t('onboarding:analytics.technicalData.desc')}</InlineDesc>
<ModalContent mx={5}>
<Ul>{items.map(item => <li key={item.key}>{item.desc}</li>)}</Ul>
</ModalContent>
<ModalFooter horizontal justifyContent="flex-end">
<Button onClick={onClose} primary>
{t('app:common.close')}
</Button>
</ModalFooter>
</ModalBody>
)}
/>
)
}
}
export default translate()(TechnicalData)

2
src/config/constants.js

@ -96,6 +96,8 @@ export const MODAL_RECEIVE = 'MODAL_RECEIVE'
export const MODAL_SEND = 'MODAL_SEND' export const MODAL_SEND = 'MODAL_SEND'
export const MODAL_SETTINGS_ACCOUNT = 'MODAL_SETTINGS_ACCOUNT' export const MODAL_SETTINGS_ACCOUNT = 'MODAL_SETTINGS_ACCOUNT'
export const MODAL_RELEASES_NOTES = 'MODAL_RELEASES_NOTES' export const MODAL_RELEASES_NOTES = 'MODAL_RELEASES_NOTES'
export const MODAL_SHARE_ANALYTICS = 'MODAL_SHARE_ANALYTICS'
export const MODAL_TECHNICAL_DATA = 'MODAL_TECHNICAL_DATA'
export const MODAL_DISCLAIMER = 'MODAL_DISCLAIMER' export const MODAL_DISCLAIMER = 'MODAL_DISCLAIMER'
export const MODAL_DISCLAIMER_DELAY = 1 * 1000 export const MODAL_DISCLAIMER_DELAY = 1 * 1000

1
static/i18n/en/app.yml

@ -7,6 +7,7 @@ common:
cancel: Cancel cancel: Cancel
delete: Delete delete: Delete
continue: Continue continue: Continue
learnMore: Learn More
skipThisStep: Skip this step skipThisStep: Skip this step
chooseWalletPlaceholder: Choose a wallet... chooseWalletPlaceholder: Choose a wallet...
currency: Currency currency: Currency

26
static/i18n/en/onboarding.yml

@ -131,12 +131,32 @@ analytics:
shareAnalytics: shareAnalytics:
title: Share usage data title: Share usage data
desc: Enable analytics of anonymous data to help Ledger improve the user experience. This includes the operating system, language, firmware versions and the number of added accounts. desc: Enable analytics of anonymous data to help Ledger improve the user experience. This includes the operating system, language, firmware versions and the number of added accounts.
mandatoryContextual:
item1: Page visits
item2: Actions (send, receive, logout)
item3: Clicks
item4: Redirections to webpages
item5: Scrolled to end of page
item6: Install/Uninstall
item7: Number of accounts, currencies and operations
item8: Overall and page session duration
item9: Device product ID
item10: Device firmware and app versions
sentryLogs: sentryLogs:
title: Report bugs title: Report bugs
desc: Automatically send reports to help Ledger fix bugs desc: Automatically send reports to help Ledger fix bugs
# mandatoryContextual: technicalData:
# title: Technical data title: Technical data *
# desc: Ledger will automatically collect technical information to help improve user experience. This information is fully anonymized. desc: Ledger will automatically collect technical information to help improve user experience. This information is fully anonymized.
mandatoryText: '* mandatory'
mandatoryContextual:
title: Technical data
item1: Active unique users
item2: OS name
item3: OS versions
item4: Ledger Live application version
item5: App Language/Region
item6: OS Language/Region
finish: finish:
title: Your device is ready! title: Your device is ready!
desc: Proceed to your portfolio and start adding your accounts... desc: Proceed to your portfolio and start adding your accounts...

Loading…
Cancel
Save