Implement initial relayer grid
This commit is contained in:
parent
674e56cea6
commit
250d97a7c4
@ -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,6 +59,7 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
|
||||
{this._renderMenuItemWithIcon('Wrap ETH', 'zmdi-circle-o')}
|
||||
</MenuItem>
|
||||
{configs.ENVIRONMENT === Environments.DEVELOPMENT && (
|
||||
<div>
|
||||
<MenuItem
|
||||
style={this.props.menuItemStyle}
|
||||
className="py2"
|
||||
@ -67,6 +68,15 @@ export class PortalMenu extends React.Component<PortalMenuProps, PortalMenuState
|
||||
>
|
||||
{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);
|
||||
|
@ -490,4 +490,12 @@ export interface TokenState {
|
||||
allowance: BigNumber;
|
||||
isLoaded: boolean;
|
||||
}
|
||||
|
||||
export interface RelayerInfo {
|
||||
headerUrl: string;
|
||||
id: string;
|
||||
name: string;
|
||||
marketShare: number;
|
||||
topTokens: Token[];
|
||||
}
|
||||
// tslint:disable:max-file-line-count
|
||||
|
Loading…
x
Reference in New Issue
Block a user