Browse Source

Merge pull request #840 from gre/fix-analytics-events

Use more properties instead of context
master
Gaëtan Renaudeau 7 years ago
committed by GitHub
parent
commit
de02be7342
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 44
      src/analytics/segment.js
  2. 2
      src/components/DashboardPage/AccountsOrder.js
  3. 6
      src/components/ExchangePage/ExchangeCard.js
  4. 1
      src/components/IsUnlocked.js
  5. 8
      src/components/Onboarding/steps/Finish.js
  6. 4
      src/components/Onboarding/steps/GenuineCheck/index.js
  7. 8
      src/components/Onboarding/steps/NoDevice.js
  8. 2
      src/components/OperationsList/index.js
  9. 24
      src/components/PillsDaysCount.js
  10. 6
      src/components/RenderError.js
  11. 37
      src/components/SelectExchange.js
  12. 4
      src/components/SettingsPage/AboutRowItem.js
  13. 1
      src/components/SettingsPage/CleanButton.js
  14. 24
      src/components/SettingsPage/CounterValueExchangeSelect.js
  15. 3
      src/components/SettingsPage/CounterValueSelect.js
  16. 6
      src/components/SettingsPage/LanguageSelect.js
  17. 8
      src/components/SettingsPage/MarketIndicatorRadio.js
  18. 2
      src/components/SettingsPage/RegionSelect.js
  19. 4
      src/components/SettingsPage/ReleaseNotesButton.js
  20. 1
      src/components/SettingsPage/ResetButton.js
  21. 2
      src/components/SettingsPage/sections/Currencies.js
  22. 2
      src/components/SettingsPage/sections/CurrencyRows.js
  23. 2
      src/components/StickyBackToTop.js
  24. 2
      src/components/TopBar/ActivityIndicator.js
  25. 4
      src/components/base/Modal/ConfirmModal.js
  26. 1
      src/components/base/Modal/stories.js
  27. 12
      src/components/modals/AccountSettingRenderBody.js
  28. 6
      src/components/modals/OperationDetails.js
  29. 2
      src/components/modals/ReleaseNotes.js
  30. 2
      src/components/modals/UpdateFirmware/Disclaimer.js
  31. 2
      src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js
  32. 2
      src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js
  33. 2
      src/components/modals/UpdateFirmware/steps/03-step-confirmation.js
  34. 12
      src/helpers/linking.js

44
src/analytics/segment.js

@ -16,12 +16,15 @@ if (!process.env.STORYBOOK_ENV) {
const sessionId = uuid()
const getContext = store => {
const getContext = _store => ({
ip: '0.0.0.0',
})
const extraProperties = store => {
const state = store.getState()
const { language, region } = langAndRegionSelector(state)
const systemLocale = getSystemLocale()
return {
ip: '0.0.0.0',
appVersion: __APP_VERSION__,
language,
region,
@ -45,13 +48,9 @@ export const start = (store: *) => {
return
}
load()
analytics.identify(
id,
{},
{
context: getContext(store),
},
)
analytics.identify(id, extraProperties(store), {
context: getContext(store),
})
}
export const stop = () => {
@ -75,9 +74,16 @@ export const track = (event: string, properties: ?Object) => {
logger.error('analytics is not available')
return
}
analytics.track(event, properties, {
context: getContext(storeInstance),
})
analytics.track(
event,
{
...extraProperties(storeInstance),
...properties,
},
{
context: getContext(storeInstance),
},
)
}
export const page = (category: string, name: ?string, properties: ?Object) => {
@ -90,7 +96,15 @@ export const page = (category: string, name: ?string, properties: ?Object) => {
logger.error('analytics is not available')
return
}
analytics.page(category, name, properties, {
context: getContext(storeInstance),
})
analytics.page(
category,
name,
{
...extraProperties(storeInstance),
...properties,
},
{
context: getContext(storeInstance),
},
)
}

2
src/components/DashboardPage/AccountsOrder.js

@ -21,6 +21,7 @@ import { reorderAccounts } from 'actions/accounts'
import { accountsSelector } from 'reducers/accounts'
import { saveSettings } from 'actions/settings'
import Track from 'analytics/Track'
import BoldToggle from 'components/base/BoldToggle'
import Box from 'components/base/Box'
import DropDown, { DropDownItem } from 'components/base/DropDown'
@ -202,6 +203,7 @@ class AccountsOrder extends Component<Props> {
onStateChange={this.onStateChange}
value={sortItems.find(item => item.key === orderAccounts)}
>
<Track onUpdate event="ChangeSort" orderAccounts={orderAccounts} />
<Text ff="Open Sans|SemiBold" fontSize={4}>
{t('app:common.sortBy')}
</Text>

6
src/components/ExchangePage/ExchangeCard.js

@ -1,8 +1,7 @@
// @flow
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import { track } from 'analytics/segment'
import { openURL } from 'helpers/linking'
import type { T } from 'types/common'
@ -19,8 +18,7 @@ type CardType = {
export default class ExchangeCard extends PureComponent<{ t: T, card: CardType }> {
onClick = () => {
const { card } = this.props
shell.openExternal(card.url)
track('VisitExchange', { id: card.id, url: card.url })
openURL(card.url, 'VisitExchange', { id: card.id })
}
render() {
const {

1
src/components/IsUnlocked.js

@ -186,6 +186,7 @@ class IsUnlocked extends Component<Props, State> {
</Box>
</form>
<ConfirmModal
analyticsName="HardReset"
isDanger
isLoading={isHardResetting}
isOpened={isHardResetModalOpened}

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

@ -1,7 +1,7 @@
// @flow
import React, { Component } from 'react'
import { shell } from 'electron'
import { openURL } from 'helpers/linking'
import styled from 'styled-components'
import { i } from 'helpers/staticPath'
import { urls } from 'config/support'
@ -35,19 +35,19 @@ const socialMedia = [
key: 'twitter',
url: urls.twitter,
icon: <IconSocialTwitter size={24} />,
onClick: url => shell.openExternal(url),
onClick: url => openURL(url),
},
{
key: 'github',
url: urls.github,
icon: <IconSocialGithub size={24} />,
onClick: url => shell.openExternal(url),
onClick: url => openURL(url),
},
{
key: 'reddit',
url: urls.reddit,
icon: <IconSocialReddit size={24} />,
onClick: url => shell.openExternal(url),
onClick: url => openURL(url),
},
]

4
src/components/Onboarding/steps/GenuineCheck/index.js

@ -1,7 +1,7 @@
// @flow
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import { openURL } from 'helpers/linking'
import { connect } from 'react-redux'
import styled from 'styled-components'
import { colors } from 'styles/theme'
@ -144,7 +144,7 @@ class GenuineCheck extends PureComponent<StepProps, State> {
}
contactSupport = () => {
shell.openExternal(urls.genuineCheckContactSupport)
openURL(urls.genuineCheckContactSupport)
}
handlePrevStep = () => {

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

@ -1,7 +1,7 @@
// @flow
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import { openURL } from 'helpers/linking'
import { i } from 'helpers/staticPath'
import Box from 'components/base/Box'
@ -27,7 +27,7 @@ class NoDevice extends PureComponent<StepProps, *> {
icon: <IconCart size={20} />,
title: t('onboarding:noDevice.buyNew.title'),
onClick: () => {
shell.openExternal(urls.noDeviceBuyNew)
openURL(urls.noDeviceBuyNew)
},
},
{
@ -35,7 +35,7 @@ class NoDevice extends PureComponent<StepProps, *> {
icon: <IconTruck size={20} />,
title: t('onboarding:noDevice.trackOrder.title'),
onClick: () => {
shell.openExternal(urls.noDeviceTrackOrder)
openURL(urls.noDeviceTrackOrder)
},
},
{
@ -43,7 +43,7 @@ class NoDevice extends PureComponent<StepProps, *> {
icon: <IconInfoCircle size={20} />,
title: t('onboarding:noDevice.learnMore.title'),
onClick: () => {
shell.openExternal(urls.noDeviceLearnMore)
openURL(urls.noDeviceLearnMore)
},
},
]

2
src/components/OperationsList/index.js

@ -25,6 +25,7 @@ import IconAngleDown from 'icons/AngleDown'
import Box, { Card } from 'components/base/Box'
import Text from 'components/base/Text'
import Track from 'analytics/Track'
import { track } from 'analytics/segment'
import SectionTitle from './SectionTitle'
import OperationC from './Operation'
@ -81,6 +82,7 @@ export class OperationsList extends PureComponent<Props, State> {
// TODO: convert of async/await if fetching with the api
fetchMoreOperations = () => {
track('FetchMoreOperations')
this.setState({ nbToShow: this.state.nbToShow + 20 })
}

24
src/components/PillsDaysCount.js

@ -1,11 +1,12 @@
// @flow
import React, { PureComponent } from 'react'
import React, { Fragment, PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import Pills from 'components/base/Pills'
import { timeRangeDaysByKey } from 'reducers/settings'
import type { TimeRange } from 'reducers/settings'
import Track from 'analytics/Track'
type Props = {
selected: string,
@ -17,15 +18,18 @@ class PillsDaysCount extends PureComponent<Props> {
render() {
const { selected, onChange, t } = this.props
return (
<Pills
items={Object.keys(timeRangeDaysByKey).map((key: TimeRange) => ({
key,
value: timeRangeDaysByKey[key],
label: t(`app:time.${key}`),
}))}
activeKey={selected}
onChange={onChange}
/>
<Fragment>
<Track onUpdate event="PillsDaysChange" selected={selected} />
<Pills
items={Object.keys(timeRangeDaysByKey).map((key: TimeRange) => ({
key,
value: timeRangeDaysByKey[key],
label: t(`app:time.${key}`),
}))}
activeKey={selected}
onChange={onChange}
/>
</Fragment>
)
}
}

6
src/components/RenderError.js

@ -2,7 +2,8 @@
import React, { PureComponent } from 'react'
import styled from 'styled-components'
import { shell, remote } from 'electron'
import { openURL } from 'helpers/linking'
import { remote } from 'electron'
import qs from 'querystring'
import { translate } from 'react-i18next'
@ -60,7 +61,7 @@ ${error.stack}
\`\`\`
`,
})
shell.openExternal(`https://github.com/LedgerHQ/ledger-live-desktop/issues/new?${q}`)
openURL(`https://github.com/LedgerHQ/ledger-live-desktop/issues/new?${q}`)
}
handleRestart = () => {
@ -112,6 +113,7 @@ ${error.stack}
</Button>
</Box>
<ConfirmModal
analyticsName="HardReset"
isDanger
isLoading={isHardResetting}
isOpened={isHardResetModalOpened}

37
src/components/SelectExchange.js

@ -1,11 +1,12 @@
// @flow
import React, { Component } from 'react'
import React, { Fragment, Component } from 'react'
import { translate } from 'react-i18next'
import LRU from 'lru-cache'
import type { Currency } from '@ledgerhq/live-common/lib/types'
import type { Exchange } from '@ledgerhq/live-common/lib/countervalues/types'
import logger from 'logger'
import Track from 'analytics/Track'
import Select from 'components/base/Select'
import Text from 'components/base/Text'
import CounterValues from 'helpers/countervalues'
@ -91,27 +92,37 @@ class SelectExchange extends Component<
}
render() {
const { onChange, exchangeId, style, t, ...props } = this.props
const { onChange, exchangeId, style, t, from, to, ...props } = this.props
const { exchanges, error } = this.state
const options = exchanges ? exchanges.map(e => ({ value: e.id, label: e.name, ...e })) : []
const value = options.find(e => e.id === exchangeId)
return error ? (
<Text ff="Open Sans|SemiBold" color="dark" fontSize={4}>
{t('app:common.error.load')}
</Text>
) : (
<Select
value={options.find(e => e.id === exchangeId)}
options={options}
onChange={onChange}
isLoading={options.length === 0}
placeholder={t('app:common.selectExchange')}
noOptionsMessage={({ inputValue }) =>
t('app:common.selectExchangeNoOption', { exchangeName: inputValue })
}
{...props}
/>
<Fragment>
<Track
onUpdate
event="SelectExchange"
exchangeName={value && value.id}
fromCurrency={from.ticker}
toCurrency={to.ticker}
/>
<Select
value={value}
options={options}
onChange={onChange}
isLoading={options.length === 0}
placeholder={t('app:common.selectExchange')}
noOptionsMessage={({ inputValue }) =>
t('app:common.selectExchangeNoOption', { exchangeName: inputValue })
}
{...props}
/>
</Fragment>
)
}
}

4
src/components/SettingsPage/AboutRowItem.js

@ -1,6 +1,6 @@
// @flow
import React, { PureComponent } from 'react'
import { shell } from 'electron'
import { openURL } from 'helpers/linking'
import IconExternalLink from 'icons/ExternalLink'
import { Tabbable } from 'components/base/Box'
import { SettingsSectionRow } from './SettingsSection'
@ -10,7 +10,7 @@ export default class AboutRowItem extends PureComponent<{
title: string,
desc: string,
}> {
onClick = () => shell.openExternal(this.props.url)
onClick = () => openURL(this.props.url)
render() {
const { title, desc } = this.props

1
src/components/SettingsPage/CleanButton.js

@ -50,6 +50,7 @@ class CleanButton extends PureComponent<Props, State> {
</Button>
<ConfirmModal
analyticsName="CleanCache"
isDanger
isOpened={opened}
onClose={this.close}

24
src/components/SettingsPage/CounterValueExchangeSelect.js

@ -11,6 +11,7 @@ import {
import { setCounterValueExchange } from 'actions/settings'
import type { Currency } from '@ledgerhq/live-common/lib/types'
import SelectExchange from 'components/SelectExchange'
import Track from 'analytics/Track'
type Props = {
counterValueCurrency: Currency,
@ -25,20 +26,19 @@ class CounterValueExchangeSelect extends PureComponent<Props> {
render() {
const { counterValueCurrency, counterValueExchange } = this.props
return (
return counterValueCurrency ? (
<Fragment>
{counterValueCurrency ? (
<SelectExchange
small
from={intermediaryCurrency}
to={counterValueCurrency}
exchangeId={counterValueExchange}
onChange={this.handleChangeExchange}
minWidth={200}
/>
) : null}
<Track onUpdate event="CounterValueExchangeSelect" exchangeId={counterValueExchange} />
<SelectExchange
small
from={intermediaryCurrency}
to={counterValueCurrency}
exchangeId={counterValueExchange}
onChange={this.handleChangeExchange}
minWidth={200}
/>
</Fragment>
)
) : null
}
}

3
src/components/SettingsPage/CounterValueSelect.js

@ -8,6 +8,7 @@ import type { Currency } from '@ledgerhq/live-common/lib/types'
import { setCounterValue } from 'actions/settings'
import { counterValueCurrencySelector } from 'reducers/settings'
import Select from 'components/base/Select'
import Track from 'analytics/Track'
const fiats = listFiatCurrencies()
.map(f => f.units[0])
@ -35,7 +36,7 @@ class CounterValueSelect extends PureComponent<Props> {
return (
<Fragment>
{/* TODO Track */}
<Track onUpdate event="CounterValueSelect" counterValue={cvOption && cvOption.value} />
<Select
small
minWidth={250}

6
src/components/SettingsPage/LanguageSelect.js

@ -8,6 +8,7 @@ import { connect } from 'react-redux'
import { setLanguage } from 'actions/settings'
import { langAndRegionSelector } from 'reducers/settings'
import languageKeys from 'config/languages'
import Track from 'analytics/Track'
import Select from 'components/base/Select'
type Props = {
@ -37,6 +38,11 @@ class LanguageSelect extends PureComponent<Props> {
: this.languages.find(l => l.value === language)
return (
<Fragment>
<Track
onUpdate
event="LanguageSelect"
currentRegion={currentLanguage && currentLanguage.value}
/>
<Select
small
minWidth={250}

8
src/components/SettingsPage/MarketIndicatorRadio.js

@ -1,6 +1,6 @@
// @flow
import React, { PureComponent } from 'react'
import React, { Fragment, PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import { connect } from 'react-redux'
@ -8,6 +8,7 @@ import { createStructuredSelector } from 'reselect'
import { setMarketIndicator } from 'actions/settings'
import { marketIndicatorSelector } from 'reducers/settings'
import RadioGroup from 'components/base/RadioGroup'
import Track from 'analytics/Track'
type Props = {
t: T,
@ -35,7 +36,10 @@ class MarketIndicatorRadio extends PureComponent<Props> {
render() {
const { marketIndicator } = this.props
return (
<RadioGroup items={this.indicators} activeKey={marketIndicator} onChange={this.onChange} />
<Fragment>
<Track onUpdate event="MarketIndicatorRadio" marketIndicator={marketIndicator} />
<RadioGroup items={this.indicators} activeKey={marketIndicator} onChange={this.onChange} />
</Fragment>
)
}
}

2
src/components/SettingsPage/RegionSelect.js

@ -8,6 +8,7 @@ import { langAndRegionSelector, counterValueCurrencySelector } from 'reducers/se
import type { Currency } from '@ledgerhq/live-common/lib/types'
import type { T } from 'types/common'
import Track from 'analytics/Track'
import regionsByKey from 'helpers/regions.json'
import Select from 'components/base/Select'
@ -39,6 +40,7 @@ class RegionSelect extends PureComponent<Props> {
return (
<Fragment>
<Track onUpdate event="RegionSelectChange" currentRegion={currentRegion.region} />
<Select
small
minWidth={250}

4
src/components/SettingsPage/ReleaseNotesButton.js

@ -3,7 +3,7 @@
import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'
import type { T } from 'types/common'
import { shell } from 'electron'
import { openURL } from 'helpers/linking'
import { connect } from 'react-redux'
import { openModal } from 'reducers/modals'
import { MODAL_RELEASES_NOTES } from 'config/constants'
@ -19,7 +19,7 @@ const mapDispatchToProps = {
}
class ReleaseNotesButton extends PureComponent<Props> {
handleOpenLink = (url: string) => shell.openExternal(url)
handleOpenLink = (url: string) => openURL(url)
render() {
const { t, openModal } = this.props

1
src/components/SettingsPage/ResetButton.js

@ -49,6 +49,7 @@ class ResetButton extends PureComponent<Props, State> {
</Button>
<ConfirmModal
analyticsName="HardReset"
isDanger
isLoading={pending}
isOpened={opened}

2
src/components/SettingsPage/sections/Currencies.js

@ -44,7 +44,7 @@ class TabCurrencies extends PureComponent<Props, State> {
const { t, currencies } = this.props
return (
<Section key={currency.id}>
<TrackPage category="Settings" name="Currencies" />
<TrackPage category="Settings" name="Currencies" currencyId={currency.id} />
<Header
icon={<IconCurrencies size={16} />}
title={t('app:settings.tabs.currencies')}

2
src/components/SettingsPage/sections/CurrencyRows.js

@ -12,6 +12,7 @@ import type { SettingsState, CurrencySettings } from 'reducers/settings'
import { currencySettingsDefaults } from 'helpers/SettingsDefaults'
import StepperNumber from 'components/base/StepperNumber'
import ExchangeSelect from 'components/SelectExchange'
import Track from 'analytics/Track'
import { SettingsSectionRow as Row } from '../SettingsSection'
@ -87,6 +88,7 @@ class CurrencyRows extends PureComponent<Props> {
title={t('app:settings.currencies.confirmationsNb')}
desc={t('app:settings.currencies.confirmationsNbDesc')}
>
<Track onUpdate event="ConfirmationsNb" confirmationsNb={confirmationsNb} />
<StepperNumber
min={defaults.confirmationsNb.min}
max={defaults.confirmationsNb.max}

2
src/components/StickyBackToTop.js

@ -3,6 +3,7 @@ import React, { PureComponent } from 'react'
import ReactDOM from 'react-dom'
import styled from 'styled-components'
import smoothscroll from 'smoothscroll-polyfill'
import { track } from 'analytics/segment'
import Box from 'components/base/Box'
import AngleUp from 'icons/AngleUp'
import { GrowScrollContext } from './base/GrowScroll'
@ -79,6 +80,7 @@ class StickyBackToTop extends PureComponent<Props, State> {
if (scrollContainer) {
// $FlowFixMe seems to be missing in flow
scrollContainer.scrollTo({ top: 0, behavior: 'smooth' })
track('ScrollBackToTop')
}
}

2
src/components/TopBar/ActivityIndicator.js

@ -9,6 +9,7 @@ import { translate } from 'react-i18next'
import type { T } from 'types/common'
import type { AsyncState } from 'reducers/bridgeSync'
import { track } from 'analytics/segment'
import { globalSyncStateSelector } from 'reducers/bridgeSync'
import { isUpToDateSelector } from 'reducers/accounts'
import { BridgeSyncConsumer } from 'bridge/BridgeSyncContext'
@ -47,6 +48,7 @@ class ActivityIndicatorInner extends PureComponent<Props, { lastClickTime: numbe
this.props.cvPoll()
this.props.setSyncBehavior({ type: 'SYNC_ALL_ACCOUNTS', priority: 5 })
this.setState({ lastClickTime: Date.now() })
track('SyncRefreshClick')
}
render() {

4
src/components/base/Modal/ConfirmModal.js

@ -5,6 +5,7 @@ import { translate } from 'react-i18next'
import type { T } from 'types/common'
import TrackPage from 'analytics/TrackPage'
import Button from 'components/base/Button'
import Box from 'components/base/Box'
@ -23,6 +24,7 @@ type Props = {
onConfirm: Function,
t: T,
isLoading?: boolean,
analyticsName: string,
}
class ConfirmModal extends PureComponent<Props> {
@ -40,6 +42,7 @@ class ConfirmModal extends PureComponent<Props> {
isLoading,
renderIcon,
t,
analyticsName,
...props
} = this.props
@ -52,6 +55,7 @@ class ConfirmModal extends PureComponent<Props> {
{...props}
render={({ onClose }) => (
<ModalBody onClose={isLoading ? undefined : onClose}>
<TrackPage category="Modal" name={analyticsName} />
<ModalTitle>{title}</ModalTitle>
<ModalContent>
{subTitle && (

1
src/components/base/Modal/stories.js

@ -36,6 +36,7 @@ stories.add('Modal', () => (
stories.add('ConfirmModal', () => (
<ConfirmModal
categoryName=""
isOpened
isDanger={boolean('isDanger', false)}
title={text('title', 'Hard reset')}

12
src/components/modals/AccountSettingRenderBody.js

@ -17,6 +17,7 @@ import { setDataModal } from 'reducers/modals'
import { getBridgeForCurrency } from 'bridge'
import TrackPage from 'analytics/TrackPage'
import Spoiler from 'components/base/Spoiler'
import CryptoCurrencyIcon from 'components/CryptoCurrencyIcon'
import Box from 'components/base/Box'
@ -197,6 +198,7 @@ class HelperComp extends PureComponent<Props, State> {
return (
<ModalBody onClose={onClose}>
<form onSubmit={this.handleSubmit(account, onClose)}>
<TrackPage category="Modal" name="AccountSettings" />
<ModalTitle>{t('app:account.settings.title')}</ModalTitle>
<ModalContent mb={3}>
<Container>
@ -275,15 +277,21 @@ class HelperComp extends PureComponent<Props, State> {
</Spoiler>
</ModalContent>
<ModalFooter horizontal>
<Button danger type="button" onClick={this.handleOpenRemoveAccountModal}>
<Button
event="OpenAccountDelete"
danger
type="button"
onClick={this.handleOpenRemoveAccountModal}
>
{t('app:common.delete')}
</Button>
<Button ml="auto" type="submit" primary>
<Button event="DoneEditingAccount" ml="auto" type="submit" primary>
{t('app:common.apply')}
</Button>
</ModalFooter>
</form>
<ConfirmModal
analyticsName="RemoveAccount"
isDanger
isOpened={isRemoveAccountModalOpen}
onClose={this.handleCloseRemoveAccountModal}

6
src/components/modals/OperationDetails.js

@ -2,13 +2,14 @@
import React, { Fragment, Component } from 'react'
import { connect } from 'react-redux'
import { shell } from 'electron'
import { openURL } from 'helpers/linking'
import { translate } from 'react-i18next'
import styled from 'styled-components'
import moment from 'moment'
import { getOperationAmountNumber } from '@ledgerhq/live-common/lib/helpers/operation'
import { getAccountOperationExplorer } from '@ledgerhq/live-common/lib/explorers'
import TrackPage from 'analytics/TrackPage'
import type { Account, Operation } from '@ledgerhq/live-common/lib/types'
import type { T, CurrencySettings } from 'types/common'
@ -128,6 +129,7 @@ const OperationDetails = connect(mapStateToProps)((props: Props) => {
return (
<ModalBody onClose={onClose}>
<TrackPage category="Modal" name="OperationDetails" />
<ModalTitle>{t('app:operationDetails.title')}</ModalTitle>
<ModalContent relative style={{ height: 500 }} px={0} pb={0}>
<GrowScroll px={5} pt={1} pb={8}>
@ -229,7 +231,7 @@ const OperationDetails = connect(mapStateToProps)((props: Props) => {
{url && (
<ModalFooter horizontal justify="flex-end" flow={2}>
<Button primary onClick={() => shell.openExternal(url)}>
<Button primary onClick={() => openURL(url)}>
{t('app:operationDetails.viewOperation')}
</Button>
</ModalFooter>

2
src/components/modals/ReleaseNotes.js

@ -14,6 +14,7 @@ import GrowScroll from 'components/base/GrowScroll'
import Text from 'components/base/Text'
import Spinner from 'components/base/Spinner'
import GradientBox from 'components/GradientBox'
import TrackPage from 'analytics/TrackPage'
import type { T } from 'types/common'
@ -220,6 +221,7 @@ class ReleaseNotes extends PureComponent<Props, State> {
return (
<ModalBody onClose={onClose}>
<TrackPage category="Modal" name="ReleaseNotes" />
<ModalTitle>{t('app:releaseNotes.title')}</ModalTitle>
<ModalContent relative style={{ height: 500 }} px={0} pb={0}>
<GrowScroll px={5} pb={8}>

2
src/components/modals/UpdateFirmware/Disclaimer.js

@ -13,6 +13,7 @@ import Button from 'components/base/Button'
import GrowScroll from 'components/base/GrowScroll'
import GradientBox from 'components/GradientBox'
import { Notes } from 'components/modals/ReleaseNotes'
import TrackPage from 'analytics/TrackPage'
import type { ModalStatus } from 'components/ManagerPage/FirmwareUpdate'
@ -42,6 +43,7 @@ class DisclaimerModal extends PureComponent<Props, State> {
onClose={onClose}
render={({ onClose }) => (
<ModalBody onClose={onClose} grow align="center" justify="center" mt={3}>
<TrackPage category="Manager" name="DisclaimerModal" />
<Fragment>
<ModalTitle>{t('app:manager.firmware.update')}</ModalTitle>
<ModalContent>

2
src/components/modals/UpdateFirmware/steps/01-step-install-full-firmware.js

@ -11,6 +11,7 @@ import getDeviceInfo from 'commands/getDeviceInfo'
import { getCurrentDevice } from 'reducers/devices'
import { createCancelablePolling, delay } from 'helpers/promise'
import TrackPage from 'analytics/TrackPage'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import Progress from 'components/base/Progress'
@ -169,6 +170,7 @@ class StepFullFirmwareInstall extends PureComponent<Props, State> {
? t('app:manager.modal.installing')
: t('app:manager.modal.confirmIdentifier')}
</Title>
<TrackPage category="Manager" name="InstallFirmware" />
{this.renderBody()}
</Container>
)

2
src/components/modals/UpdateFirmware/steps/02-step-flash-mcu.js

@ -11,6 +11,7 @@ import { getCurrentDevice } from 'reducers/devices'
import { createCancelablePolling } from 'helpers/promise'
import getDeviceInfo from 'commands/getDeviceInfo'
import TrackPage from 'analytics/TrackPage'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import Progress from 'components/base/Progress'
@ -186,6 +187,7 @@ class StepFlashMcu extends PureComponent<Props, State> {
<Title>
{installing ? t('app:manager.modal.flashing') : t('app:manager.modal.mcuTitle')}
</Title>
<TrackPage category="Manager" name="FlashMCU" />
{this.renderBody()}
</Container>
)

2
src/components/modals/UpdateFirmware/steps/03-step-confirmation.js

@ -3,6 +3,7 @@
import React from 'react'
import styled from 'styled-components'
import TrackPage from 'analytics/TrackPage'
import Box from 'components/base/Box'
import Text from 'components/base/Text'
import Button from 'components/base/Button'
@ -27,6 +28,7 @@ const Title = styled(Box).attrs({
function StepConfirmation({ t }: StepProps) {
return (
<Container>
<TrackPage category="Manager" name="FirmwareConfirmation" />
<Box mx={7} color="positiveGreen" my={4}>
<CheckCircle size={44} />
</Box>

12
src/helpers/linking.js

@ -0,0 +1,12 @@
// @flow
import { shell } from 'electron'
import { track } from 'analytics/segment'
export const openURL = (
url: string,
customEventName: string = 'OpenURL',
extraParams: Object = {},
) => {
track(customEventName, { ...extraParams, url })
shell.openExternal(url)
}
Loading…
Cancel
Save