Implement initial relayer grid
This commit is contained in:
		@@ -15,6 +15,7 @@ import { EthWrappers } from 'ts/components/eth_wrappers';
 | 
			
		||||
import { FillOrder } from 'ts/components/fill_order';
 | 
			
		||||
import { Footer } from 'ts/components/footer';
 | 
			
		||||
import { PortalMenu } from 'ts/components/portal_menu';
 | 
			
		||||
import { RelayerIndex } from 'ts/components/relayer_index/relayer_index';
 | 
			
		||||
import { TokenBalances } from 'ts/components/token_balances';
 | 
			
		||||
import { TopBar } from 'ts/components/top_bar/top_bar';
 | 
			
		||||
import { TradeHistory } from 'ts/components/trade_history/trade_history';
 | 
			
		||||
@@ -155,6 +156,7 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
 | 
			
		||||
        const updateShouldBlockchainErrDialogBeOpen = this.props.dispatcher.updateShouldBlockchainErrDialogBeOpen.bind(
 | 
			
		||||
            this.props.dispatcher,
 | 
			
		||||
        );
 | 
			
		||||
        const isDevelopment = configs.ENVIRONMENT === Environments.DEVELOPMENT;
 | 
			
		||||
        const portalStyle: React.CSSProperties = {
 | 
			
		||||
            minHeight: '100vh',
 | 
			
		||||
            display: 'flex',
 | 
			
		||||
@@ -204,12 +206,18 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
 | 
			
		||||
                                    <div className="py2" style={{ backgroundColor: colors.grey50 }}>
 | 
			
		||||
                                        {this.props.blockchainIsLoaded ? (
 | 
			
		||||
                                            <Switch>
 | 
			
		||||
                                                {configs.ENVIRONMENT === Environments.DEVELOPMENT && (
 | 
			
		||||
                                                {isDevelopment && (
 | 
			
		||||
                                                    <Route
 | 
			
		||||
                                                        path={`${WebsitePaths.Portal}/wallet`}
 | 
			
		||||
                                                        render={this._renderWallet.bind(this)}
 | 
			
		||||
                                                    />
 | 
			
		||||
                                                )}
 | 
			
		||||
                                                {isDevelopment && (
 | 
			
		||||
                                                    <Route
 | 
			
		||||
                                                        path={`${WebsitePaths.Portal}/relayers`}
 | 
			
		||||
                                                        render={this._renderRelayers.bind(this)}
 | 
			
		||||
                                                    />
 | 
			
		||||
                                                )}
 | 
			
		||||
                                                <Route
 | 
			
		||||
                                                    path={`${WebsitePaths.Portal}/weth`}
 | 
			
		||||
                                                    render={this._renderEthWrapper.bind(this)}
 | 
			
		||||
@@ -313,6 +321,15 @@ export class Portal extends React.Component<PortalAllProps, PortalAllState> {
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    private _renderRelayers() {
 | 
			
		||||
        return (
 | 
			
		||||
            <div className="flex flex-center">
 | 
			
		||||
                <div className="mx-auto" style={{ width: 800 }}>
 | 
			
		||||
                    <RelayerIndex networkId={this.props.networkId} />
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    private _renderEthWrapper() {
 | 
			
		||||
        return (
 | 
			
		||||
            <EthWrappers
 | 
			
		||||
 
 | 
			
		||||
@@ -59,14 +59,24 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
 | 
			
		||||
                    {this._renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')}
 | 
			
		||||
                </MenuItem>
 | 
			
		||||
                {configs.ENVIRONMENT === Environments.DEVELOPMENT && (
 | 
			
		||||
                    <MenuItem
 | 
			
		||||
                        style={this.props.menuItemStyle}
 | 
			
		||||
                        className="py2"
 | 
			
		||||
                        to={`${WebsitePaths.Portal}/wallet`}
 | 
			
		||||
                        onClick={this.props.onClick.bind(this)}
 | 
			
		||||
                    >
 | 
			
		||||
                        {this._renderMenuItemWithIcon('Wallet', 'zmdi-balance-wallet')}
 | 
			
		||||
                    </MenuItem>
 | 
			
		||||
                    <div>
 | 
			
		||||
                        <MenuItem
 | 
			
		||||
                            style={this.props.menuItemStyle}
 | 
			
		||||
                            className="py2"
 | 
			
		||||
                            to={`${WebsitePaths.Portal}/wallet`}
 | 
			
		||||
                            onClick={this.props.onClick.bind(this)}
 | 
			
		||||
                        >
 | 
			
		||||
                            {this._renderMenuItemWithIcon('Wallet', 'zmdi-balance-wallet')}
 | 
			
		||||
                        </MenuItem>
 | 
			
		||||
                        <MenuItem
 | 
			
		||||
                            style={this.props.menuItemStyle}
 | 
			
		||||
                            className="py2"
 | 
			
		||||
                            to={`${WebsitePaths.Portal}/relayers`}
 | 
			
		||||
                            onClick={this.props.onClick.bind(this)}
 | 
			
		||||
                        >
 | 
			
		||||
                            {this._renderMenuItemWithIcon('Relayers', 'zmdi-input-antenna')}
 | 
			
		||||
                        </MenuItem>
 | 
			
		||||
                    </div>
 | 
			
		||||
                )}
 | 
			
		||||
            </div>
 | 
			
		||||
        );
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,84 @@
 | 
			
		||||
import { colors, Styles } from '@0xproject/react-shared';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import { GridTile } from 'material-ui/GridList';
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
 | 
			
		||||
import { TopTokens } from 'ts/components/relayer_index/relayer_top_tokens';
 | 
			
		||||
import { TokenIcon } from 'ts/components/ui/token_icon';
 | 
			
		||||
import { RelayerInfo, Token } from 'ts/types';
 | 
			
		||||
 | 
			
		||||
export interface RelayerGridTileProps {
 | 
			
		||||
    relayerInfo: RelayerInfo;
 | 
			
		||||
    networkId: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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: {
 | 
			
		||||
        padding: 6,
 | 
			
		||||
        height: '100%',
 | 
			
		||||
        boxSizing: 'border-box',
 | 
			
		||||
    },
 | 
			
		||||
    header: {
 | 
			
		||||
        height: '50%',
 | 
			
		||||
        width: '100%',
 | 
			
		||||
        objectFit: 'cover',
 | 
			
		||||
        borderBottomRightRadius: 4,
 | 
			
		||||
        borderBottomLeftRadius: 4,
 | 
			
		||||
        borderTopRightRadius: 4,
 | 
			
		||||
        borderTopLeftRadius: 4,
 | 
			
		||||
    },
 | 
			
		||||
    body: {
 | 
			
		||||
        paddingLeft: 6,
 | 
			
		||||
        paddingRight: 6,
 | 
			
		||||
        height: '50%',
 | 
			
		||||
        width: '100%',
 | 
			
		||||
        boxSizing: 'border-box',
 | 
			
		||||
    },
 | 
			
		||||
    marketShareBar: {
 | 
			
		||||
        height: 14,
 | 
			
		||||
        width: '100%',
 | 
			
		||||
        backgroundColor: colors.mediumBlue,
 | 
			
		||||
    },
 | 
			
		||||
    subLabel: {
 | 
			
		||||
        fontSize: 12,
 | 
			
		||||
        color: colors.lightGrey,
 | 
			
		||||
    },
 | 
			
		||||
    relayerNameLabel: {
 | 
			
		||||
        fontSize: 16,
 | 
			
		||||
        fontWeight: 'bold',
 | 
			
		||||
        color: colors.black,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const RelayerGridTile: React.StatelessComponent<RelayerGridTileProps> = (props: RelayerGridTileProps) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <GridTile style={styles.root}>
 | 
			
		||||
            <div style={styles.innerDiv}>
 | 
			
		||||
                <img src={props.relayerInfo.headerUrl} style={styles.header} />
 | 
			
		||||
                <div style={styles.body}>
 | 
			
		||||
                    <div className="py1" style={styles.relayerNameLabel}>
 | 
			
		||||
                        {props.relayerInfo.name}
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div style={styles.marketShareBar} />
 | 
			
		||||
                    <div className="py1" style={styles.subLabel}>
 | 
			
		||||
                        Market share
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <TopTokens tokens={props.relayerInfo.topTokens} networkId={props.networkId} />
 | 
			
		||||
                    <div className="py1" style={styles.subLabel}>
 | 
			
		||||
                        Top tokens
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </GridTile>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
							
								
								
									
										118
									
								
								packages/website/ts/components/relayer_index/relayer_index.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										118
									
								
								packages/website/ts/components/relayer_index/relayer_index.tsx
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,118 @@
 | 
			
		||||
import { colors, Styles } from '@0xproject/react-shared';
 | 
			
		||||
import { GridList } from 'material-ui/GridList';
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
 | 
			
		||||
import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile';
 | 
			
		||||
import { RelayerInfo } from 'ts/types';
 | 
			
		||||
 | 
			
		||||
export interface RelayerIndexProps {
 | 
			
		||||
    networkId: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const styles: Styles = {
 | 
			
		||||
    root: {
 | 
			
		||||
        width: '100%',
 | 
			
		||||
    },
 | 
			
		||||
    item: {
 | 
			
		||||
        backgroundColor: colors.white,
 | 
			
		||||
        borderBottomRightRadius: 10,
 | 
			
		||||
        borderBottomLeftRadius: 10,
 | 
			
		||||
        borderTopRightRadius: 10,
 | 
			
		||||
        borderTopLeftRadius: 10,
 | 
			
		||||
        boxShadow: `0px 4px 6px ${colors.walletBoxShadow}`,
 | 
			
		||||
        overflow: 'hidden',
 | 
			
		||||
        padding: 4,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// TODO: replace fake data with real, remote data
 | 
			
		||||
const topTokens = [
 | 
			
		||||
    {
 | 
			
		||||
        address: '0x1dad4783cf3fe3085c1426157ab175a6119a04ba',
 | 
			
		||||
        decimals: 18,
 | 
			
		||||
        iconUrl: '/images/token_icons/makerdao.png',
 | 
			
		||||
        isRegistered: true,
 | 
			
		||||
        isTracked: true,
 | 
			
		||||
        name: 'Maker DAO',
 | 
			
		||||
        symbol: 'MKR',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        address: '0x323b5d4c32345ced77393b3530b1eed0f346429d',
 | 
			
		||||
        decimals: 18,
 | 
			
		||||
        iconUrl: '/images/token_icons/melon.png',
 | 
			
		||||
        isRegistered: true,
 | 
			
		||||
        isTracked: true,
 | 
			
		||||
        name: 'Melon Token',
 | 
			
		||||
        symbol: 'MLN',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        address: '0xb18845c260f680d5b9d84649638813e342e4f8c9',
 | 
			
		||||
        decimals: 18,
 | 
			
		||||
        iconUrl: '/images/token_icons/augur.png',
 | 
			
		||||
        isRegistered: true,
 | 
			
		||||
        isTracked: true,
 | 
			
		||||
        name: 'Augur Reputation Token',
 | 
			
		||||
        symbol: 'REP',
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const relayerInfos: RelayerInfo[] = [
 | 
			
		||||
    {
 | 
			
		||||
        id: '1',
 | 
			
		||||
        headerUrl: '/images/og_image.png',
 | 
			
		||||
        name: 'Radar Relay',
 | 
			
		||||
        marketShare: 0.5,
 | 
			
		||||
        topTokens,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        id: '2',
 | 
			
		||||
        headerUrl: '/images/og_image.png',
 | 
			
		||||
        name: 'Paradex',
 | 
			
		||||
        marketShare: 0.5,
 | 
			
		||||
        topTokens,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        id: '3',
 | 
			
		||||
        headerUrl: '/images/og_image.png',
 | 
			
		||||
        name: 'yo',
 | 
			
		||||
        marketShare: 0.5,
 | 
			
		||||
        topTokens,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        id: '4',
 | 
			
		||||
        headerUrl: '/images/og_image.png',
 | 
			
		||||
        name: 'test',
 | 
			
		||||
        marketShare: 0.5,
 | 
			
		||||
        topTokens,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        id: '5',
 | 
			
		||||
        headerUrl: '/images/og_image.png',
 | 
			
		||||
        name: 'blahg',
 | 
			
		||||
        marketShare: 0.5,
 | 
			
		||||
        topTokens,
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        id: '6',
 | 
			
		||||
        headerUrl: '/images/og_image.png',
 | 
			
		||||
        name: 'hello',
 | 
			
		||||
        marketShare: 0.5,
 | 
			
		||||
        topTokens,
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
const CELL_HEIGHT = 260;
 | 
			
		||||
const NUMBER_OF_COLUMNS = 4;
 | 
			
		||||
const GRID_PADDING = 16;
 | 
			
		||||
 | 
			
		||||
export const RelayerIndex: React.StatelessComponent<RelayerIndexProps> = (props: RelayerIndexProps) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <div style={styles.root}>
 | 
			
		||||
            <GridList cellHeight={CELL_HEIGHT} cols={NUMBER_OF_COLUMNS} padding={GRID_PADDING} style={styles.gridList}>
 | 
			
		||||
                {relayerInfos.map((relayerInfo: RelayerInfo) => (
 | 
			
		||||
                    <RelayerGridTile key={relayerInfo.id} relayerInfo={relayerInfo} networkId={props.networkId} />
 | 
			
		||||
                ))}
 | 
			
		||||
            </GridList>
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
@@ -0,0 +1,46 @@
 | 
			
		||||
import { colors, EtherscanLinkSuffixes, Styles, utils as sharedUtils } from '@0xproject/react-shared';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
import * as React from 'react';
 | 
			
		||||
 | 
			
		||||
import { TokenIcon } from 'ts/components/ui/token_icon';
 | 
			
		||||
import { Token } from 'ts/types';
 | 
			
		||||
 | 
			
		||||
export interface TopTokensProps {
 | 
			
		||||
    tokens: Token[];
 | 
			
		||||
    networkId: number;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const styles: Styles = {
 | 
			
		||||
    tokenLabel: {
 | 
			
		||||
        textDecoration: 'none',
 | 
			
		||||
        color: colors.mediumBlue,
 | 
			
		||||
    },
 | 
			
		||||
    followingTokenLabel: {
 | 
			
		||||
        paddingLeft: 16,
 | 
			
		||||
    },
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const TopTokens: React.StatelessComponent<TopTokensProps> = (props: TopTokensProps) => {
 | 
			
		||||
    return (
 | 
			
		||||
        <div className="flex">
 | 
			
		||||
            {_.map(props.tokens, (token: Token, index: number) => {
 | 
			
		||||
                const firstItemStyle = { ...styles.tokenLabel, ...styles.followingTokenLabel };
 | 
			
		||||
                const style = index !== 0 ? firstItemStyle : styles.tokenLabel;
 | 
			
		||||
                return (
 | 
			
		||||
                    <a
 | 
			
		||||
                        key={token.address}
 | 
			
		||||
                        href={tokenLinkFromToken(token, props.networkId)}
 | 
			
		||||
                        target="_blank"
 | 
			
		||||
                        style={style}
 | 
			
		||||
                    >
 | 
			
		||||
                        {token.symbol}
 | 
			
		||||
                    </a>
 | 
			
		||||
                );
 | 
			
		||||
            })}
 | 
			
		||||
        </div>
 | 
			
		||||
    );
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function tokenLinkFromToken(token: Token, networkId: number) {
 | 
			
		||||
    return sharedUtils.getEtherScanLinkIfExists(token.address, networkId, EtherscanLinkSuffixes.Address);
 | 
			
		||||
}
 | 
			
		||||
@@ -71,7 +71,7 @@ interface AccessoryItemConfig {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const styles: Styles = {
 | 
			
		||||
    wallet: {
 | 
			
		||||
    root: {
 | 
			
		||||
        width: 346,
 | 
			
		||||
        backgroundColor: colors.white,
 | 
			
		||||
        borderBottomRightRadius: 10,
 | 
			
		||||
@@ -174,7 +174,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
 | 
			
		||||
    }
 | 
			
		||||
    public render() {
 | 
			
		||||
        const isReadyToRender = this.props.blockchainIsLoaded && this.props.blockchainErr === BlockchainErrs.NoError;
 | 
			
		||||
        return <div style={styles.wallet}>{isReadyToRender && this._renderRows()}</div>;
 | 
			
		||||
        return <div style={styles.root}>{isReadyToRender && this._renderRows()}</div>;
 | 
			
		||||
    }
 | 
			
		||||
    private _renderRows() {
 | 
			
		||||
        const isAddressAvailable = !_.isEmpty(this.props.userAddress);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user