aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorfragosti <francesco.agosti93@gmail.com>2018-05-23 01:15:58 +0800
committerfragosti <francesco.agosti93@gmail.com>2018-05-25 01:51:06 +0800
commit7af77d3eb0a73a0bd27898f5d3842c7dc7afef77 (patch)
tree9e054751e325965ce7c0d6ab18dbbd7447808751 /packages
parentde1ff52de3c9953dfb60283c8025b73d6e417029 (diff)
downloaddexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.tar
dexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.tar.gz
dexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.tar.bz2
dexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.tar.lz
dexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.tar.xz
dexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.tar.zst
dexon-sol-tools-7af77d3eb0a73a0bd27898f5d3842c7dc7afef77.zip
Basic onboarding flow infrastructure set up
Diffstat (limited to 'packages')
-rw-r--r--packages/typescript-typings/types/react-highlight/index.d.ts1
-rw-r--r--packages/typescript-typings/types/react-joyride/index.d.ts54
-rw-r--r--packages/website/package.json1
-rw-r--r--packages/website/ts/components/onboarding/onboarding_flow.tsx31
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx29
-rw-r--r--packages/website/ts/components/portal/portal.tsx50
-rw-r--r--packages/website/ts/components/relayer_index/relayer_grid_tile.tsx12
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx3
-rw-r--r--packages/website/ts/components/ui/container.tsx16
-rw-r--r--packages/website/ts/components/ui/island.tsx33
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx12
-rw-r--r--packages/website/ts/containers/portal_onboarding_flow.ts23
-rw-r--r--packages/website/ts/redux/dispatcher.ts7
-rw-r--r--packages/website/ts/redux/reducer.ts21
-rw-r--r--packages/website/ts/types.ts8
-rw-r--r--packages/website/ts/utils/style.ts4
16 files changed, 268 insertions, 37 deletions
diff --git a/packages/typescript-typings/types/react-highlight/index.d.ts b/packages/typescript-typings/types/react-highlight/index.d.ts
index 875721533..e0bb910d8 100644
--- a/packages/typescript-typings/types/react-highlight/index.d.ts
+++ b/packages/typescript-typings/types/react-highlight/index.d.ts
@@ -1 +1,2 @@
declare module 'react-highlight';
+
diff --git a/packages/typescript-typings/types/react-joyride/index.d.ts b/packages/typescript-typings/types/react-joyride/index.d.ts
new file mode 100644
index 000000000..21e46074f
--- /dev/null
+++ b/packages/typescript-typings/types/react-joyride/index.d.ts
@@ -0,0 +1,54 @@
+// 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 interface Step {
+ title?: string;
+ content: React.ReactNode;
+ target: string;
+ placement?: "top" | "top-left" | "top-right" | "bottom" | "bottom-left" | "bottom-right" | "right" | "left";
+ type?: "click" | "hover";
+ isFixed?: boolean;
+ allowClicksThruHole?: boolean;
+ disableBeacon?: boolean;
+ style?: StyleOptions;
+ [prop: string]: any;
+ }
+
+ export interface Props {
+ steps?: Step[];
+ beaconComponent?: React.ComponentClass;
+ run?: boolean;
+ stepIndex?: number;
+ callback?: (options: any) => void;
+ debug?: boolean;
+ styles?: { options: StyleOptions };
+ }
+
+ export interface State {
+ action: string,
+ controlled: boolean,
+ index: number,
+ lifecycle: string,
+ size: 0,
+ status: string,
+ }
+
+ export default class Joyride extends React.Component<Props, State> {
+ constructor(props: Props);
+
+ static defaultProps: Props;
+ }
+} \ No newline at end of file
diff --git a/packages/website/package.json b/packages/website/package.json
index cd0bfaf5e..484639746 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -42,6 +42,7 @@
"react-document-title": "^2.0.3",
"react-dom": "15.6.1",
"react-ga": "^2.4.1",
+ "react-joyride": "^2.0.0-11",
"react-redux": "^5.0.3",
"react-router-dom": "^4.1.1",
"react-scroll": "^1.5.2",
diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx
new file mode 100644
index 000000000..5bbf84e1b
--- /dev/null
+++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx
@@ -0,0 +1,31 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+import Joyride, { Step, StyleOptions } from 'react-joyride';
+
+import { zIndex } from 'ts/utils/style';
+
+interface OnboardingFlowProps {
+ steps: Step[];
+ stepIndex?: number;
+ isRunning: boolean;
+}
+
+const style: StyleOptions = {
+ zIndex: zIndex.overlay,
+};
+
+// Wrapper around Joyride with defaults and styles set
+export class OnboardingFlow extends React.Component<OnboardingFlowProps> {
+ public render(): React.ReactNode {
+ const { steps, stepIndex, isRunning } = this.props;
+ return (
+ <Joyride
+ run={isRunning}
+ debug={true}
+ steps={steps}
+ stepIndex={stepIndex}
+ styles={{ options: style }}
+ />
+ );
+ }
+};
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
new file mode 100644
index 000000000..57b209fac
--- /dev/null
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -0,0 +1,29 @@
+import * as React from 'react';
+
+import { OnboardingFlow } from 'ts/components/onboarding/onboarding_flow';
+
+export interface PortalOnboardingFlowProps {
+ stepIndex: number;
+ isRunning: boolean;
+}
+
+const steps = [
+ {
+ target: '.wallet',
+ content: 'Hey!',
+ placement: 'right',
+ disableBeacon: true,
+ },
+];
+
+export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlow> {
+ public render(): React.ReactNode {
+ return (
+ <OnboardingFlow
+ steps={steps}
+ stepIndex={this.props.stepIndex}
+ isRunning={this.props.isRunning}
+ />
+ )
+ }
+};
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index 1bd318c28..a4e3a006e 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -19,8 +19,11 @@ import { TextHeader } from 'ts/components/portal/text_header';
import { RelayerIndex } from 'ts/components/relayer_index/relayer_index';
import { TokenBalances } from 'ts/components/token_balances';
import { TopBar, TopBarDisplayType } from 'ts/components/top_bar/top_bar';
+import { PortalOnboardingFlow } from 'ts/containers/portal_onboarding_flow';
+import { Island } from 'ts/components/ui/island';
import { TradeHistory } from 'ts/components/trade_history/trade_history';
import { FlashMessage } from 'ts/components/ui/flash_message';
+import { Container } from 'ts/components/ui/container';
import { Wallet } from 'ts/components/wallet/wallet';
import { GenerateOrderForm } from 'ts/containers/generate_order_form';
import { localStorage } from 'ts/local_storage/local_storage';
@@ -183,6 +186,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
: TokenVisibility.TRACKED;
return (
<div style={styles.root}>
+ <PortalOnboardingFlow />
<DocumentTitle title="0x Portal DApp" />
<TopBar
userAddress={this.props.userAddress}
@@ -278,25 +282,37 @@ export class Portal extends React.Component<PortalProps, PortalState> {
const allTokens = _.values(this.props.tokenByAddress);
const trackedTokens = _.filter(allTokens, t => t.isTracked);
return (
- <Wallet
- userAddress={this.props.userAddress}
- networkId={this.props.networkId}
- blockchain={this._blockchain}
- blockchainIsLoaded={this.props.blockchainIsLoaded}
- blockchainErr={this.props.blockchainErr}
- dispatcher={this.props.dispatcher}
- tokenByAddress={this.props.tokenByAddress}
- trackedTokens={trackedTokens}
- userEtherBalanceInWei={this.props.userEtherBalanceInWei}
- lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
- injectedProviderName={this.props.injectedProviderName}
- providerType={this.props.providerType}
- onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)}
- onAddToken={this._onAddToken.bind(this)}
- onRemoveToken={this._onRemoveToken.bind(this)}
- />
+ <div>
+ <Wallet
+ userAddress={this.props.userAddress}
+ networkId={this.props.networkId}
+ blockchain={this._blockchain}
+ blockchainIsLoaded={this.props.blockchainIsLoaded}
+ blockchainErr={this.props.blockchainErr}
+ dispatcher={this.props.dispatcher}
+ tokenByAddress={this.props.tokenByAddress}
+ trackedTokens={trackedTokens}
+ userEtherBalanceInWei={this.props.userEtherBalanceInWei}
+ lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+ injectedProviderName={this.props.injectedProviderName}
+ providerType={this.props.providerType}
+ onToggleLedgerDialog={this._onToggleLedgerDialog.bind(this)}
+ onAddToken={this._onAddToken.bind(this)}
+ onRemoveToken={this._onRemoveToken.bind(this)}
+ />
+ <Container marginTop="15px">
+ <Island>
+ {/** TODO: Implement real styles. */}
+ <p onClick={this._startOnboarding.bind(this)}>Start onboarding flow.</p>
+ </Island>
+ </Container>
+ </div>
);
}
+
+ private _startOnboarding(): void {
+ this.props.dispatcher.updatePortalOnboardingShowing(true);
+ }
private _renderWalletSection(): React.ReactNode {
return <Section header={<TextHeader labelText="Your Account" />} body={this._renderWallet()} />;
}
diff --git a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
index dc9eeb29d..23c2f0b56 100644
--- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
@@ -4,6 +4,7 @@ import { GridTile } from 'material-ui/GridList';
import * as React from 'react';
import { TopTokens } from 'ts/components/relayer_index/relayer_top_tokens';
+import { Island } from 'ts/components/ui/island';
import { TokenIcon } from 'ts/components/ui/token_icon';
import { Token, WebsiteBackendRelayerInfo } from 'ts/types';
import { colors } from 'ts/utils/colors';
@@ -15,13 +16,6 @@ export interface RelayerGridTileProps {
const styles: Styles = {
root: {
- backgroundColor: colors.white,
- borderBottomRightRadius: 10,
- borderBottomLeftRadius: 10,
- borderTopRightRadius: 10,
- borderTopLeftRadius: 10,
- boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`,
- overflow: 'hidden',
boxSizing: 'border-box',
},
innerDiv: {
@@ -68,7 +62,7 @@ const FALLBACK_IMG_SRC = '/images/landing/hero_chip_image.png';
export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (props: RelayerGridTileProps) => {
const link = props.relayerInfo.appUrl || props.relayerInfo.url;
return (
- <GridTile style={styles.root}>
+ <Island style={styles.root} Component={GridTile}>
<div style={styles.innerDiv}>
<a href={link} target="_blank" style={{ textDecoration: 'none' }}>
<ImgWithFallback
@@ -91,7 +85,7 @@ export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (
</div>
</div>
</div>
- </GridTile>
+ </Island>
);
};
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index f2d0c6177..3f11f9779 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -20,6 +20,7 @@ import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/ty
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
+import { zIndex } from 'ts/utils/style';
export enum TopBarDisplayType {
Default,
@@ -59,7 +60,7 @@ const styles: Styles = {
width: '100%',
position: 'relative',
top: 0,
- zIndex: 1100,
+ zIndex: zIndex.topBar,
paddingBottom: 1,
},
bottomBar: {
diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx
new file mode 100644
index 000000000..7565dd1ae
--- /dev/null
+++ b/packages/website/ts/components/ui/container.tsx
@@ -0,0 +1,16 @@
+import * as React from 'react';
+
+interface ContainerProps {
+ marginTop?: string | number;
+ marginBottom?: string | number;
+ marginRight?: string | number;
+ marginLeft?: string | number;
+ children?: React.ReactNode;
+}
+
+export const Container: React.StatelessComponent<ContainerProps> = (props: ContainerProps) => {
+ const { children, ...style } = props;
+ return <div style={style}>{children}</div>;
+};
+
+Container.displayName = 'Container';
diff --git a/packages/website/ts/components/ui/island.tsx b/packages/website/ts/components/ui/island.tsx
new file mode 100644
index 000000000..da3602c3e
--- /dev/null
+++ b/packages/website/ts/components/ui/island.tsx
@@ -0,0 +1,33 @@
+import * as React from 'react';
+import { Styleable } from 'ts/types';
+import { colors } from 'ts/utils/colors';
+
+export interface IslandProps {
+ style?: React.CSSProperties;
+ children?: React.ReactNode;
+ className?: string;
+ Component?: string | React.ComponentClass<any> | React.StatelessComponent<any>;
+}
+
+const defaultStyle: React.CSSProperties = {
+ backgroundColor: colors.white,
+ borderBottomRightRadius: 10,
+ borderBottomLeftRadius: 10,
+ borderTopRightRadius: 10,
+ borderTopLeftRadius: 10,
+ boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`,
+ overflow: 'hidden',
+};
+
+export const Island: React.StatelessComponent<IslandProps> = (props: IslandProps) => (
+ <props.Component style={{...defaultStyle, ...props.style}} className={props.className}>
+ {props.children}
+ </props.Component>
+);
+
+Island.defaultProps = {
+ Component: 'div',
+ style: {},
+};
+
+Island.displayName = 'Island';
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index d0354580d..1790f7258 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -25,6 +25,7 @@ import { Blockchain } from 'ts/blockchain';
import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle';
import { IconButton } from 'ts/components/ui/icon_button';
import { Identicon } from 'ts/components/ui/identicon';
+import { Island } from 'ts/components/ui/island';
import { TokenIcon } from 'ts/components/ui/token_icon';
import { WalletDisconnectedItem } from 'ts/components/wallet/wallet_disconnected_item';
import { WrapEtherItem } from 'ts/components/wallet/wrap_ether_item';
@@ -84,13 +85,6 @@ interface AccessoryItemConfig {
const styles: Styles = {
root: {
width: '100%',
- backgroundColor: colors.white,
- borderBottomRightRadius: 10,
- borderBottomLeftRadius: 10,
- borderTopRightRadius: 10,
- borderTopLeftRadius: 10,
- boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`,
- overflow: 'hidden',
},
headerItemInnerDiv: {
paddingLeft: 65,
@@ -198,11 +192,11 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
const isReadyToRender = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError;
const isAddressAvailable = !_.isEmpty(this.props.userAddress);
return (
- <div className="flex flex-column" style={styles.root}>
+ <Island className="flex flex-column" style={styles.root}>
{isReadyToRender && isAddressAvailable
? _.concat(this._renderConnectedHeaderRows(), this._renderBody(), this._renderFooterRows())
: _.concat(this._renderDisconnectedHeaderRows(), this._renderDisconnectedRows())}
- </div>
+ </Island>
);
}
private _renderDisconnectedHeaderRows(): React.ReactElement<{}> {
diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts
new file mode 100644
index 000000000..46c23f62f
--- /dev/null
+++ b/packages/website/ts/containers/portal_onboarding_flow.ts
@@ -0,0 +1,23 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+
+import {
+ PortalOnboardingFlow as PortalOnboardingFlowComponent,
+ PortalOnboardingFlowProps as PortalOnboardingFlowComponentProps,
+} from 'ts/components/onboarding/portal_onboarding_flow';
+import { State } from 'ts/redux/reducer';
+
+interface ConnectedState {
+ stepIndex: number;
+ isRunning: boolean;
+}
+
+const mapStateToProps = (state: State, ownProps: PortalOnboardingFlowComponentProps): ConnectedState => {
+ return {
+ stepIndex: state.portalOnboardingStep,
+ isRunning: state.isPortalOnboardingShowing,
+ };
+};
+
+export const PortalOnboardingFlow: React.ComponentClass<PortalOnboardingFlowComponentProps> = connect(mapStateToProps)(PortalOnboardingFlowComponent);
diff --git a/packages/website/ts/redux/dispatcher.ts b/packages/website/ts/redux/dispatcher.ts
index 340b80d49..0b4cc3938 100644
--- a/packages/website/ts/redux/dispatcher.ts
+++ b/packages/website/ts/redux/dispatcher.ts
@@ -174,6 +174,13 @@ export class Dispatcher {
});
}
+ public updatePortalOnboardingShowing(isShowing: boolean): void {
+ this._dispatch({
+ data: isShowing,
+ type: ActionTypes.UpdatePortalOnboardingShowing,
+ });
+ }
+
// Docs
public updateCurrentDocsVersion(version: string): void {
this._dispatch({
diff --git a/packages/website/ts/redux/reducer.ts b/packages/website/ts/redux/reducer.ts
index fba6afa5d..e61345c87 100644
--- a/packages/website/ts/redux/reducer.ts
+++ b/packages/website/ts/redux/reducer.ts
@@ -40,6 +40,8 @@ export interface State {
lastForceTokenStateRefetch: number;
userAddress: string;
userEtherBalanceInWei: BigNumber;
+ portalOnboardingStep: number;
+ isPortalOnboardingShowing: boolean;
// Note: cache of supplied orderJSON in fill order step. Do not use for anything else.
userSuppliedOrderCache: Order;
@@ -80,7 +82,8 @@ const INITIAL_STATE: State = {
userAddress: '',
userEtherBalanceInWei: new BigNumber(0),
userSuppliedOrderCache: undefined,
-
+ portalOnboardingStep: 0,
+ isPortalOnboardingShowing: false,
// Docs
docsVersion: DEFAULT_DOCS_VERSION,
availableDocVersions: [DEFAULT_DOCS_VERSION],
@@ -293,6 +296,22 @@ export function reducer(state: State = INITIAL_STATE, action: Action): State {
};
}
+ case ActionTypes.UpdatePortalOnboardingStep: {
+ const portalOnboardingStep = action.data;
+ return {
+ ...state,
+ portalOnboardingStep,
+ };
+ }
+
+ case ActionTypes.UpdatePortalOnboardingShowing: {
+ const isPortalOnboardingShowing = action.data;
+ return {
+ ...state,
+ isPortalOnboardingShowing,
+ };
+ }
+
// Docs
case ActionTypes.UpdateLibraryVersion: {
return {
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index 294a58f64..aca3edae8 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -1,6 +1,7 @@
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
+import * as React from 'react';
export enum Side {
Receive = 'RECEIVE',
@@ -21,6 +22,11 @@ export interface TokenByAddress {
[address: string]: Token;
}
+export interface Styleable {
+ style: React.CSSProperties;
+ children: React.ReactNode;
+}
+
export interface AssetToken {
address?: string;
amount?: BigNumber;
@@ -125,6 +131,8 @@ export enum ActionTypes {
UpdateUserSuppliedOrderCache = 'UPDATE_USER_SUPPLIED_ORDER_CACHE',
UpdateOrderFillAmount = 'UPDATE_ORDER_FILL_AMOUNT',
UpdateShouldBlockchainErrDialogBeOpen = 'UPDATE_SHOULD_BLOCKCHAIN_ERR_DIALOG_BE_OPEN',
+ UpdatePortalOnboardingStep = 'UPDATE_ONBOARDING_STEP',
+ UpdatePortalOnboardingShowing = 'UPDATE_PORTAL_ONBOARDING_SHOWING',
// Docs
UpdateLibraryVersion = 'UPDATE_LIBRARY_VERSION',
diff --git a/packages/website/ts/utils/style.ts b/packages/website/ts/utils/style.ts
new file mode 100644
index 000000000..f3593b198
--- /dev/null
+++ b/packages/website/ts/utils/style.ts
@@ -0,0 +1,4 @@
+export const zIndex = {
+ topBar: 1100,
+ overlay: 1101,
+}; \ No newline at end of file