From b49148ec54886b11042e42eed9ad4e8793840775 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 24 May 2018 10:11:56 -0700 Subject: Implement metamask installation flow --- .../ts/components/onboarding/onboarding_flow.tsx | 7 +++ .../onboarding/portal_onboarding_flow.tsx | 60 ++++++++++++++++++---- .../ts/components/top_bar/provider_display.tsx | 9 ++-- .../components/wallet/wallet_disconnected_item.tsx | 4 +- .../ts/containers/portal_onboarding_flow.ts | 10 +++- packages/website/ts/utils/utils.ts | 4 ++ 6 files changed, 75 insertions(+), 19 deletions(-) diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 621d14260..22fc71481 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -17,9 +17,16 @@ const joyrideStyleOptions: StyleOptions = { // Wrapper around Joyride with defaults and styles set export class OnboardingFlow extends React.Component { + private _joyrideRef: React.RefObject; + constructor(props: OnboardingFlowProps) { + super(props); + this._joyrideRef = React.createRef(); + } + public render(): React.ReactNode { return ( void; + userAddress: string; + providerType: ProviderType; + injectedProviderName: string; + blockchainIsLoaded: boolean; + setOnboardingStep: (stepIndex: number) => void; } -const steps: Step[] = [ - { - target: '.wallet', - content: 'You are onboarding right now!', - placement: 'right', - disableBeacon: true, - }, -]; - export class PortalOnboardingFlow extends React.Component { public render(): React.ReactNode { return ( ); } + + private _isAddressAvailable(): boolean { + return !_.isEmpty(this.props.userAddress); + } + + private _getSteps(): Step[] { + const allSteps: Step[] = [ + { + target: '.wallet', + content: + 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps', + placement: 'right', + disableBeacon: true, + }, + { + target: '.wallet', + content: 'Unlock your metamask extension to begin', + placement: 'right', + disableBeacon: true, + }, + { + target: '.wallet', + content: + 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', + placement: 'right', + disableBeacon: true, + }, + ]; + const [noMetamaskStep, lockedMetamaskStep, ...restOfSteps] = allSteps; + if (this._isAddressAvailable()) { + return restOfSteps; + } + const isExternallyInjected = utils.isExternallyInjected( + this.props.providerType, + this.props.injectedProviderName, + ); + if (isExternallyInjected) { + return [lockedMetamaskStep, ...restOfSteps]; + } + return allSteps; + } } diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx index fc516882a..4dc37f231 100644 --- a/packages/website/ts/components/top_bar/provider_display.tsx +++ b/packages/website/ts/components/top_bar/provider_display.tsx @@ -39,8 +39,7 @@ const styles: Styles = { export class ProviderDisplay extends React.Component { public render(): React.ReactNode { const isAddressAvailable = !_.isEmpty(this.props.userAddress); - const isExternallyInjectedProvider = - this.props.providerType === ProviderType.Injected && this.props.injectedProviderName !== '0x Public'; + const isExternallyInjectedProvider = utils.isExternallyInjected(this.props.providerType, this.props.injectedProviderName); const displayAddress = isAddressAvailable ? utils.getAddressBeginAndEnd(this.props.userAddress) : isExternallyInjectedProvider @@ -69,15 +68,13 @@ export class ProviderDisplay extends React.Component ); - const hasInjectedProvider = - this.props.injectedProviderName !== '0x Public' && this.props.providerType === ProviderType.Injected; const hasLedgerProvider = this.props.providerType === ProviderType.Ledger; - const horizontalPosition = hasInjectedProvider || hasLedgerProvider ? 'left' : 'middle'; + const horizontalPosition = isExternallyInjectedProvider || hasLedgerProvider ? 'left' : 'middle'; return (
= ( props: WalletDisconnectedItemProps, ) => { - const isExternallyInjectedProvider = - props.providerType === ProviderType.Injected && props.injectedProviderName !== '0x Public'; + const isExternallyInjectedProvider = utils.isExternallyInjected(props.providerType, props.injectedProviderName); return (
diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts index 3cd4e8510..3ce91b7b3 100644 --- a/packages/website/ts/containers/portal_onboarding_flow.ts +++ b/packages/website/ts/containers/portal_onboarding_flow.ts @@ -1,7 +1,7 @@ import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionTypes } from 'ts/types'; +import { ActionTypes, ProviderType } from 'ts/types'; import { PortalOnboardingFlow as PortalOnboardingFlowComponent } from 'ts/components/onboarding/portal_onboarding_flow'; import { State } from 'ts/redux/reducer'; @@ -11,6 +11,10 @@ interface PortalOnboardingFlowProps {} interface ConnectedState { stepIndex: number; isRunning: boolean; + userAddress: string; + providerType: ProviderType; + injectedProviderName: string; + blockchainIsLoaded: boolean; } interface ConnectedDispatch { @@ -20,6 +24,10 @@ interface ConnectedDispatch { const mapStateToProps = (state: State): ConnectedState => ({ stepIndex: state.portalOnboardingStep, isRunning: state.isPortalOnboardingShowing, + userAddress: state.userAddress, + providerType: state.providerType, + injectedProviderName: state.injectedProviderName, + blockchainIsLoaded: state.blockchainIsLoaded, }); const mapDispatchToProps = (dispatch: Dispatch): ConnectedDispatch => ({ diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index e79a873e0..1d4f7eb5c 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -13,6 +13,7 @@ import { Providers, ScreenWidths, Side, + ProviderType, SideToAssetToken, Token, TokenByAddress, @@ -313,6 +314,9 @@ export const utils = { isStaging(): boolean { return _.includes(window.location.href, configs.DOMAIN_STAGING); }, + isExternallyInjected(providerType: ProviderType, injectedProviderName: string): boolean { + return providerType === ProviderType.Injected && injectedProviderName !== constants.PROVIDER_NAME_PUBLIC; + }, isDogfood, shouldShowPortalV2(): boolean { return this.isDevelopment() || this.isStaging() || this.isDogfood(); -- cgit v1.2.3 From f0af6388748bdf08ae81e079e497dc879703c97d Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 24 May 2018 11:44:20 -0700 Subject: Fix PortalOnboardingFlowProps --- packages/website/ts/components/onboarding/portal_onboarding_flow.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 7abfdabda..feaa9c997 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -14,7 +14,6 @@ export interface PortalOnboardingFlowProps { providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; - setOnboardingStep: (stepIndex: number) => void; } export class PortalOnboardingFlow extends React.Component { -- cgit v1.2.3 From 809ac3340cb477d4b46e24d4bad028568beeec06 Mon Sep 17 00:00:00 2001 From: fragosti Date: Thu, 24 May 2018 17:10:39 -0700 Subject: Add ability to blacklist onboarding steps --- .../ts/components/onboarding/onboarding_flow.tsx | 56 +++++++++++++++++-- .../onboarding/portal_onboarding_flow.tsx | 63 ++++++++++++---------- .../ts/containers/portal_onboarding_flow.ts | 7 +++ 3 files changed, 92 insertions(+), 34 deletions(-) diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 22fc71481..0cb640f8f 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -6,9 +6,11 @@ import { zIndex } from 'ts/utils/style'; export interface OnboardingFlowProps { steps: Step[]; + blacklistedStepIndices: number[]; stepIndex: number; isRunning: boolean; onClose: () => void; + setOnboardingStep: (stepIndex: number) => void; } const joyrideStyleOptions: StyleOptions = { @@ -17,16 +19,17 @@ const joyrideStyleOptions: StyleOptions = { // Wrapper around Joyride with defaults and styles set export class OnboardingFlow extends React.Component { - private _joyrideRef: React.RefObject; - constructor(props: OnboardingFlowProps) { - super(props); - this._joyrideRef = React.createRef(); + public componentDidMount(): void { + this._setOnboardingStepBasedOnBlacklist(this.props.stepIndex); + } + + public componentWillReceiveProps(nextProps: OnboardingFlowProps): void { + this._setOnboardingStepBasedOnBlacklist(nextProps.stepIndex); } public render(): React.ReactNode { return ( { ); } + private _setOnboardingStepBasedOnBlacklist(nextIndex: number): void { + const blacklistedSteps = this.props.blacklistedStepIndices; + const newStepIndex = this._adjustedStepBasedOnBlacklist( + this.props.stepIndex, + nextIndex, + this.props.steps.length, + blacklistedSteps, + ); + this.props.setOnboardingStep(newStepIndex); + } + + private _adjustedStepBasedOnBlacklist( + currentStep: number, + nextStep: number, + totalSteps: number, + blacklistedSteps: number[], + ): number { + if (!blacklistedSteps.includes(nextStep)) { + return nextStep; + } + let newStep = nextStep; + const op = nextStep >= currentStep ? _.add : _.subtract; + let didSearch = false; + while (blacklistedSteps.includes(newStep)) { + newStep = op(newStep, 1); + if (newStep < 0) { + if (didSearch) { + break; + } + newStep = totalSteps - 1; + didSearch = true; + } + if (newStep >= totalSteps) { + if (didSearch) { + break; + } + newStep = 0; + didSearch = true; + } + } + return newStep; + } + private _handleChange(data: CallbackData): void { switch (data.action) { case 'close': diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index feaa9c997..c80d1dd6e 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -2,6 +2,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Step } from 'react-joyride'; +import { black } from 'material-ui/styles/colors'; import { OnboardingFlow } from 'ts/components/onboarding/onboarding_flow'; import { ProviderType } from 'ts/types'; import { utils } from 'ts/utils/utils'; @@ -9,21 +10,47 @@ import { utils } from 'ts/utils/utils'; export interface PortalOnboardingFlowProps { stepIndex: number; isRunning: boolean; - onClose: () => void; userAddress: string; providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; + onClose: () => void; + setOnboardingStep: (stepIndex: number) => void; } +const steps: Step[] = [ + { + target: '.wallet', + content: + 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps', + placement: 'right', + disableBeacon: true, + }, + { + target: '.wallet', + content: 'Unlock your metamask extension to begin', + placement: 'right', + disableBeacon: true, + }, + { + target: '.wallet', + content: + 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', + placement: 'right', + disableBeacon: true, + }, +]; + export class PortalOnboardingFlow extends React.Component { public render(): React.ReactNode { return ( ); } @@ -32,40 +59,18 @@ export class PortalOnboardingFlow extends React.Component void; + setOnboardingStep: (stepIndex: number) => void; } const mapStateToProps = (state: State): ConnectedState => ({ @@ -37,6 +38,12 @@ const mapDispatchToProps = (dispatch: Dispatch): ConnectedDispatch => ({ data: false, }); }, + setOnboardingStep: (stepIndex: number): void => { + dispatch({ + type: ActionTypes.UpdatePortalOnboardingStep, + data: stepIndex, + }); + }, }); export const PortalOnboardingFlow: React.ComponentClass = connect( -- cgit v1.2.3 From e575323c6013b89873b698a7f34da135a4b2c51f Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 25 May 2018 11:36:07 -0700 Subject: Auto-show onboarding flow on first page view --- .../ts/components/onboarding/portal_onboarding_flow.tsx | 17 +++++++++++++++-- .../website/ts/containers/portal_onboarding_flow.ts | 8 +++++--- packages/website/ts/index.tsx | 16 +++++++++++++++- packages/website/ts/local_storage/local_storage.ts | 14 ++++++++++++++ packages/website/ts/redux/reducer.ts | 5 ++++- 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index c80d1dd6e..ab9d58415 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -14,7 +14,8 @@ export interface PortalOnboardingFlowProps { providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; - onClose: () => void; + hasBeenSeen: boolean; + setIsRunning: (isRunning: boolean) => void; setOnboardingStep: (stepIndex: number) => void; } @@ -42,6 +43,12 @@ const steps: Step[] = [ ]; export class PortalOnboardingFlow extends React.Component { + public componentDidMount(): void { + this._autoStartOnboardingIfShould(); + } + public componentDidUpdate(): void { + this._autoStartOnboardingIfShould(); + } public render(): React.ReactNode { return ( ); @@ -73,4 +80,10 @@ export class PortalOnboardingFlow extends React.Component void; + setIsRunning: (isRunning: boolean) => void; setOnboardingStep: (stepIndex: number) => void; } @@ -29,13 +30,14 @@ const mapStateToProps = (state: State): ConnectedState => ({ providerType: state.providerType, injectedProviderName: state.injectedProviderName, blockchainIsLoaded: state.blockchainIsLoaded, + hasBeenSeen: state.hasPortalOnboardingBeenSeen, }); const mapDispatchToProps = (dispatch: Dispatch): ConnectedDispatch => ({ - onClose: (): void => { + setIsRunning: (isRunning: boolean): void => { dispatch({ type: ActionTypes.UpdatePortalOnboardingShowing, - data: false, + data: isRunning, }); }, setOnboardingStep: (stepIndex: number): void => { diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index 4fe81a91e..5ab03c07c 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -1,4 +1,5 @@ // Polyfills +import * as _ from 'lodash'; import { MuiThemeProvider } from 'material-ui/styles'; import * as React from 'react'; import { render } from 'react-dom'; @@ -14,6 +15,7 @@ import { Landing } from 'ts/containers/landing'; import { NotFound } from 'ts/containers/not_found'; import { Wiki } from 'ts/containers/wiki'; import { createLazyComponent } from 'ts/lazy_component'; +import { stateStorage } from 'ts/local_storage/state_storage'; import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage'; import { reducer, State } from 'ts/redux/reducer'; @@ -75,7 +77,19 @@ const LazyOrderUtilsDocumentation = createLazyComponent('Documentation', async ( analytics.init(); // tslint:disable-next-line:no-floating-promises analytics.logProviderAsync((window as any).web3); -const store: ReduxStore = createStore(reducer, devToolsEnhancer({ name: '0x Website Redux Store' })); +const store: ReduxStore = createStore( + reducer, + stateStorage.getPersistedDefaultState(), + devToolsEnhancer({ name: '0x Website Redux Store' }), +); +store.subscribe( + _.throttle(() => { + stateStorage.saveState({ + hasPortalOnboardingBeenSeen: store.getState().hasPortalOnboardingBeenSeen, + }); + }, 1000), +); + render(
diff --git a/packages/website/ts/local_storage/local_storage.ts b/packages/website/ts/local_storage/local_storage.ts index 20a533a91..569e262fc 100644 --- a/packages/website/ts/local_storage/local_storage.ts +++ b/packages/website/ts/local_storage/local_storage.ts @@ -26,6 +26,20 @@ export const localStorage = { } window.localStorage.removeItem(key); }, + getObject(key: string): object { + const item = localStorage.getItemIfExists(key); + if (item) { + try { + return JSON.parse(item); + } catch (err) { + return undefined; + } + } + return undefined; + }, + setObject(key: string, value: object): void { + localStorage.setItem(key, JSON.stringify(value)); + }, getAllKeys(): string[] { if (!this.doesExist) { return []; diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts index e61345c87..5c57792f7 100644 --- a/packages/website/ts/redux/reducer.ts +++ b/packages/website/ts/redux/reducer.ts @@ -42,6 +42,7 @@ export interface State { userEtherBalanceInWei: BigNumber; portalOnboardingStep: number; isPortalOnboardingShowing: boolean; + hasPortalOnboardingBeenSeen: boolean; // Note: cache of supplied orderJSON in fill order step. Do not use for anything else. userSuppliedOrderCache: Order; @@ -56,7 +57,7 @@ export interface State { translate: Translate; } -const INITIAL_STATE: State = { +export const INITIAL_STATE: State = { // Portal blockchainErr: BlockchainErrs.NoError, blockchainIsLoaded: false, @@ -84,6 +85,7 @@ const INITIAL_STATE: State = { userSuppliedOrderCache: undefined, portalOnboardingStep: 0, isPortalOnboardingShowing: false, + hasPortalOnboardingBeenSeen: false, // Docs docsVersion: DEFAULT_DOCS_VERSION, availableDocVersions: [DEFAULT_DOCS_VERSION], @@ -309,6 +311,7 @@ export function reducer(state: State = INITIAL_STATE, action: Action): State { return { ...state, isPortalOnboardingShowing, + hasPortalOnboardingBeenSeen: true, }; } -- cgit v1.2.3 From b0e6ce581a77d752d4a0b7f025237c4ac0aee010 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 25 May 2018 12:02:18 -0700 Subject: Add next button --- packages/typescript-typings/types/react-joyride/index.d.ts | 3 ++- packages/website/ts/components/onboarding/onboarding_flow.tsx | 6 +++++- .../website/ts/components/onboarding/portal_onboarding_flow.tsx | 6 ++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/packages/typescript-typings/types/react-joyride/index.d.ts b/packages/typescript-typings/types/react-joyride/index.d.ts index f126e4c86..b9094823d 100644 --- a/packages/typescript-typings/types/react-joyride/index.d.ts +++ b/packages/typescript-typings/types/react-joyride/index.d.ts @@ -62,6 +62,7 @@ declare module 'react-joyride' { steps?: Step[]; beaconComponent?: React.ReactNode; disableOverlayClose?: boolean; + continuous?: boolean; run?: boolean; stepIndex?: number; callback?: (data: CallbackData) => void; @@ -70,7 +71,7 @@ declare module 'react-joyride' { } export interface State { - action: string; + action: 'prev' | 'close' | 'next'; controlled: boolean; index: number; lifecycle: string; diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 0cb640f8f..68dfc11bf 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -31,6 +31,7 @@ export class OnboardingFlow extends React.Component { return ( { this.props.steps.length, blacklistedSteps, ); - this.props.setOnboardingStep(newStepIndex); + if (newStepIndex !== nextIndex) { + this.props.setOnboardingStep(newStepIndex); + } } private _adjustedStepBasedOnBlacklist( @@ -87,6 +90,7 @@ export class OnboardingFlow extends React.Component { switch (data.action) { case 'close': this.props.onClose(); + break; } } } diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index ab9d58415..99fe5006d 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -40,6 +40,12 @@ const steps: Step[] = [ placement: 'right', disableBeacon: true, }, + { + target: '.wallet', + content: 'Before you begin you will need to send some ETH to your metamask wallet', + placement: 'right', + disableBeacon: true, + }, ]; export class PortalOnboardingFlow extends React.Component { -- cgit v1.2.3 From 9631927a8cbbc739f1e1d0d574c61e19803ee0dc Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 25 May 2018 12:02:45 -0700 Subject: Add localstorage helper --- packages/website/ts/local_storage/state_storage.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 packages/website/ts/local_storage/state_storage.ts diff --git a/packages/website/ts/local_storage/state_storage.ts b/packages/website/ts/local_storage/state_storage.ts new file mode 100644 index 000000000..517784b5b --- /dev/null +++ b/packages/website/ts/local_storage/state_storage.ts @@ -0,0 +1,16 @@ +import { localStorage } from 'ts/local_storage/local_storage'; +import { INITIAL_STATE, State } from 'ts/redux/reducer'; + +const STORAGE_NAME = 'persistedState'; + +export const stateStorage = { + saveState(partialState: Partial): void { + localStorage.setObject(STORAGE_NAME, partialState); + }, + getPersistedState(): Partial { + return localStorage.getObject(STORAGE_NAME); + }, + getPersistedDefaultState(): State { + return { ...INITIAL_STATE, ...stateStorage.getPersistedState() }; + }, +}; -- cgit v1.2.3 From 1026952f26043611c4aa3d77b2024cae304021e9 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 25 May 2018 13:13:06 -0700 Subject: Run linter --- packages/website/ts/components/top_bar/provider_display.tsx | 5 ++++- packages/website/ts/utils/utils.ts | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx index 4dc37f231..1cead7a5d 100644 --- a/packages/website/ts/components/top_bar/provider_display.tsx +++ b/packages/website/ts/components/top_bar/provider_display.tsx @@ -39,7 +39,10 @@ const styles: Styles = { export class ProviderDisplay extends React.Component { public render(): React.ReactNode { const isAddressAvailable = !_.isEmpty(this.props.userAddress); - const isExternallyInjectedProvider = utils.isExternallyInjected(this.props.providerType, this.props.injectedProviderName); + const isExternallyInjectedProvider = utils.isExternallyInjected( + this.props.providerType, + this.props.injectedProviderName, + ); const displayAddress = isAddressAvailable ? utils.getAddressBeginAndEnd(this.props.userAddress) : isExternallyInjectedProvider diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 1d4f7eb5c..c0d055070 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -11,9 +11,9 @@ import { Environments, Order, Providers, + ProviderType, ScreenWidths, Side, - ProviderType, SideToAssetToken, Token, TokenByAddress, -- cgit v1.2.3 From 39008372e522bd0963dc71ec91235bb81813355f Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 25 May 2018 15:31:27 -0700 Subject: Write custom tooltip component --- .../types/react-joyride/index.d.ts | 2 +- .../ts/components/onboarding/onboarding_flow.tsx | 39 ++++++++++++++++++---- .../components/onboarding/onboarding_tooltip.tsx | 23 +++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) create mode 100644 packages/website/ts/components/onboarding/onboarding_tooltip.tsx diff --git a/packages/typescript-typings/types/react-joyride/index.d.ts b/packages/typescript-typings/types/react-joyride/index.d.ts index b9094823d..dacdf47a6 100644 --- a/packages/typescript-typings/types/react-joyride/index.d.ts +++ b/packages/typescript-typings/types/react-joyride/index.d.ts @@ -65,9 +65,9 @@ declare module 'react-joyride' { continuous?: boolean; run?: boolean; stepIndex?: number; - callback?: (data: CallbackData) => void; debug?: boolean; styles?: StyleOptionsProp; + tooltipComponent: React.ComponentClass | React.StatelessComponent; } export interface State { diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 68dfc11bf..4ed834916 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -2,6 +2,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import Joyride, { CallbackData, Step, StyleOptions } from 'react-joyride'; +import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; import { zIndex } from 'ts/utils/style'; export interface OnboardingFlowProps { @@ -36,7 +37,7 @@ export class OnboardingFlow extends React.Component { steps={this.props.steps} stepIndex={this.props.stepIndex} styles={{ options: joyrideStyleOptions }} - callback={this._handleChange.bind(this)} + tooltipComponent={this._renderToolTip.bind(this)} /> ); } @@ -86,11 +87,37 @@ export class OnboardingFlow extends React.Component { return newStep; } - private _handleChange(data: CallbackData): void { - switch (data.action) { - case 'close': - this.props.onClose(); - break; + private _renderToolTip(): React.ReactNode { + const { steps, stepIndex } = this.props; + const step = steps[stepIndex]; + const isLastStep = steps.length - 1 === stepIndex; + return ( + + ); + } + + private _goToNextStep(): void { + const nextStep = this.props.stepIndex + 1; + if (nextStep < this.props.steps.length) { + this.props.setOnboardingStep(nextStep); + } else { + this.props.onClose(); + } + } + + private _goToPrevStep(): void { + const nextStep = this.props.stepIndex - 1; + if (nextStep >= 0) { + this.props.setOnboardingStep(nextStep); + } else { + this.props.onClose(); } } } diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx new file mode 100644 index 000000000..3ab18b011 --- /dev/null +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -0,0 +1,23 @@ +import * as React from 'react'; + +import { Island } from 'ts/components/ui/island'; + +export interface OnboardingTooltipProps { + title: string; + content: React.ReactNode; + isLastStep: boolean; + index: number; + onClose: () => void; + onClickNext: () => void; + onClickBack: () => void; +} + +export const OnboardingTooltip: React.StatelessComponent = (props: OnboardingTooltipProps) => ( + + {props.title} + {props.content} + + + + +); -- cgit v1.2.3 From d4a366aeb13d8b3ea2ace86f5566ddf8d94bf9c2 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 10:48:44 -0700 Subject: Replace react-joyride with react-popper --- .../types/react-popper/index.d.ts | 4 ++ packages/website/package.json | 14 ++--- packages/website/public/index.html | 68 +++++++++++----------- .../ts/components/onboarding/onboarding_flow.tsx | 31 +++++++--- .../components/onboarding/onboarding_tooltip.tsx | 3 +- yarn.lock | 32 +++++++++- 6 files changed, 96 insertions(+), 56 deletions(-) create mode 100644 packages/typescript-typings/types/react-popper/index.d.ts diff --git a/packages/typescript-typings/types/react-popper/index.d.ts b/packages/typescript-typings/types/react-popper/index.d.ts new file mode 100644 index 000000000..4341c4521 --- /dev/null +++ b/packages/typescript-typings/types/react-popper/index.d.ts @@ -0,0 +1,4 @@ +// Type definitions for react-popper 1.0.0-beta.6 +// Project: https://github.com/gilbarbara/react-joyride + +declare module 'react-popper'; diff --git a/packages/website/package.json b/packages/website/package.json index 69115be9a..0cc6dfac1 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -11,22 +11,19 @@ "clean": "shx rm -f public/bundle*", "lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'", "watch": "webpack-dev-server --content-base public --https", - "deploy_dogfood": - "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_staging": - "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", - "deploy_live": - "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers" + "deploy_dogfood": "npm run build; aws s3 sync ./public/. s3://dogfood.0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_staging": "npm run build; aws s3 sync ./public/. s3://staging-0xproject --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers", + "deploy_live": "npm run build; aws s3 sync ./public/. s3://0xproject.com --profile 0xproject --region us-east-1 --grants read=uri=http://acs.amazonaws.com/groups/global/AllUsers" }, "author": "Fabio Berger", "license": "Apache-2.0", "dependencies": { + "@0xproject/contract-wrappers": "^0.0.2", "@0xproject/react-docs": "^0.0.12", "@0xproject/react-shared": "^0.1.7", "@0xproject/subproviders": "^0.10.2", - "@0xproject/contract-wrappers": "^0.0.2", - "@0xproject/typescript-typings": "^0.3.2", "@0xproject/types": "0.7.0", + "@0xproject/typescript-typings": "^0.3.2", "@0xproject/utils": "^0.6.2", "@0xproject/web3-wrapper": "^0.6.4", "accounting": "^0.4.1", @@ -47,6 +44,7 @@ "react-dom": "15.6.1", "react-ga": "^2.4.1", "react-joyride": "^2.0.0-11", + "react-popper": "^1.0.0-beta.6", "react-redux": "^5.0.3", "react-router-dom": "^4.1.1", "react-scroll": "^1.5.2", diff --git a/packages/website/public/index.html b/packages/website/public/index.html index c28e4abf4..4c0985c71 100644 --- a/packages/website/public/index.html +++ b/packages/website/public/index.html @@ -26,53 +26,53 @@ + gtag('config', 'UA-98720122-1'); +
+ (function (d, s, id) { + var js, + fjs = d.getElementsByTagName(s)[0]; + if (d.getElementById(id)) return; + js = d.createElement(s); + js.id = id; + js.src = '//connect.facebook.net/en_US/sdk.js#xfbml=1&version=v2.8&appId=1687545238205192'; + fjs.parentNode.insertBefore(js, fjs); + })(document, 'script', 'facebook-jssdk'); +
+ t._e = []; + t.ready = function (f) { + t._e.push(f); + }; + return t; + })(document, 'script', 'twitter-wjs'); + - + \ No newline at end of file diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 4ed834916..cd6fe2195 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -1,6 +1,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import Joyride, { CallbackData, Step, StyleOptions } from 'react-joyride'; +import { Popper, PopperChildrenProps } from 'react-popper'; import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; import { zIndex } from 'ts/utils/style'; @@ -29,16 +30,13 @@ export class OnboardingFlow extends React.Component { } public render(): React.ReactNode { + if (!this.props.isRunning) { + return null; + } return ( - + + {this._renderPopperChildren.bind(this)} + ); } @@ -87,6 +85,21 @@ export class OnboardingFlow extends React.Component { return newStep; } + private _getElementForStep(): Element { + const step = this.props.steps[this.props.stepIndex]; + return document.querySelector(step.target); + } + + private _renderPopperChildren(props: any): React.ReactNode { + const { arrowProps } = props; + return ( +
+ {this._renderToolTip()} +
+
+ ); + } + private _renderToolTip(): React.ReactNode { const { steps, stepIndex } = this.props; const step = steps[stepIndex]; diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 3ab18b011..3994b0546 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -3,10 +3,9 @@ import * as React from 'react'; import { Island } from 'ts/components/ui/island'; export interface OnboardingTooltipProps { - title: string; + title?: string; content: React.ReactNode; isLastStep: boolean; - index: number; onClose: () => void; onClickNext: () => void; onClickBack: () => void; diff --git a/yarn.lock b/yarn.lock index b13953f18..51e522bae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1443,7 +1443,7 @@ babel-register@^6.26.0, babel-register@^6.9.0: mkdirp "^0.5.1" source-map-support "^0.4.15" -babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: +babel-runtime@6.x.x, babel-runtime@^6.11.6, babel-runtime@^6.18.0, babel-runtime@^6.20.0, babel-runtime@^6.22.0, babel-runtime@^6.23.0, babel-runtime@^6.26.0: version "6.26.0" resolved "https://registry.yarnpkg.com/babel-runtime/-/babel-runtime-6.26.0.tgz#965c7058668e82b55d7bfe04ff2337bc8b5647fe" dependencies: @@ -2890,6 +2890,13 @@ create-react-class@^15.5.2, create-react-class@^15.6.0: loose-envify "^1.3.1" object-assign "^4.1.1" +create-react-context@^0.2.1: + version "0.2.2" + resolved "https://registry.npmjs.org/create-react-context/-/create-react-context-0.2.2.tgz#9836542f9aaa22868cd7d4a6f82667df38019dca" + dependencies: + fbjs "^0.8.0" + gud "^1.0.0" + cross-fetch@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-2.1.0.tgz#7d4ea7e10a4f3bb73d5c2f0a3791ec3752d39b50" @@ -4395,7 +4402,7 @@ faye-websocket@~0.11.0: dependencies: websocket-driver ">=0.5.1" -fbjs@^0.8.1, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.6, fbjs@^0.8.9: +fbjs@^0.8.0, fbjs@^0.8.1, fbjs@^0.8.16, fbjs@^0.8.4, fbjs@^0.8.6, fbjs@^0.8.9: version "0.8.16" resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.16.tgz#5e67432f550dc41b572bf55847b8aca64e5337db" dependencies: @@ -5219,6 +5226,10 @@ growl@1.9.2: version "1.9.2" resolved "https://registry.yarnpkg.com/growl/-/growl-1.9.2.tgz#0ea7743715db8d8de2c5ede1775e1b45ac85c02f" +gud@^1.0.0: + version "1.0.0" + resolved "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz#a489581b17e6a70beca9abe3ae57de7a499852c0" + gulp-sourcemaps@1.6.0: version "1.6.0" resolved "https://registry.yarnpkg.com/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz#b86ff349d801ceb56e1d9e7dc7bbcb4b7dee600c" @@ -8612,7 +8623,7 @@ plur@^2.1.2: dependencies: irregular-plurals "^1.0.0" -popper.js@^1.14.3: +popper.js@^1.14.1, popper.js@^1.14.3: version "1.14.3" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" @@ -9482,6 +9493,17 @@ react-markdown@^3.2.2: unist-util-visit "^1.3.0" xtend "^4.0.1" +react-popper@^1.0.0-beta.6: + version "1.0.0-beta.6" + resolved "https://registry.npmjs.org/react-popper/-/react-popper-1.0.0-beta.6.tgz#cb27a2ac56adccbaf5f9c4132387289069240834" + dependencies: + babel-runtime "6.x.x" + create-react-context "^0.2.1" + popper.js "^1.14.1" + prop-types "^15.6.1" + typed-styles "^0.0.5" + warning "^3.0.0" + react-proptype-conditional-require@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz#69c2d5741e6df5e08f230f36bbc2944ee1222555" @@ -11663,6 +11685,10 @@ type-is@~1.6.15, type-is@~1.6.16: media-typer "0.3.0" mime-types "~2.1.18" +typed-styles@^0.0.5: + version "0.0.5" + resolved "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.5.tgz#a60df245d482a9b1adf9c06c078d0f06085ed1cf" + typedarray-to-buffer@^3.1.2: version "3.1.5" resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" -- cgit v1.2.3 From 338e8be327731116a4a0308ba353266293013dce Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 10:53:55 -0700 Subject: Add types for react-popper, remove types for react-joyride --- .../types/react-joyride/index.d.ts | 87 ---------------------- .../types/react-popper/index.d.ts | 47 +++++++++++- .../ts/components/onboarding/onboarding_flow.tsx | 26 ++++--- .../onboarding/portal_onboarding_flow.tsx | 7 +- 4 files changed, 62 insertions(+), 105 deletions(-) delete mode 100644 packages/typescript-typings/types/react-joyride/index.d.ts diff --git a/packages/typescript-typings/types/react-joyride/index.d.ts b/packages/typescript-typings/types/react-joyride/index.d.ts deleted file mode 100644 index dacdf47a6..000000000 --- a/packages/typescript-typings/types/react-joyride/index.d.ts +++ /dev/null @@ -1,87 +0,0 @@ -// Type definitions for react-joyride 2.0.0-11 -// Project: https://github.com/gilbarbara/react-joyride - -declare module 'react-joyride' { - import * as React from 'react'; - export interface StyleOptions { - arrowColor?: string; - backgroundColor?: string; - primaryColor?: string; - textColor?: string; - overlayColor?: string; - spotlightShadow?: string; - beaconSize?: number; - zIndex?: number; - } - - export type Placement = - | 'top' - | 'top-left' - | 'top-right' - | 'bottom' - | 'bottom-left' - | 'bottom-right' - | 'right' - | 'left'; - - export interface Step { - title?: string; - content: React.ReactNode; - target: string; - placement?: Placement; - type?: 'click' | 'hover'; - isFixed?: boolean; - allowClicksThruHole?: boolean; - disableBeacon?: boolean; - style?: StyleOptions; - [prop: string]: any; - } - - export interface StyleOptionsProp { - options: StyleOptions; - } - - interface CallbackMetadata { - type: - | 'tour:start' - | 'step:before' - | 'beacon' - | 'tooltip' - | 'close' - | 'step:after' - | 'tour:end' - | 'tour:status' - | 'error:target_not_found' - | 'error'; - step: number; - } - - export type CallbackData = CallbackMetadata & State; - - export interface Props { - steps?: Step[]; - beaconComponent?: React.ReactNode; - disableOverlayClose?: boolean; - continuous?: boolean; - run?: boolean; - stepIndex?: number; - debug?: boolean; - styles?: StyleOptionsProp; - tooltipComponent: React.ComponentClass | React.StatelessComponent; - } - - export interface State { - action: 'prev' | 'close' | 'next'; - controlled: boolean; - index: number; - lifecycle: string; - size: 0; - status: string; - } - - export default class Joyride extends React.Component { - constructor(props: Props); - - static defaultProps: Props; - } -} diff --git a/packages/typescript-typings/types/react-popper/index.d.ts b/packages/typescript-typings/types/react-popper/index.d.ts index 4341c4521..d7dbca17f 100644 --- a/packages/typescript-typings/types/react-popper/index.d.ts +++ b/packages/typescript-typings/types/react-popper/index.d.ts @@ -1,4 +1,49 @@ // Type definitions for react-popper 1.0.0-beta.6 // Project: https://github.com/gilbarbara/react-joyride -declare module 'react-popper'; +declare module 'react-popper' { + import * as React from 'react'; + import * as PopperJS from 'popper.js'; + + interface ManagerProps { + children: React.ReactNode; + } + export class Manager extends React.Component {} + + type RefHandler = (ref: HTMLElement | null) => void; + + export interface ReferenceChildrenProps { + ref: RefHandler; + } + + export interface ReferenceProps { + children: (props: ReferenceChildrenProps) => React.ReactNode; + } + export class Reference extends React.Component {} + + export interface PopperArrowProps { + ref: RefHandler; + style: React.CSSProperties; + } + + export type Placement = PopperJS.Placement; + + export interface PopperChildrenProps { + arrowProps: PopperArrowProps; + outOfBoundaries: boolean | null; + placement: PopperJS.Placement; + ref: RefHandler; + scheduleUpdate: () => void; + style: React.CSSProperties; + } + + export interface PopperProps { + children: (props: PopperChildrenProps) => React.ReactNode; + eventsEnabled?: boolean; + modifiers?: PopperJS.Modifiers; + placement?: PopperJS.Placement; + positionFixed?: boolean; + referenceElement?: Element; + } + export class Popper extends React.Component {} +} diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index cd6fe2195..9c416c2e1 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -1,11 +1,17 @@ import * as _ from 'lodash'; import * as React from 'react'; -import Joyride, { CallbackData, Step, StyleOptions } from 'react-joyride'; -import { Popper, PopperChildrenProps } from 'react-popper'; +import { Placement, Popper, PopperChildrenProps } from 'react-popper'; import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; import { zIndex } from 'ts/utils/style'; +export interface Step { + target: string; + title?: string; + content: React.ReactNode; + placement?: Placement; +} + export interface OnboardingFlowProps { steps: Step[]; blacklistedStepIndices: number[]; @@ -15,11 +21,6 @@ export interface OnboardingFlowProps { setOnboardingStep: (stepIndex: number) => void; } -const joyrideStyleOptions: StyleOptions = { - zIndex: zIndex.overlay, -}; - -// Wrapper around Joyride with defaults and styles set export class OnboardingFlow extends React.Component { public componentDidMount(): void { this._setOnboardingStepBasedOnBlacklist(this.props.stepIndex); @@ -34,7 +35,7 @@ export class OnboardingFlow extends React.Component { return null; } return ( - + {this._renderPopperChildren.bind(this)} ); @@ -86,11 +87,10 @@ export class OnboardingFlow extends React.Component { } private _getElementForStep(): Element { - const step = this.props.steps[this.props.stepIndex]; - return document.querySelector(step.target); + return document.querySelector(this._getCurrentStep().target); } - private _renderPopperChildren(props: any): React.ReactNode { + private _renderPopperChildren(props: PopperChildrenProps): React.ReactNode { const { arrowProps } = props; return (
@@ -116,6 +116,10 @@ export class OnboardingFlow extends React.Component { ); } + private _getCurrentStep(): Step { + return this.props.steps[this.props.stepIndex]; + } + private _goToNextStep(): void { const nextStep = this.props.stepIndex + 1; if (nextStep < this.props.steps.length) { diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 99fe5006d..00d278ce0 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -1,9 +1,8 @@ import * as _ from 'lodash'; import * as React from 'react'; -import { Step } from 'react-joyride'; import { black } from 'material-ui/styles/colors'; -import { OnboardingFlow } from 'ts/components/onboarding/onboarding_flow'; +import { OnboardingFlow, Step } from 'ts/components/onboarding/onboarding_flow'; import { ProviderType } from 'ts/types'; import { utils } from 'ts/utils/utils'; @@ -25,26 +24,22 @@ const steps: Step[] = [ content: 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps', placement: 'right', - disableBeacon: true, }, { target: '.wallet', content: 'Unlock your metamask extension to begin', placement: 'right', - disableBeacon: true, }, { target: '.wallet', content: 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', placement: 'right', - disableBeacon: true, }, { target: '.wallet', content: 'Before you begin you will need to send some ETH to your metamask wallet', placement: 'right', - disableBeacon: true, }, ]; -- cgit v1.2.3 From f0bbf2cab0ca7aef47699a3954fb0444d5d6d233 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 12:53:18 -0700 Subject: Improve tooltip look --- .../ts/components/onboarding/onboarding_flow.tsx | 9 ++++-- .../components/onboarding/onboarding_tooltip.tsx | 15 ++++++---- .../ts/components/top_bar/provider_display.tsx | 3 ++ packages/website/ts/components/ui/container.tsx | 15 +++++++--- packages/website/ts/components/ui/overlay.tsx | 34 ++++++++++++++++++++++ packages/website/ts/components/wallet/wallet.tsx | 3 ++ packages/website/ts/utils/style.ts | 3 +- 7 files changed, 69 insertions(+), 13 deletions(-) create mode 100644 packages/website/ts/components/ui/overlay.tsx diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 9c416c2e1..8af1a3a3f 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { Placement, Popper, PopperChildrenProps } from 'react-popper'; import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; +import { Overlay } from 'ts/components/ui/overlay'; import { zIndex } from 'ts/utils/style'; export interface Step { @@ -35,9 +36,11 @@ export class OnboardingFlow extends React.Component { return null; } return ( - - {this._renderPopperChildren.bind(this)} - + + + {this._renderPopperChildren.bind(this)} + + ); } diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 3994b0546..2d316b6b7 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; +import { Container } from 'ts/components/ui/container'; import { Island } from 'ts/components/ui/island'; export interface OnboardingTooltipProps { @@ -13,10 +14,14 @@ export interface OnboardingTooltipProps { export const OnboardingTooltip: React.StatelessComponent = (props: OnboardingTooltipProps) => ( - {props.title} - {props.content} - - - + +
+ {props.title} + {props.content} + + + +
+
); diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx index 1cead7a5d..82c95aa6d 100644 --- a/packages/website/ts/components/top_bar/provider_display.tsx +++ b/packages/website/ts/components/top_bar/provider_display.tsx @@ -11,6 +11,7 @@ import { Dispatcher } from 'ts/redux/dispatcher'; import { ProviderType } from 'ts/types'; import { colors } from 'ts/utils/colors'; import { constants } from 'ts/utils/constants'; +import { zIndex } from 'ts/utils/style'; import { utils } from 'ts/utils/utils'; const ROOT_HEIGHT = 24; @@ -33,6 +34,8 @@ const styles: Styles = { backgroundColor: colors.white, borderRadius: ROOT_HEIGHT, boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`, + zIndex: zIndex.aboveOverlay, + position: 'relative', }, }; diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx index 07868608c..d577447b0 100644 --- a/packages/website/ts/components/ui/container.tsx +++ b/packages/website/ts/components/ui/container.tsx @@ -1,10 +1,17 @@ import * as React from 'react'; +type StringOrNum = string | number; + export interface ContainerProps { - marginTop?: string | number; - marginBottom?: string | number; - marginRight?: string | number; - marginLeft?: string | number; + marginTop?: StringOrNum; + marginBottom?: StringOrNum; + marginRight?: StringOrNum; + marginLeft?: StringOrNum; + paddingTop?: StringOrNum; + paddingBottom?: StringOrNum; + paddingRight?: StringOrNum; + paddingLeft?: StringOrNum; + maxWidth?: StringOrNum; children?: React.ReactNode; } diff --git a/packages/website/ts/components/ui/overlay.tsx b/packages/website/ts/components/ui/overlay.tsx new file mode 100644 index 000000000..bb2ed8e59 --- /dev/null +++ b/packages/website/ts/components/ui/overlay.tsx @@ -0,0 +1,34 @@ +import { colors } from '@0xproject/react-shared'; +import * as _ from 'lodash'; +import * as React from 'react'; + +import { zIndex } from 'ts/utils/style'; + +export interface OverlayProps { + children?: React.ReactNode; + style?: React.CSSProperties; + onClick?: () => void; +} + +const style: React.CSSProperties = { + position: 'fixed', + top: 0, + right: 0, + bottom: 0, + left: 0, + zIndex: zIndex.overlay, + backgroundColor: 'rgba(0, 0, 0, 0.6)', +}; + +export const Overlay: React.StatelessComponent = (props: OverlayProps) => ( +
+ {props.children} +
+); + +Overlay.defaultProps = { + style: {}, + onClick: _.noop, +}; + +Overlay.displayName = 'Overlay'; diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 39e591bac..eab986208 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -47,6 +47,7 @@ import { colors } from 'ts/utils/colors'; import { constants } from 'ts/utils/constants'; import { utils } from 'ts/utils/utils'; import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles'; +import { zIndex } from '../../utils/style'; export interface WalletProps { userAddress: string; @@ -85,6 +86,8 @@ interface AccessoryItemConfig { const styles: Styles = { root: { width: '100%', + zIndex: zIndex.aboveOverlay, + position: 'relative', }, headerItemInnerDiv: { paddingLeft: 65, diff --git a/packages/website/ts/utils/style.ts b/packages/website/ts/utils/style.ts index 51b6e4eb6..0411cdd91 100644 --- a/packages/website/ts/utils/style.ts +++ b/packages/website/ts/utils/style.ts @@ -1,4 +1,5 @@ export const zIndex = { topBar: 1100, - overlay: 1101, + overlay: 1105, + aboveOverlay: 1106, }; -- cgit v1.2.3 From 92cb5e10be479ca0440b3c7ca91fe70a1ef94c03 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 14:26:38 -0700 Subject: Some cleanup --- .../ts/components/onboarding/onboarding_flow.tsx | 23 +++++++++++----------- .../components/onboarding/onboarding_tooltip.tsx | 1 + 2 files changed, 13 insertions(+), 11 deletions(-) diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 8af1a3a3f..d53f63400 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -3,6 +3,7 @@ import * as React from 'react'; import { Placement, Popper, PopperChildrenProps } from 'react-popper'; import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; +import { Container } from 'ts/components/ui/container'; import { Overlay } from 'ts/components/ui/overlay'; import { zIndex } from 'ts/utils/style'; @@ -36,7 +37,7 @@ export class OnboardingFlow extends React.Component { return null; } return ( - + {this._renderPopperChildren.bind(this)} @@ -94,11 +95,9 @@ export class OnboardingFlow extends React.Component { } private _renderPopperChildren(props: PopperChildrenProps): React.ReactNode { - const { arrowProps } = props; return (
{this._renderToolTip()} -
); } @@ -108,14 +107,16 @@ export class OnboardingFlow extends React.Component { const step = steps[stepIndex]; const isLastStep = steps.length - 1 === stepIndex; return ( - + + + ); } diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 2d316b6b7..5e8102af0 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; +import { colors } from '@0xproject/react-shared'; import { Container } from 'ts/components/ui/container'; import { Island } from 'ts/components/ui/island'; -- cgit v1.2.3 From 30ac5fcb5e97c1ae62045ecf84fcd75a2da1ecf2 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 15:15:30 -0700 Subject: Remove blacklist concept --- .../ts/components/onboarding/onboarding_flow.tsx | 56 +--------------------- .../components/onboarding/onboarding_tooltip.tsx | 3 +- .../onboarding/portal_onboarding_flow.tsx | 25 ++++++---- .../ts/components/top_bar/provider_display.tsx | 2 - 4 files changed, 20 insertions(+), 66 deletions(-) diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index d53f63400..de734318e 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -12,11 +12,11 @@ export interface Step { title?: string; content: React.ReactNode; placement?: Placement; + hideBackButton?: boolean; } export interface OnboardingFlowProps { steps: Step[]; - blacklistedStepIndices: number[]; stepIndex: number; isRunning: boolean; onClose: () => void; @@ -24,14 +24,6 @@ export interface OnboardingFlowProps { } export class OnboardingFlow extends React.Component { - public componentDidMount(): void { - this._setOnboardingStepBasedOnBlacklist(this.props.stepIndex); - } - - public componentWillReceiveProps(nextProps: OnboardingFlowProps): void { - this._setOnboardingStepBasedOnBlacklist(nextProps.stepIndex); - } - public render(): React.ReactNode { if (!this.props.isRunning) { return null; @@ -45,51 +37,6 @@ export class OnboardingFlow extends React.Component { ); } - private _setOnboardingStepBasedOnBlacklist(nextIndex: number): void { - const blacklistedSteps = this.props.blacklistedStepIndices; - const newStepIndex = this._adjustedStepBasedOnBlacklist( - this.props.stepIndex, - nextIndex, - this.props.steps.length, - blacklistedSteps, - ); - if (newStepIndex !== nextIndex) { - this.props.setOnboardingStep(newStepIndex); - } - } - - private _adjustedStepBasedOnBlacklist( - currentStep: number, - nextStep: number, - totalSteps: number, - blacklistedSteps: number[], - ): number { - if (!blacklistedSteps.includes(nextStep)) { - return nextStep; - } - let newStep = nextStep; - const op = nextStep >= currentStep ? _.add : _.subtract; - let didSearch = false; - while (blacklistedSteps.includes(newStep)) { - newStep = op(newStep, 1); - if (newStep < 0) { - if (didSearch) { - break; - } - newStep = totalSteps - 1; - didSearch = true; - } - if (newStep >= totalSteps) { - if (didSearch) { - break; - } - newStep = 0; - didSearch = true; - } - } - return newStep; - } - private _getElementForStep(): Element { return document.querySelector(this._getCurrentStep().target); } @@ -112,6 +59,7 @@ export class OnboardingFlow extends React.Component { title={step.title} content={step.content} isLastStep={isLastStep} + hideBackButton={step.hideBackButton} onClose={this.props.onClose} onClickNext={this._goToNextStep.bind(this)} onClickBack={this._goToPrevStep.bind(this)} diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 5e8102af0..41925a672 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -11,6 +11,7 @@ export interface OnboardingTooltipProps { onClose: () => void; onClickNext: () => void; onClickBack: () => void; + hideBackButton?: boolean; } export const OnboardingTooltip: React.StatelessComponent = (props: OnboardingTooltipProps) => ( @@ -19,7 +20,7 @@ export const OnboardingTooltip: React.StatelessComponent
{props.title} {props.content} - + {!props.hideBackButton && }
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 00d278ce0..25570b4a7 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -35,6 +35,7 @@ const steps: Step[] = [ content: 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', placement: 'right', + hideBackButton: true, }, { target: '.wallet', @@ -45,16 +46,15 @@ const steps: Step[] = [ export class PortalOnboardingFlow extends React.Component { public componentDidMount(): void { - this._autoStartOnboardingIfShould(); + this._overrideOnboardingStateIfShould(); } public componentDidUpdate(): void { - this._autoStartOnboardingIfShould(); + this._overrideOnboardingStateIfShould(); } public render(): React.ReactNode { return ( Date: Tue, 29 May 2018 15:24:10 -0700 Subject: Add entry to CHANGELOG.json --- packages/typescript-typings/CHANGELOG.json | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/typescript-typings/CHANGELOG.json b/packages/typescript-typings/CHANGELOG.json index 77a5ffad2..86b4a5078 100644 --- a/packages/typescript-typings/CHANGELOG.json +++ b/packages/typescript-typings/CHANGELOG.json @@ -1,4 +1,12 @@ [ + { + "version": "0.5.0", + "changes": [ + { + "note": "Add types for `react-popper`, remove types for `react-joyride`" + } + ] + }, { "version": "0.4.0", "changes": [ -- cgit v1.2.3 From 0d3010f6fc8b14011444f090dfbd0221411a1ab0 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 15:27:30 -0700 Subject: Remove react-joyride from deps --- packages/website/package.json | 1 - yarn.lock | 81 ++----------------------------------------- 2 files changed, 2 insertions(+), 80 deletions(-) diff --git a/packages/website/package.json b/packages/website/package.json index 0cc6dfac1..95804f988 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -43,7 +43,6 @@ "react-document-title": "^2.0.3", "react-dom": "15.6.1", "react-ga": "^2.4.1", - "react-joyride": "^2.0.0-11", "react-popper": "^1.0.0-beta.6", "react-redux": "^5.0.3", "react-router-dom": "^4.1.1", diff --git a/yarn.lock b/yarn.lock index 51e522bae..f6b990aed 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3253,14 +3253,6 @@ dedent@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/dedent/-/dedent-0.7.0.tgz#2495ddbaf6eb874abb0e1be9df22d2e5a544326c" -deep-diff@^0.3.8: - version "0.3.8" - resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-0.3.8.tgz#c01de63efb0eec9798801d40c7e0dae25b582c84" - -deep-diff@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/deep-diff/-/deep-diff-1.0.0.tgz#0dd55f9412f22a07b2edbfbb11bb4633be6be40b" - deep-eql@^0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2" @@ -3293,10 +3285,6 @@ deep-is@~0.1.3: version "0.1.3" resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.3.tgz#b369d6fb5dbc13eecf524f91b070feedc357cf34" -deepmerge@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-2.1.0.tgz#511a54fff405fc346f0240bb270a3e9533a31102" - default-require-extensions@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-1.0.0.tgz#f37ea15d3e13ffd9b437d33e1a75b5fb97874cb8" @@ -4210,7 +4198,7 @@ execa@^0.8.0: signal-exit "^3.0.0" strip-eof "^1.0.0" -exenv@^1.2.1, exenv@^1.2.2: +exenv@^1.2.1: version "1.2.2" resolved "https://registry.yarnpkg.com/exenv/-/exenv-1.2.2.tgz#2ae78e85d9894158670b03d47bec1f03bd91bb9d" @@ -6052,10 +6040,6 @@ is-installed-globally@^0.1.0: global-dirs "^0.1.0" is-path-inside "^1.0.0" -is-lite@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/is-lite/-/is-lite-0.2.0.tgz#1532415467f1fd49aa693ba013a8669575df7cf3" - is-mobile@^0.2.2: version "0.2.2" resolved "https://registry.yarnpkg.com/is-mobile/-/is-mobile-0.2.2.tgz#0e2e006d99ed2c2155b761df80f2a3619ae2ad9f" @@ -7771,10 +7755,6 @@ neo-async@^2.5.0: version "2.5.1" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-2.5.1.tgz#acb909e327b1e87ec9ef15f41b8a269512ad41ee" -nested-property@0.0.7, nested-property@^0.0.7: - version "0.0.7" - resolved "https://registry.yarnpkg.com/nested-property/-/nested-property-0.0.7.tgz#ff222f233ca8793c6828b4117091bea597130f4f" - newman@^3.9.3: version "3.9.3" resolved "https://registry.yarnpkg.com/newman/-/newman-3.9.3.tgz#939356026942474ba15482bd37a15c60bb200ca0" @@ -8623,7 +8603,7 @@ plur@^2.1.2: dependencies: irregular-plurals "^1.0.0" -popper.js@^1.14.1, popper.js@^1.14.3: +popper.js@^1.14.1: version "1.14.3" resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.14.3.tgz#1438f98d046acf7b4d78cd502bf418ac64d4f095" @@ -9329,12 +9309,6 @@ quick-lru@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/quick-lru/-/quick-lru-1.1.0.tgz#4360b17c61136ad38078397ff11416e186dcfbb8" -rafl@~1.2.1: - version "1.2.2" - resolved "https://registry.yarnpkg.com/rafl/-/rafl-1.2.2.tgz#fe930f758211020d47e38815f5196a8be4150740" - dependencies: - global "~4.3.0" - randomatic@^1.1.3: version "1.1.7" resolved "https://registry.yarnpkg.com/randomatic/-/randomatic-1.1.7.tgz#c7abe9cc8b87c0baa876b19fde83fd464797e38c" @@ -9441,16 +9415,6 @@ react-event-listener@^0.4.5: prop-types "^15.5.4" warning "^3.0.0" -react-floater@^0.5.4: - version "0.5.4" - resolved "https://registry.yarnpkg.com/react-floater/-/react-floater-0.5.4.tgz#411a57fd8631e96466e035ee6c91f1f118c8782a" - dependencies: - deepmerge "^2.1.0" - exenv "^1.2.2" - is-lite "^0.2.0" - popper.js "^1.14.3" - react-proptype-conditional-require "^1.0.4" - react-ga@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/react-ga/-/react-ga-2.4.1.tgz#dfbd5f028ed39a07067f7a8bf57dc0d240000767" @@ -9467,22 +9431,6 @@ react-highlight@0xproject/react-highlight: react "^15.5.4" react-dom "^15.5.4" -react-joyride@^2.0.0-11: - version "2.0.0-11" - resolved "https://registry.yarnpkg.com/react-joyride/-/react-joyride-2.0.0-11.tgz#5cbf4f86b83dfbf9242e7d19482a0fd7cc69ad52" - dependencies: - deep-diff "^1.0.0" - deepmerge "^2.1.0" - exenv "^1.2.2" - is-lite "^0.2.0" - nested-property "^0.0.7" - react-floater "^0.5.4" - react-proptype-conditional-require "^1.0.4" - scroll "^2.0.3" - scroll-doc "^0.2.1" - scrollparent "^2.0.1" - tree-changes "^0.3.2" - react-markdown@^3.2.2: version "3.3.0" resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-3.3.0.tgz#a87cdd822aa9302d6add9687961dd1a82a45d02e" @@ -9504,10 +9452,6 @@ react-popper@^1.0.0-beta.6: typed-styles "^0.0.5" warning "^3.0.0" -react-proptype-conditional-require@^1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/react-proptype-conditional-require/-/react-proptype-conditional-require-1.0.4.tgz#69c2d5741e6df5e08f230f36bbc2944ee1222555" - react-redux@^5.0.3: version "5.0.7" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-5.0.7.tgz#0dc1076d9afb4670f993ffaef44b8f8c1155a4c8" @@ -10197,20 +10141,6 @@ scoped-regex@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/scoped-regex/-/scoped-regex-1.0.0.tgz#a346bb1acd4207ae70bd7c0c7ca9e566b6baddb8" -scroll-doc@^0.2.1: - version "0.2.1" - resolved "https://registry.yarnpkg.com/scroll-doc/-/scroll-doc-0.2.1.tgz#168f9e9ac598743dd682c992839b44a38ce4dd91" - -scroll@^2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/scroll/-/scroll-2.0.3.tgz#0951b785544205fd17753bc3d294738ba16fc2ab" - dependencies: - rafl "~1.2.1" - -scrollparent@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/scrollparent/-/scrollparent-2.0.1.tgz#715d5b9cc57760fb22bdccc3befb5bfe06b1a317" - scrypt-js@2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/scrypt-js/-/scrypt-js-2.0.3.tgz#bb0040be03043da9a012a2cea9fc9f852cfc87d4" @@ -11513,13 +11443,6 @@ traverse-chain@~0.1.0: version "0.1.0" resolved "https://registry.yarnpkg.com/traverse-chain/-/traverse-chain-0.1.0.tgz#61dbc2d53b69ff6091a12a168fd7d433107e40f1" -tree-changes@^0.3.2: - version "0.3.2" - resolved "https://registry.yarnpkg.com/tree-changes/-/tree-changes-0.3.2.tgz#ad7d3b499155bd6176f2c9c6a472d8155df0a9ce" - dependencies: - deep-diff "^0.3.8" - nested-property "0.0.7" - treeify@^1.0.1: version "1.1.0" resolved "https://registry.yarnpkg.com/treeify/-/treeify-1.1.0.tgz#4e31c6a463accd0943879f30667c4fdaff411bb8" -- cgit v1.2.3 From bc28a08dd0d4db99549122fb4912b4931a3aad78 Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 15:49:13 -0700 Subject: Address PR feedback --- .../ts/components/onboarding/onboarding_flow.tsx | 6 +++--- .../onboarding/portal_onboarding_flow.tsx | 16 ++++++++-------- packages/website/ts/components/wallet/wallet.tsx | 2 +- .../website/ts/containers/portal_onboarding_flow.ts | 8 ++++---- packages/website/ts/index.tsx | 20 ++------------------ packages/website/ts/local_storage/local_storage.ts | 8 ++------ packages/website/ts/redux/store.ts | 21 +++++++++++++++++++++ 7 files changed, 41 insertions(+), 40 deletions(-) create mode 100644 packages/website/ts/redux/store.ts diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index de734318e..524587358 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -20,7 +20,7 @@ export interface OnboardingFlowProps { stepIndex: number; isRunning: boolean; onClose: () => void; - setOnboardingStep: (stepIndex: number) => void; + updateOnboardingStep: (stepIndex: number) => void; } export class OnboardingFlow extends React.Component { @@ -75,7 +75,7 @@ export class OnboardingFlow extends React.Component { private _goToNextStep(): void { const nextStep = this.props.stepIndex + 1; if (nextStep < this.props.steps.length) { - this.props.setOnboardingStep(nextStep); + this.props.updateOnboardingStep(nextStep); } else { this.props.onClose(); } @@ -84,7 +84,7 @@ export class OnboardingFlow extends React.Component { private _goToPrevStep(): void { const nextStep = this.props.stepIndex - 1; if (nextStep >= 0) { - this.props.setOnboardingStep(nextStep); + this.props.updateOnboardingStep(nextStep); } else { this.props.onClose(); } diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 25570b4a7..8bcb4c749 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -14,8 +14,8 @@ export interface PortalOnboardingFlowProps { injectedProviderName: string; blockchainIsLoaded: boolean; hasBeenSeen: boolean; - setIsRunning: (isRunning: boolean) => void; - setOnboardingStep: (stepIndex: number) => void; + updateIsRunning: (isRunning: boolean) => void; + updateOnboardingStep: (stepIndex: number) => void; } const steps: Step[] = [ @@ -57,8 +57,8 @@ export class PortalOnboardingFlow extends React.Component ); } @@ -75,7 +75,7 @@ export class PortalOnboardingFlow extends React.Component void; - setOnboardingStep: (stepIndex: number) => void; + updateIsRunning: (isRunning: boolean) => void; + updateOnboardingStep: (stepIndex: number) => void; } const mapStateToProps = (state: State): ConnectedState => ({ @@ -34,13 +34,13 @@ const mapStateToProps = (state: State): ConnectedState => ({ }); const mapDispatchToProps = (dispatch: Dispatch): ConnectedDispatch => ({ - setIsRunning: (isRunning: boolean): void => { + updateIsRunning: (isRunning: boolean): void => { dispatch({ type: ActionTypes.UpdatePortalOnboardingShowing, data: isRunning, }); }, - setOnboardingStep: (stepIndex: number): void => { + updateOnboardingStep: (stepIndex: number): void => { dispatch({ type: ActionTypes.UpdatePortalOnboardingStep, data: stepIndex, diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx index 5ab03c07c..a6bfe7dd2 100644 --- a/packages/website/ts/index.tsx +++ b/packages/website/ts/index.tsx @@ -1,13 +1,9 @@ -// Polyfills -import * as _ from 'lodash'; import { MuiThemeProvider } from 'material-ui/styles'; import * as React from 'react'; import { render } from 'react-dom'; import { Provider } from 'react-redux'; import { BrowserRouter as Router, Redirect, Route, Switch } from 'react-router-dom'; import * as injectTapEventPlugin from 'react-tap-event-plugin'; -import { createStore, Store as ReduxStore } from 'redux'; -import { devToolsEnhancer } from 'redux-devtools-extension/developmentOnly'; import { Redirecter } from 'ts/components/redirecter'; import { About } from 'ts/containers/about'; import { FAQ } from 'ts/containers/faq'; @@ -15,14 +11,14 @@ import { Landing } from 'ts/containers/landing'; import { NotFound } from 'ts/containers/not_found'; import { Wiki } from 'ts/containers/wiki'; import { createLazyComponent } from 'ts/lazy_component'; -import { stateStorage } from 'ts/local_storage/state_storage'; import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage'; import { tradeHistoryStorage } from 'ts/local_storage/trade_history_storage'; -import { reducer, State } from 'ts/redux/reducer'; +import { store } from 'ts/redux/store'; import { WebsiteLegacyPaths, WebsitePaths } from 'ts/types'; import { analytics } from 'ts/utils/analytics'; import { muiTheme } from 'ts/utils/mui_theme'; import { utils } from 'ts/utils/utils'; +// Polyfills import 'whatwg-fetch'; injectTapEventPlugin(); @@ -77,18 +73,6 @@ const LazyOrderUtilsDocumentation = createLazyComponent('Documentation', async ( analytics.init(); // tslint:disable-next-line:no-floating-promises analytics.logProviderAsync((window as any).web3); -const store: ReduxStore = createStore( - reducer, - stateStorage.getPersistedDefaultState(), - devToolsEnhancer({ name: '0x Website Redux Store' }), -); -store.subscribe( - _.throttle(() => { - stateStorage.saveState({ - hasPortalOnboardingBeenSeen: store.getState().hasPortalOnboardingBeenSeen, - }); - }, 1000), -); render( diff --git a/packages/website/ts/local_storage/local_storage.ts b/packages/website/ts/local_storage/local_storage.ts index 569e262fc..1e3258ce0 100644 --- a/packages/website/ts/local_storage/local_storage.ts +++ b/packages/website/ts/local_storage/local_storage.ts @@ -26,14 +26,10 @@ export const localStorage = { } window.localStorage.removeItem(key); }, - getObject(key: string): object { + getObject(key: string): object | undefined { const item = localStorage.getItemIfExists(key); if (item) { - try { - return JSON.parse(item); - } catch (err) { - return undefined; - } + return JSON.parse(item); } return undefined; }, diff --git a/packages/website/ts/redux/store.ts b/packages/website/ts/redux/store.ts new file mode 100644 index 000000000..203f068a1 --- /dev/null +++ b/packages/website/ts/redux/store.ts @@ -0,0 +1,21 @@ +import * as _ from 'lodash'; +import { createStore, Store as ReduxStore } from 'redux'; +import { devToolsEnhancer } from 'redux-devtools-extension/developmentOnly'; +import { stateStorage } from 'ts/local_storage/state_storage'; +import { reducer, State } from 'ts/redux/reducer'; + +const ONE_SECOND = 1000; + +export const store: ReduxStore = createStore( + reducer, + stateStorage.getPersistedDefaultState(), + devToolsEnhancer({ name: '0x Website Redux Store' }), +); +store.subscribe( + _.throttle(() => { + // Persisted state + stateStorage.saveState({ + hasPortalOnboardingBeenSeen: store.getState().hasPortalOnboardingBeenSeen, + }); + }, ONE_SECOND), +); -- cgit v1.2.3 From b14c3fe48dc8eb5bad6eefceac872754eec34ffe Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 29 May 2018 17:57:22 -0700 Subject: Onboarding: implement add ETH step, and stub for add WETH step --- .../ts/components/onboarding/onboarding_flow.tsx | 6 +- .../components/onboarding/onboarding_tooltip.tsx | 29 +++++++- .../onboarding/portal_onboarding_flow.tsx | 86 ++++++++++++++-------- packages/website/ts/components/wallet/wallet.tsx | 30 ++++---- .../ts/containers/portal_onboarding_flow.ts | 9 ++- packages/website/ts/utils/constants.ts | 3 + packages/website/ts/utils/utils.ts | 5 ++ 7 files changed, 121 insertions(+), 47 deletions(-) diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 524587358..4066babaf 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -2,7 +2,7 @@ import * as _ from 'lodash'; import * as React from 'react'; import { Placement, Popper, PopperChildrenProps } from 'react-popper'; -import { OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; +import { ContinueButtonDisplay, OnboardingTooltip } from 'ts/components/onboarding/onboarding_tooltip'; import { Container } from 'ts/components/ui/container'; import { Overlay } from 'ts/components/ui/overlay'; import { zIndex } from 'ts/utils/style'; @@ -13,6 +13,8 @@ export interface Step { content: React.ReactNode; placement?: Placement; hideBackButton?: boolean; + hideNextButton?: boolean; + continueButtonDisplay?: ContinueButtonDisplay; } export interface OnboardingFlowProps { @@ -60,9 +62,11 @@ export class OnboardingFlow extends React.Component { content={step.content} isLastStep={isLastStep} hideBackButton={step.hideBackButton} + hideNextButton={step.hideNextButton} onClose={this.props.onClose} onClickNext={this._goToNextStep.bind(this)} onClickBack={this._goToPrevStep.bind(this)} + continueButtonDisplay={step.continueButtonDisplay} /> ); diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx index 41925a672..eb34a87f2 100644 --- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx +++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx @@ -4,6 +4,8 @@ import { colors } from '@0xproject/react-shared'; import { Container } from 'ts/components/ui/container'; import { Island } from 'ts/components/ui/island'; +export type ContinueButtonDisplay = 'enabled' | 'disabled'; + export interface OnboardingTooltipProps { title?: string; content: React.ReactNode; @@ -11,19 +13,44 @@ export interface OnboardingTooltipProps { onClose: () => void; onClickNext: () => void; onClickBack: () => void; + continueButtonDisplay?: ContinueButtonDisplay; hideBackButton?: boolean; + hideNextButton?: boolean; +} + +// TODO: Make this more general button. +export interface ContinueButtonProps { + display: ContinueButtonDisplay; + children?: string; + onClick: () => void; } +export const ContinueButton: React.StatelessComponent = (props: ContinueButtonProps) => { + const isDisabled = props.display === 'disabled'; + return ( + + ); +}; + export const OnboardingTooltip: React.StatelessComponent = (props: OnboardingTooltipProps) => (
{props.title} {props.content} + {props.continueButtonDisplay && ( + + Continue + + )} {!props.hideBackButton && } - + {!props.hideNextButton && }
); + +OnboardingTooltip.displayName = 'OnboardingTooltip'; diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx index 8bcb4c749..edaeb3736 100644 --- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx @@ -1,49 +1,25 @@ import * as _ from 'lodash'; import * as React from 'react'; -import { black } from 'material-ui/styles/colors'; +import { BigNumber } from '@0xproject/utils'; import { OnboardingFlow, Step } from 'ts/components/onboarding/onboarding_flow'; -import { ProviderType } from 'ts/types'; +import { ProviderType, TokenByAddress } from 'ts/types'; import { utils } from 'ts/utils/utils'; export interface PortalOnboardingFlowProps { stepIndex: number; isRunning: boolean; userAddress: string; + hasBeenSeen: boolean; providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; - hasBeenSeen: boolean; + userEthBalanceInWei: BigNumber; + tokenByAddress: TokenByAddress; updateIsRunning: (isRunning: boolean) => void; updateOnboardingStep: (stepIndex: number) => void; } -const steps: Step[] = [ - { - target: '.wallet', - content: - 'Before you begin, you need to connect to a wallet. This will be used across all 0x relayers and dApps', - placement: 'right', - }, - { - target: '.wallet', - content: 'Unlock your metamask extension to begin', - placement: 'right', - }, - { - target: '.wallet', - content: - 'In order to start trading on any 0x relayer in the 0x ecosystem, you need to complete two simple steps', - placement: 'right', - hideBackButton: true, - }, - { - target: '.wallet', - content: 'Before you begin you will need to send some ETH to your metamask wallet', - placement: 'right', - }, -]; - export class PortalOnboardingFlow extends React.Component { public componentDidMount(): void { this._overrideOnboardingStateIfShould(); @@ -54,7 +30,7 @@ export class PortalOnboardingFlow extends React.Component new BigNumber(0); + } + + private _userHasWeth(): boolean { + // TODO: https://app.asana.com/0/681385331277907/690722374136933 + return false; + } + private _overrideOnboardingStateIfShould(): void { this._autoStartOnboardingIfShould(); this._adjustStepIfShould(); diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 524dc1952..d72c5458f 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -131,9 +131,6 @@ const styles: Styles = { }; const ETHER_ICON_PATH = '/images/ether.png'; -const ETHER_TOKEN_SYMBOL = 'WETH'; -const ZRX_TOKEN_SYMBOL = 'ZRX'; -const ETHER_SYMBOL = 'ETH'; const ICON_DIMENSION = 24; const TOKEN_AMOUNT_DISPLAY_PRECISION = 3; const BODY_ITEM_KEY = 'BODY'; @@ -319,7 +316,7 @@ export class Wallet extends React.Component { const primaryText = this._renderAmount( this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH, - ETHER_SYMBOL, + constants.ETHER_SYMBOL, ); const etherToken = this._getEthToken(); const etherPrice = this.state.trackedTokenStateByAddress[etherToken.address].price; @@ -338,13 +335,13 @@ export class Wallet extends React.Component { ? { ...walletItemStyles.focusedItem, ...styles.paddedItem } : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; const key = ETHER_ITEM_KEY; - return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig); + return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig, 'eth-row'); } private _renderTokenRows(): React.ReactNode { const trackedTokens = this.props.trackedTokens; const trackedTokensStartingWithEtherToken = trackedTokens.sort( - firstBy((t: Token) => t.symbol !== ETHER_TOKEN_SYMBOL) - .thenBy((t: Token) => t.symbol !== ZRX_TOKEN_SYMBOL) + firstBy((t: Token) => t.symbol !== constants.ETHER_TOKEN_SYMBOL) + .thenBy((t: Token) => t.symbol !== constants.ZRX_TOKEN_SYMBOL) .thenBy('address'), ); return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this)); @@ -359,7 +356,8 @@ export class Wallet extends React.Component { const icon = ; const primaryText = this._renderAmount(tokenState.balance, token.decimals, token.symbol); const secondaryText = this._renderValue(tokenState.balance, token.decimals, tokenState.price); - const wrappedEtherDirection = token.symbol === ETHER_TOKEN_SYMBOL ? Side.Receive : undefined; + const isWeth = token.symbol === constants.ETHER_TOKEN_SYMBOL; + const wrappedEtherDirection = isWeth ? Side.Receive : undefined; const accessoryItemConfig: AccessoryItemConfig = { wrappedEtherDirection, allowanceToggleConfig: { @@ -368,7 +366,14 @@ export class Wallet extends React.Component { }, }; const key = token.address; - return this._renderBalanceRow(key, icon, primaryText, secondaryText, accessoryItemConfig); + return this._renderBalanceRow( + key, + icon, + primaryText, + secondaryText, + accessoryItemConfig, + isWeth ? 'weth-row' : undefined, + ); } private _renderBalanceRow( key: string, @@ -376,6 +381,7 @@ export class Wallet extends React.Component { primaryText: React.ReactNode, secondaryText: React.ReactNode, accessoryItemConfig: AccessoryItemConfig, + className?: string, ): React.ReactNode { const shouldShowWrapEtherItem = !_.isUndefined(this.state.wrappedEtherDirection) && @@ -385,7 +391,7 @@ export class Wallet extends React.Component { : { ...styles.tokenItem, ...styles.borderedItem, ...styles.paddedItem }; const etherToken = this._getEthToken(); return ( -
+
{icon}
@@ -575,8 +581,6 @@ export class Wallet extends React.Component { }); } private _getEthToken(): Token { - const tokens = _.values(this.props.tokenByAddress); - const etherToken = _.find(tokens, { symbol: ETHER_TOKEN_SYMBOL }); - return etherToken; + return utils.getEthToken(this.props.tokenByAddress); } } // tslint:disable:max-file-line-count diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts index 56a1db553..84739192f 100644 --- a/packages/website/ts/containers/portal_onboarding_flow.ts +++ b/packages/website/ts/containers/portal_onboarding_flow.ts @@ -1,7 +1,8 @@ +import { BigNumber } from '@0xproject/utils'; import * as React from 'react'; import { connect } from 'react-redux'; import { Dispatch } from 'redux'; -import { ActionTypes, ProviderType } from 'ts/types'; +import { ActionTypes, ProviderType, TokenByAddress } from 'ts/types'; import { PortalOnboardingFlow as PortalOnboardingFlowComponent } from 'ts/components/onboarding/portal_onboarding_flow'; import { State } from 'ts/redux/reducer'; @@ -12,10 +13,12 @@ interface ConnectedState { stepIndex: number; isRunning: boolean; userAddress: string; + hasBeenSeen: boolean; providerType: ProviderType; injectedProviderName: string; blockchainIsLoaded: boolean; - hasBeenSeen: boolean; + userEthBalanceInWei: BigNumber; + tokenByAddress: TokenByAddress; } interface ConnectedDispatch { @@ -30,6 +33,8 @@ const mapStateToProps = (state: State): ConnectedState => ({ providerType: state.providerType, injectedProviderName: state.injectedProviderName, blockchainIsLoaded: state.blockchainIsLoaded, + userEthBalanceInWei: state.userEtherBalanceInWei, + tokenByAddress: state.tokenByAddress, hasBeenSeen: state.hasPortalOnboardingBeenSeen, }); diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts index f8710b349..9dc1d492c 100644 --- a/packages/website/ts/utils/constants.ts +++ b/packages/website/ts/utils/constants.ts @@ -4,6 +4,9 @@ import { BigNumber } from '@0xproject/utils'; export const constants = { DECIMAL_PLACES_ETH: 18, DECIMAL_PLACES_ZRX: 18, + ETHER_TOKEN_SYMBOL: 'WETH', + ZRX_TOKEN_SYMBOL: 'ZRX', + ETHER_SYMBOL: 'ETH', GENESIS_ORDER_BLOCK_BY_NETWORK_ID: { 1: 4145578, 42: 3117574, diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index c0d055070..b9d962b75 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -321,4 +321,9 @@ export const utils = { shouldShowPortalV2(): boolean { return this.isDevelopment() || this.isStaging() || this.isDogfood(); }, + getEthToken(tokenByAddress: TokenByAddress): Token { + const tokens = _.values(tokenByAddress); + const etherToken = _.find(tokens, { symbol: constants.ETHER_TOKEN_SYMBOL }); + return etherToken; + }, }; -- cgit v1.2.3