aboutsummaryrefslogtreecommitdiffstats
path: root/packages/website
diff options
context:
space:
mode:
Diffstat (limited to 'packages/website')
-rw-r--r--packages/website/md/docs/ethereum_types/installation.md11
-rw-r--r--packages/website/md/docs/ethereum_types/introduction.md1
-rw-r--r--packages/website/package.json4
-rw-r--r--packages/website/public/images/jobs/location1.pngbin0 -> 659608 bytes
-rw-r--r--packages/website/public/images/jobs/location2.pngbin0 -> 223872 bytes
-rw-r--r--packages/website/public/images/jobs/location3.pngbin0 -> 288733 bytes
-rw-r--r--packages/website/public/images/jobs/map.pngbin0 -> 271102 bytes
-rw-r--r--packages/website/public/images/jobs/office1.pngbin0 -> 482657 bytes
-rw-r--r--packages/website/public/images/jobs/office2.pngbin0 -> 479918 bytes
-rw-r--r--packages/website/public/images/jobs/office3.pngbin0 -> 480055 bytes
-rw-r--r--packages/website/translations/chinese.json1
-rw-r--r--packages/website/translations/english.json1
-rw-r--r--packages/website/translations/korean.json1
-rw-r--r--packages/website/translations/russian.json1
-rw-r--r--packages/website/translations/spanish.json1
-rw-r--r--packages/website/ts/blockchain.ts8
-rw-r--r--packages/website/ts/blockchain_watcher.ts3
-rw-r--r--packages/website/ts/components/dialogs/blockchain_err_dialog.tsx1
-rw-r--r--packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx6
-rw-r--r--packages/website/ts/components/dialogs/ledger_config_dialog.tsx4
-rw-r--r--packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx1
-rw-r--r--packages/website/ts/components/eth_weth_conversion_button.tsx2
-rw-r--r--packages/website/ts/components/eth_wrappers.tsx32
-rw-r--r--packages/website/ts/components/fill_order.tsx19
-rw-r--r--packages/website/ts/components/footer.tsx2
-rw-r--r--packages/website/ts/components/forms/subscribe_form.tsx123
-rw-r--r--packages/website/ts/components/generate_order/generate_order_form.tsx19
-rw-r--r--packages/website/ts/components/generate_order/new_token_form.tsx6
-rw-r--r--packages/website/ts/components/inputs/allowance_toggle.tsx11
-rw-r--r--packages/website/ts/components/inputs/balance_bounded_input.tsx2
-rw-r--r--packages/website/ts/components/inputs/expiration_input.tsx4
-rw-r--r--packages/website/ts/components/inputs/identicon_address_input.tsx1
-rw-r--r--packages/website/ts/components/inputs/token_input.tsx1
-rw-r--r--packages/website/ts/components/legacy_portal/legacy_portal.tsx21
-rw-r--r--packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx3
-rw-r--r--packages/website/ts/components/onboarding/onboarding_flow.tsx2
-rw-r--r--packages/website/ts/components/onboarding/onboarding_tooltip.tsx1
-rw-r--r--packages/website/ts/components/onboarding/portal_onboarding_flow.tsx74
-rw-r--r--packages/website/ts/components/portal/back_button.tsx2
-rw-r--r--packages/website/ts/components/portal/drawer_menu.tsx2
-rw-r--r--packages/website/ts/components/portal/menu.tsx5
-rw-r--r--packages/website/ts/components/portal/portal.tsx83
-rw-r--r--packages/website/ts/components/portal/section.tsx1
-rw-r--r--packages/website/ts/components/redirector.tsx (renamed from packages/website/ts/components/redirecter.tsx)5
-rw-r--r--packages/website/ts/components/relayer_index/relayer_grid_tile.tsx5
-rw-r--r--packages/website/ts/components/relayer_index/relayer_index.tsx35
-rw-r--r--packages/website/ts/components/relayer_index/relayer_top_tokens.tsx1
-rw-r--r--packages/website/ts/components/sidebar_header.tsx3
-rw-r--r--packages/website/ts/components/token_balances.tsx50
-rw-r--r--packages/website/ts/components/top_bar/provider_display.tsx3
-rw-r--r--packages/website/ts/components/top_bar/provider_picker.tsx2
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx24
-rw-r--r--packages/website/ts/components/trade_history/trade_history.tsx29
-rw-r--r--packages/website/ts/components/ui/button.tsx81
-rw-r--r--packages/website/ts/components/ui/container.tsx15
-rw-r--r--packages/website/ts/components/ui/copy_icon.tsx1
-rw-r--r--packages/website/ts/components/ui/drop_down.tsx3
-rw-r--r--packages/website/ts/components/ui/etherscan_icon.tsx1
-rw-r--r--packages/website/ts/components/ui/filled_image.tsx18
-rw-r--r--packages/website/ts/components/ui/input.tsx43
-rw-r--r--packages/website/ts/components/ui/island.tsx3
-rw-r--r--packages/website/ts/components/ui/lifecycle_raised_button.tsx5
-rw-r--r--packages/website/ts/components/ui/overlay.tsx3
-rw-r--r--packages/website/ts/components/ui/party.tsx1
-rw-r--r--packages/website/ts/components/ui/retry.tsx32
-rw-r--r--packages/website/ts/components/ui/swap_icon.tsx1
-rw-r--r--packages/website/ts/components/ui/text.tsx41
-rw-r--r--packages/website/ts/components/wallet/wallet.tsx99
-rw-r--r--packages/website/ts/components/wallet/wallet_disconnected_item.tsx3
-rw-r--r--packages/website/ts/components/wallet/wrap_ether_item.tsx5
-rw-r--r--packages/website/ts/containers/about.ts3
-rw-r--r--packages/website/ts/containers/connect_documentation.ts6
-rw-r--r--packages/website/ts/containers/ethereum_types_documentation.ts122
-rw-r--r--packages/website/ts/containers/faq.ts3
-rw-r--r--packages/website/ts/containers/generate_order_form.ts5
-rw-r--r--packages/website/ts/containers/inputs/allowance_toggle.ts41
-rw-r--r--packages/website/ts/containers/jobs.ts28
-rw-r--r--packages/website/ts/containers/json_schemas_documentation.ts9
-rw-r--r--packages/website/ts/containers/landing.ts3
-rw-r--r--packages/website/ts/containers/legacy_portal.ts2
-rw-r--r--packages/website/ts/containers/not_found.ts3
-rw-r--r--packages/website/ts/containers/order_utils_documentation.ts8
-rw-r--r--packages/website/ts/containers/portal.ts2
-rw-r--r--packages/website/ts/containers/portal_onboarding_flow.ts5
-rw-r--r--packages/website/ts/containers/smart_contracts_documentation.ts5
-rw-r--r--packages/website/ts/containers/sol_compiler_documentation.ts7
-rw-r--r--packages/website/ts/containers/sol_cov_documentation.ts7
-rw-r--r--packages/website/ts/containers/subproviders_documentation.ts6
-rw-r--r--packages/website/ts/containers/web3_wrapper_documentation.ts6
-rw-r--r--packages/website/ts/containers/wiki.ts3
-rw-r--r--packages/website/ts/containers/zero_ex_js_documentation.ts9
-rw-r--r--packages/website/ts/index.tsx18
-rw-r--r--packages/website/ts/local_storage/trade_history_storage.tsx2
-rw-r--r--packages/website/ts/pages/about/about.tsx1
-rw-r--r--packages/website/ts/pages/documentation/doc_page.tsx5
-rw-r--r--packages/website/ts/pages/faq/question.tsx1
-rw-r--r--packages/website/ts/pages/jobs/benefits.tsx109
-rw-r--r--packages/website/ts/pages/jobs/jobs.tsx81
-rw-r--r--packages/website/ts/pages/jobs/join_0x.tsx41
-rw-r--r--packages/website/ts/pages/jobs/list/header_item.tsx26
-rw-r--r--packages/website/ts/pages/jobs/list/list_item.tsx15
-rw-r--r--packages/website/ts/pages/jobs/mission.tsx56
-rw-r--r--packages/website/ts/pages/jobs/open_positions.tsx192
-rw-r--r--packages/website/ts/pages/jobs/photo_rail.tsx22
-rw-r--r--packages/website/ts/pages/jobs/teams.tsx90
-rw-r--r--packages/website/ts/pages/jobs/values.tsx60
-rw-r--r--packages/website/ts/pages/landing/landing.tsx77
-rw-r--r--packages/website/ts/pages/not_found.tsx4
-rw-r--r--packages/website/ts/pages/wiki/wiki.tsx10
-rw-r--r--packages/website/ts/schemas/validator.ts1
-rw-r--r--packages/website/ts/style/colors.ts (renamed from packages/website/ts/utils/colors.ts)2
-rw-r--r--packages/website/ts/style/theme.ts17
-rw-r--r--packages/website/ts/style/z_index.ts (renamed from packages/website/ts/utils/style.ts)0
-rw-r--r--packages/website/ts/types.ts12
-rw-r--r--packages/website/ts/utils/backend_client.ts21
-rw-r--r--packages/website/ts/utils/configs.ts1
-rw-r--r--packages/website/ts/utils/constants.ts1
-rw-r--r--packages/website/ts/utils/doc_utils.ts3
-rw-r--r--packages/website/ts/utils/error_reporter.ts3
-rw-r--r--packages/website/ts/utils/fetch_utils.ts32
-rw-r--r--packages/website/ts/utils/utils.ts22
-rw-r--r--packages/website/ts/utils/wallet_item_styles.ts2
122 files changed, 1741 insertions, 441 deletions
diff --git a/packages/website/md/docs/ethereum_types/installation.md b/packages/website/md/docs/ethereum_types/installation.md
new file mode 100644
index 000000000..5371cfa47
--- /dev/null
+++ b/packages/website/md/docs/ethereum_types/installation.md
@@ -0,0 +1,11 @@
+**Install**
+
+```bash
+yarn add ethereum-types
+```
+
+**Import**
+
+```typescript
+import { Provider } from 'ethereum-types';
+```
diff --git a/packages/website/md/docs/ethereum_types/introduction.md b/packages/website/md/docs/ethereum_types/introduction.md
new file mode 100644
index 000000000..43484cdd1
--- /dev/null
+++ b/packages/website/md/docs/ethereum_types/introduction.md
@@ -0,0 +1 @@
+Welcome to the [ethereum-types](https://github.com/0xProject/0x-monorepo/packages/ethereum-types) documentation! This package provides ethereum specific (but not library-specific) types that are meant to be shared between other ethereum packages.
diff --git a/packages/website/package.json b/packages/website/package.json
index a17964f2b..5287414c7 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -10,7 +10,7 @@
"build": "NODE_ENV=production webpack; exit 0;",
"clean": "shx rm -f public/bundle*",
"lint": "tslint --project . 'ts/**/*.ts' 'ts/**/*.tsx'",
- "watch": "webpack-dev-server --content-base public --https",
+ "watch_without_deps": "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"
@@ -37,6 +37,7 @@
"lodash": "^4.17.4",
"material-ui": "^0.17.1",
"moment": "2.21.0",
+ "polished": "^1.9.2",
"query-string": "^6.0.0",
"react": "15.6.1",
"react-copy-to-clipboard": "^4.2.3",
@@ -52,6 +53,7 @@
"redux": "^3.6.0",
"redux-devtools-extension": "^2.13.2",
"semver-sort": "0.0.4",
+ "styled-components": "^3.3.0",
"thenby": "^1.2.3",
"truffle-contract": "2.0.1",
"web3": "^0.20.0",
diff --git a/packages/website/public/images/jobs/location1.png b/packages/website/public/images/jobs/location1.png
new file mode 100644
index 000000000..bfda47576
--- /dev/null
+++ b/packages/website/public/images/jobs/location1.png
Binary files differ
diff --git a/packages/website/public/images/jobs/location2.png b/packages/website/public/images/jobs/location2.png
new file mode 100644
index 000000000..c05f9403f
--- /dev/null
+++ b/packages/website/public/images/jobs/location2.png
Binary files differ
diff --git a/packages/website/public/images/jobs/location3.png b/packages/website/public/images/jobs/location3.png
new file mode 100644
index 000000000..34b2e5380
--- /dev/null
+++ b/packages/website/public/images/jobs/location3.png
Binary files differ
diff --git a/packages/website/public/images/jobs/map.png b/packages/website/public/images/jobs/map.png
new file mode 100644
index 000000000..7b85ff66e
--- /dev/null
+++ b/packages/website/public/images/jobs/map.png
Binary files differ
diff --git a/packages/website/public/images/jobs/office1.png b/packages/website/public/images/jobs/office1.png
new file mode 100644
index 000000000..f6e6d9163
--- /dev/null
+++ b/packages/website/public/images/jobs/office1.png
Binary files differ
diff --git a/packages/website/public/images/jobs/office2.png b/packages/website/public/images/jobs/office2.png
new file mode 100644
index 000000000..65f97dcad
--- /dev/null
+++ b/packages/website/public/images/jobs/office2.png
Binary files differ
diff --git a/packages/website/public/images/jobs/office3.png b/packages/website/public/images/jobs/office3.png
new file mode 100644
index 000000000..1dfcb9c58
--- /dev/null
+++ b/packages/website/public/images/jobs/office3.png
Binary files differ
diff --git a/packages/website/translations/chinese.json b/packages/website/translations/chinese.json
index 966457a93..3e9f21370 100644
--- a/packages/website/translations/chinese.json
+++ b/packages/website/translations/chinese.json
@@ -59,6 +59,7 @@
"SOL_COMPILER": "Solidity Compiler",
"JSON_SCHEMAS": "JSON Schemas",
"SOL_COV": "Solidity Coverage",
+ "ETHEREUM_TYPES": "Ethereum Types",
"SUBPROVIDERS": "Subproviders",
"BLOG": "博客",
"FORUM": "论坛",
diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json
index f3acea3be..04fb0507a 100644
--- a/packages/website/translations/english.json
+++ b/packages/website/translations/english.json
@@ -60,6 +60,7 @@
"SOL_COMPILER": "Solidity Compiler",
"JSON_SCHEMAS": "JSON Schemas",
"SOL_COV": "Solidity Coverage",
+ "ETHEREUM_TYPES": "Ethereum Types",
"SUBPROVIDERS": "Subproviders",
"BLOG": "blog",
"FORUM": "forum",
diff --git a/packages/website/translations/korean.json b/packages/website/translations/korean.json
index 7414207f7..c38de6677 100644
--- a/packages/website/translations/korean.json
+++ b/packages/website/translations/korean.json
@@ -59,6 +59,7 @@
"SOL_COMPILER": "Solidity Compiler",
"JSON_SCHEMAS": "JSON Schemas",
"SOL_COV": "Solidity Coverage",
+ "ETHEREUM_TYPES": "Ethereum Types",
"SUBPROVIDERS": "Subproviders",
"BLOG": "블로그",
"FORUM": "포럼",
diff --git a/packages/website/translations/russian.json b/packages/website/translations/russian.json
index 75ab02a27..a7e06d646 100644
--- a/packages/website/translations/russian.json
+++ b/packages/website/translations/russian.json
@@ -59,6 +59,7 @@
"SOL_COMPILER": "Solidity Compiler",
"JSON_SCHEMAS": "JSON Schemas",
"SOL_COV": "Solidity Coverage",
+ "ETHEREUM_TYPES": "Ethereum Types",
"SUBPROVIDERS": "Subproviders",
"BLOG": "Блог",
"FORUM": "Форум",
diff --git a/packages/website/translations/spanish.json b/packages/website/translations/spanish.json
index 8f537ea40..5a8920f61 100644
--- a/packages/website/translations/spanish.json
+++ b/packages/website/translations/spanish.json
@@ -60,6 +60,7 @@
"SOL_COMPILER": "Solidity Compiler",
"JSON_SCHEMAS": "JSON Schemas",
"SOL_COV": "Solidity Coverage",
+ "ETHEREUM_TYPES": "Ethereum Types",
"SUBPROVIDERS": "Subproviders",
"BLOG": "blog",
"FORUM": "foro",
diff --git a/packages/website/ts/blockchain.ts b/packages/website/ts/blockchain.ts
index 6e4d03e27..c955e1033 100644
--- a/packages/website/ts/blockchain.ts
+++ b/packages/website/ts/blockchain.ts
@@ -132,7 +132,7 @@ export class Blockchain {
return provider;
}
- constructor(dispatcher: Dispatcher, isSalePage: boolean = false) {
+ constructor(dispatcher: Dispatcher) {
this._dispatcher = dispatcher;
const defaultGasPrice = GWEI_IN_WEI * 30;
this._defaultGasPrice = new BigNumber(defaultGasPrice);
@@ -577,13 +577,13 @@ export class Blockchain {
trackedTokensByAddress[token.address] = token;
});
if (!_.isUndefined(this._userAddressIfExists)) {
- _.each(trackedTokensByAddress, (token: Token, address: string) => {
+ _.each(trackedTokensByAddress, (token: Token) => {
trackedTokenStorage.addTrackedTokenToUser(this._userAddressIfExists, this.networkId, token);
});
}
} else {
// Properly set all tokenRegistry tokens `isTracked` to true if they are in the existing trackedTokens array
- _.each(trackedTokensByAddress, (trackedToken: Token, address: string) => {
+ _.each(trackedTokensByAddress, (_trackedToken: Token, address: string) => {
if (!_.isUndefined(tokenRegistryTokensByAddress[address])) {
tokenRegistryTokensByAddress[address].isTracked = true;
}
@@ -754,7 +754,7 @@ export class Blockchain {
const tokenRegistryTokens = await this._contractWrappers.tokenRegistry.getTokensAsync();
const tokenByAddress: TokenByAddress = {};
- _.each(tokenRegistryTokens, (t: ZeroExToken, i: number) => {
+ _.each(tokenRegistryTokens, (t: ZeroExToken) => {
// HACK: For now we have a hard-coded list of iconUrls for the dummyTokens
// TODO: Refactor this out and pull the iconUrl directly from the TokenRegistry
const iconUrl = configs.ICON_URL_BY_SYMBOL[t.symbol];
diff --git a/packages/website/ts/blockchain_watcher.ts b/packages/website/ts/blockchain_watcher.ts
index 0d376bc74..3890a9e57 100644
--- a/packages/website/ts/blockchain_watcher.ts
+++ b/packages/website/ts/blockchain_watcher.ts
@@ -1,8 +1,7 @@
-import { BigNumber, intervalUtils, logUtils, promisify } from '@0xproject/utils';
+import { BigNumber, intervalUtils, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import { Dispatcher } from 'ts/redux/dispatcher';
-import { utils } from 'ts/utils/utils';
export class BlockchainWatcher {
private _dispatcher: Dispatcher;
diff --git a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
index 7156e700b..b968a3147 100644
--- a/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
+++ b/packages/website/ts/components/dialogs/blockchain_err_dialog.tsx
@@ -1,5 +1,4 @@
import { colors, Networks } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import * as React from 'react';
diff --git a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
index d647bba80..9ac78e80e 100644
--- a/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
+++ b/packages/website/ts/components/dialogs/eth_weth_conversion_dialog.tsx
@@ -20,7 +20,7 @@ interface EthWethConversionDialogProps {
onCancelled: () => void;
isOpen: boolean;
token: Token;
- etherBalanceInWei: BigNumber;
+ etherBalanceInWei?: BigNumber;
lastForceTokenStateRefetch: number;
}
@@ -60,7 +60,7 @@ export class EthWethConversionDialog extends React.Component<
<FlatButton key="convert" label="Convert" primary={true} onTouchTap={this._onConvertClick.bind(this)} />,
];
const title = this.props.direction === Side.Deposit ? 'Wrap ETH' : 'Unwrap WETH';
- return (
+ return !_.isUndefined(this.props.etherBalanceInWei) ? (
<Dialog
title={title}
titleStyle={{ fontWeight: 100 }}
@@ -70,7 +70,7 @@ export class EthWethConversionDialog extends React.Component<
>
{this._renderConversionDialogBody()}
</Dialog>
- );
+ ) : null;
}
private _renderConversionDialogBody(): React.ReactNode {
const explanation =
diff --git a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
index 196414407..c9727b553 100644
--- a/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
+++ b/packages/website/ts/components/dialogs/ledger_config_dialog.tsx
@@ -250,7 +250,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
});
return true;
}
- private _onDerivationPathChanged(e: any, derivationPath: string): void {
+ private _onDerivationPathChanged(_event: any, derivationPath: string): void {
let derivationErrMsg = '';
if (!_.startsWith(derivationPath, VALID_ETHEREUM_DERIVATION_PATH_PREFIX)) {
derivationErrMsg = 'Must be valid Ethereum path.';
@@ -295,7 +295,7 @@ export class LedgerConfigDialog extends React.Component<LedgerConfigDialogProps,
}
return userAddresses;
}
- private _onSelectedNetworkUpdated(e: any, index: number, networkId: number): void {
+ private _onSelectedNetworkUpdated(_event: any, _index: number, networkId: number): void {
this.setState({
preferredNetworkId: networkId,
});
diff --git a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
index ac0b27cdc..f6594b9d5 100644
--- a/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
+++ b/packages/website/ts/components/dialogs/track_token_confirmation_dialog.tsx
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
import FlatButton from 'material-ui/FlatButton';
import * as React from 'react';
diff --git a/packages/website/ts/components/eth_weth_conversion_button.tsx b/packages/website/ts/components/eth_weth_conversion_button.tsx
index 2fb35cc1c..4b91a2ebd 100644
--- a/packages/website/ts/components/eth_weth_conversion_button.tsx
+++ b/packages/website/ts/components/eth_weth_conversion_button.tsx
@@ -18,7 +18,7 @@ interface EthWethConversionButtonProps {
ethToken: Token;
dispatcher: Dispatcher;
blockchain: Blockchain;
- userEtherBalanceInWei?: BigNumber;
+ userEtherBalanceInWei: BigNumber;
isOutdatedWrappedEther: boolean;
onConversionSuccessful?: () => void;
isDisabled?: boolean;
diff --git a/packages/website/ts/components/eth_wrappers.tsx b/packages/website/ts/components/eth_wrappers.tsx
index 1db5ff77f..20b446155 100644
--- a/packages/website/ts/components/eth_wrappers.tsx
+++ b/packages/website/ts/components/eth_wrappers.tsx
@@ -20,7 +20,6 @@ import {
} from 'ts/types';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
-import { utils } from 'ts/utils/utils';
const DATE_FORMAT = 'D/M/YY';
const ICON_DIMENSION = 40;
@@ -35,6 +34,7 @@ interface EthWrappersProps {
userAddress: string;
userEtherBalanceInWei?: BigNumber;
lastForceTokenStateRefetch: number;
+ isFullWidth?: boolean;
}
interface EthWrappersState {
@@ -43,6 +43,9 @@ interface EthWrappersState {
}
export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersState> {
+ public static defaultProps: Partial<EthWrappersProps> = {
+ isFullWidth: false,
+ };
private _isUnmounted: boolean;
constructor(props: EthWrappersProps) {
super(props);
@@ -93,12 +96,12 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
EtherscanLinkSuffixes.Address,
);
const tokenLabel = this._renderToken('Wrapped Ether', etherToken.address, configs.ICON_URL_BY_SYMBOL.WETH);
- const userEtherBalanceInEth = Web3Wrapper.toUnitAmount(
- this.props.userEtherBalanceInWei,
- constants.DECIMAL_PLACES_ETH,
- );
+ const userEtherBalanceInEth = !_.isUndefined(this.props.userEtherBalanceInWei)
+ ? Web3Wrapper.toUnitAmount(this.props.userEtherBalanceInWei, constants.DECIMAL_PLACES_ETH)
+ : undefined;
+ const rootClassName = this.props.isFullWidth ? 'clearfix' : 'clearfix lg-px4 md-px4 sm-px2';
return (
- <div className="clearfix lg-px4 md-px4 sm-px2" style={{ minHeight: 600 }}>
+ <div className={rootClassName} style={{ minHeight: 600 }}>
<div className="relative">
<h3>ETH Wrapper</h3>
<div className="absolute" style={{ top: 0, right: 0 }}>
@@ -116,7 +119,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
<div>
<div className="py2">Wrap ETH into an ERC20-compliant Ether token. 1 ETH = 1 WETH.</div>
<div>
- <Table selectable={false} style={{ backgroundColor: colors.grey50 }}>
+ <Table selectable={false} style={{ backgroundColor: 'transparent' }}>
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
<TableRow>
<TableHeaderColumn>ETH Token</TableHeaderColumn>
@@ -143,7 +146,11 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</div>
</TableRowColumn>
<TableRowColumn>
- {userEtherBalanceInEth.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} ETH
+ {!_.isUndefined(userEtherBalanceInEth) ? (
+ `${userEtherBalanceInEth.toFixed(configs.AMOUNT_DISPLAY_PRECSION)} ETH`
+ ) : (
+ <i className="zmdi zmdi-spinner zmdi-hc-spin" />
+ )}
</TableRowColumn>
<TableRowColumn>
<EthWethConversionButton
@@ -157,6 +164,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
dispatcher={this.props.dispatcher}
blockchain={this.props.blockchain}
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
+ isDisabled={_.isUndefined(userEtherBalanceInEth)}
/>
</TableRowColumn>
</TableRow>
@@ -203,7 +211,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
it to the updated WETH token.
</div>
<div>
- <Table selectable={false} style={{ backgroundColor: colors.grey50 }}>
+ <Table selectable={false} style={{ backgroundColor: 'transparent' }}>
<TableHeader displaySelectAll={false} adjustForCheckbox={false}>
<TableRow>
<TableHeaderColumn>WETH Version</TableHeaderColumn>
@@ -213,9 +221,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</TableHeaderColumn>
</TableRow>
</TableHeader>
- <TableBody displayRowCheckbox={false}>
- {this._renderOutdatedWeths(etherToken, this.state.ethTokenState)}
- </TableBody>
+ <TableBody displayRowCheckbox={false}>{this._renderOutdatedWeths(etherToken)}</TableBody>
</Table>
</div>
</div>
@@ -241,7 +247,7 @@ export class EthWrappers extends React.Component<EthWrappersProps, EthWrappersSt
</div>
);
}
- private _renderOutdatedWeths(etherToken: Token, etherTokenState: TokenState): React.ReactNode {
+ private _renderOutdatedWeths(etherToken: Token): React.ReactNode {
const rows = _.map(
configs.OUTDATED_WRAPPED_ETHERS,
(outdatedWETHByNetworkId: OutdatedWrappedEtherByNetworkId) => {
diff --git a/packages/website/ts/components/fill_order.tsx b/packages/website/ts/components/fill_order.tsx
index 0168ec8f6..f3ea44286 100644
--- a/packages/website/ts/components/fill_order.tsx
+++ b/packages/website/ts/components/fill_order.tsx
@@ -39,6 +39,8 @@ interface FillOrderProps {
initialOrder: Order;
dispatcher: Dispatcher;
lastForceTokenStateRefetch: number;
+ isFullWidth?: boolean;
+ shouldHideHeader?: boolean;
}
interface FillOrderState {
@@ -61,6 +63,10 @@ interface FillOrderState {
}
export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
+ public static defaultProps: Partial<FillOrderProps> = {
+ isFullWidth: false,
+ shouldHideHeader: false,
+ };
private _isUnmounted: boolean;
constructor(props: FillOrderProps) {
super(props);
@@ -97,10 +103,15 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
this._isUnmounted = true;
}
public render(): React.ReactNode {
+ const rootClassName = this.props.isFullWidth ? 'clearfix' : 'lg-px4 md-px4 sm-px2';
return (
- <div className="clearfix lg-px4 md-px4 sm-px2" style={{ minHeight: 600 }}>
- <h3>Fill an order</h3>
- <Divider />
+ <div className={rootClassName} style={{ minHeight: 600 }}>
+ {!this.props.shouldHideHeader && (
+ <div>
+ <h3>Fill an order</h3>
+ <Divider />
+ </div>
+ )}
<div>
{!this.props.isOrderInUrl && (
<div>
@@ -340,7 +351,7 @@ export class FillOrder extends React.Component<FillOrderProps, FillOrderState> {
this._onFillOrderClickFireAndForgetAsync();
}
}
- private _onFillAmountChange(isValid: boolean, amount?: BigNumber): void {
+ private _onFillAmountChange(_isValid: boolean, amount?: BigNumber): void {
this.props.dispatcher.updateOrderFillAmount(amount);
}
private _onFillOrderJSONChanged(event: any): void {
diff --git a/packages/website/ts/components/footer.tsx b/packages/website/ts/components/footer.tsx
index c44e41084..9fb332a98 100644
--- a/packages/website/ts/components/footer.tsx
+++ b/packages/website/ts/components/footer.tsx
@@ -235,7 +235,7 @@ export class Footer extends React.Component<FooterProps, FooterState> {
</div>
);
}
- private _updateLanguage(e: any, index: number, value: Language): void {
+ private _updateLanguage(_event: any, _index: number, value: Language): void {
this.setState({
selectedLanguage: value,
});
diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx
new file mode 100644
index 000000000..8ef58328e
--- /dev/null
+++ b/packages/website/ts/components/forms/subscribe_form.tsx
@@ -0,0 +1,123 @@
+import { colors } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+import { Container } from 'ts/components/ui/container';
+import { Input } from 'ts/components/ui/input';
+import { Text } from 'ts/components/ui/text';
+import { backendClient } from 'ts/utils/backend_client';
+
+export interface SubscribeFormProps {}
+
+export enum SubscribeFormStatus {
+ None,
+ Error,
+ Success,
+ Loading,
+ Other,
+}
+
+export interface SubscribeFormState {
+ emailText: string;
+ lastSubmittedEmail: string;
+ status: SubscribeFormStatus;
+}
+
+const FORM_FONT_SIZE = '15px';
+
+// TODO: Translate visible strings. https://app.asana.com/0/628666249318202/697485674422001
+export class SubscribeForm extends React.Component<SubscribeFormProps, SubscribeFormState> {
+ public state = {
+ emailText: '',
+ lastSubmittedEmail: '',
+ status: SubscribeFormStatus.None,
+ };
+ public render(): React.ReactNode {
+ return (
+ <Container className="flex flex-column items-center justify-between md-mx2 sm-mx2">
+ <Container marginBottom="15px">
+ <Text fontFamily="Roboto Mono" fontColor={colors.grey} center={true}>
+ Subscribe to our newsletter for 0x relayer and dApp updates
+ </Text>
+ </Container>
+ <form onSubmit={this._handleFormSubmitAsync.bind(this)}>
+ <Container className="flex flex-wrap justify-center items-center">
+ <Container marginTop="15px">
+ <Input
+ placeholder="you@email.com"
+ value={this.state.emailText}
+ fontColor={colors.white}
+ fontSize={FORM_FONT_SIZE}
+ backgroundColor={colors.projectsGrey}
+ width="300px"
+ onChange={this._handleEmailInputChange.bind(this)}
+ />
+ </Container>
+ <Container marginLeft="15px" marginTop="15px">
+ <Button
+ type="submit"
+ backgroundColor={colors.darkestGrey}
+ fontColor={colors.white}
+ fontSize={FORM_FONT_SIZE}
+ >
+ Subscribe
+ </Button>
+ </Container>
+ </Container>
+ </form>
+ {this._renderMessage()}
+ </Container>
+ );
+ }
+ private _renderMessage(): React.ReactNode {
+ let message = null;
+ switch (this.state.status) {
+ case SubscribeFormStatus.Error:
+ message = 'Sorry, something went wrong. Try again later.';
+ break;
+ case SubscribeFormStatus.Loading:
+ message = 'One second...';
+ break;
+ case SubscribeFormStatus.Success:
+ message = `Thanks! ${this.state.lastSubmittedEmail} is now on the mailing list.`;
+ break;
+ case SubscribeFormStatus.None:
+ break;
+ default:
+ throw new Error(
+ 'The SubscribeFormStatus switch statement is not exhaustive when choosing an error message.',
+ );
+ }
+ return (
+ <Container isHidden={!message} marginTop="30px">
+ <Text center={true} fontFamily="Roboto Mono" fontColor={colors.grey}>
+ {message || 'spacer text (never shown to user)'}
+ </Text>
+ </Container>
+ );
+ }
+ private _handleEmailInputChange(event: React.ChangeEvent<HTMLInputElement>): void {
+ this.setState({ emailText: event.target.value });
+ }
+ private async _handleFormSubmitAsync(event: React.FormEvent<HTMLInputElement>): Promise<void> {
+ event.preventDefault();
+ if (_.isUndefined(this.state.emailText) || _.isEmpty(this.state.emailText)) {
+ return;
+ }
+ this.setState({
+ status: SubscribeFormStatus.Loading,
+ lastSubmittedEmail: this.state.emailText,
+ });
+ try {
+ const response = await backendClient.subscribeToNewsletterAsync(this.state.emailText);
+ const status = response.status === 200 ? SubscribeFormStatus.Success : SubscribeFormStatus.Error;
+ this.setState({ status, emailText: '' });
+ } catch (error) {
+ this._setStatus(SubscribeFormStatus.Error);
+ }
+ }
+ private _setStatus(status: SubscribeFormStatus): void {
+ this.setState({ status });
+ }
+}
diff --git a/packages/website/ts/components/generate_order/generate_order_form.tsx b/packages/website/ts/components/generate_order/generate_order_form.tsx
index 5f968a5e4..d26b5c3fa 100644
--- a/packages/website/ts/components/generate_order/generate_order_form.tsx
+++ b/packages/website/ts/components/generate_order/generate_order_form.tsx
@@ -47,6 +47,8 @@ interface GenerateOrderFormProps {
sideToAssetToken: SideToAssetToken;
tokenByAddress: TokenByAddress;
lastForceTokenStateRefetch: number;
+ isFullWidth?: boolean;
+ shouldHideHeader?: boolean;
}
interface GenerateOrderFormState {
@@ -56,6 +58,10 @@ interface GenerateOrderFormState {
}
export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, GenerateOrderFormState> {
+ public static defaultProps: Partial<GenerateOrderFormProps> = {
+ isFullWidth: false,
+ shouldHideHeader: false,
+ };
constructor(props: GenerateOrderFormProps) {
super(props);
this.state = {
@@ -80,10 +86,15 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
const exchangeContractIfExists = this.props.blockchain.getExchangeContractAddressIfExists();
const initialTakerAddress =
this.props.orderTakerAddress === constants.NULL_ADDRESS ? '' : this.props.orderTakerAddress;
+ const rootClassName = this.props.isFullWidth ? 'clearfix mb2' : 'clearfix mb2 lg-px4 md-px4 sm-px2';
return (
- <div className="clearfix mb2 lg-px4 md-px4 sm-px2">
- <h3>Generate an order</h3>
- <Divider />
+ <div className={rootClassName}>
+ {!this.props.shouldHideHeader && (
+ <div>
+ <h3>Generate an order</h3>
+ <Divider />
+ </div>
+ )}
<div className="mx-auto" style={{ maxWidth: 580 }}>
<div className="pt3">
<div className="mx-auto clearfix">
@@ -215,7 +226,7 @@ export class GenerateOrderForm extends React.Component<GenerateOrderFormProps, G
</div>
);
}
- private _onTokenAmountChange(token: Token, side: Side, isValid: boolean, amount?: BigNumber): void {
+ private _onTokenAmountChange(token: Token, side: Side, _isValid: boolean, amount?: BigNumber): void {
this.props.dispatcher.updateChosenAssetToken(side, {
address: token.address,
amount,
diff --git a/packages/website/ts/components/generate_order/new_token_form.tsx b/packages/website/ts/components/generate_order/new_token_form.tsx
index a9b8e9589..176a0807b 100644
--- a/packages/website/ts/components/generate_order/new_token_form.tsx
+++ b/packages/website/ts/components/generate_order/new_token_form.tsx
@@ -152,7 +152,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
};
this.props.onNewTokenSubmitted(newToken);
}
- private _onTokenNameChanged(e: any, name: string): void {
+ private _onTokenNameChanged(_event: any, name: string): void {
let nameErrText = '';
const maxLength = 30;
const tokens = _.values(this.props.tokenByAddress);
@@ -173,7 +173,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
nameErrText,
});
}
- private _onTokenSymbolChanged(e: any, symbol: string): void {
+ private _onTokenSymbolChanged(_event: any, symbol: string): void {
let symbolErrText = '';
const maxLength = 5;
const tokens = _.values(this.props.tokenByAddress);
@@ -193,7 +193,7 @@ export class NewTokenForm extends React.Component<NewTokenFormProps, NewTokenFor
symbolErrText,
});
}
- private _onTokenDecimalsChanged(e: any, decimals: string): void {
+ private _onTokenDecimalsChanged(_event: any, decimals: string): void {
let decimalsErrText = '';
const maxLength = 2;
if (decimals === '') {
diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx
index d61dfa87d..0dd2a5aa5 100644
--- a/packages/website/ts/components/inputs/allowance_toggle.tsx
+++ b/packages/website/ts/components/inputs/allowance_toggle.tsx
@@ -5,10 +5,9 @@ import Toggle from 'material-ui/Toggle';
import * as React from 'react';
import { Blockchain } from 'ts/blockchain';
import { Dispatcher } from 'ts/redux/dispatcher';
+import { colors } from 'ts/style/colors';
import { BalanceErrs, Token, TokenState } from 'ts/types';
import { analytics } from 'ts/utils/analytics';
-import { colors } from 'ts/utils/colors';
-import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter';
import { utils } from 'ts/utils/utils';
@@ -18,11 +17,11 @@ interface AllowanceToggleProps {
networkId: number;
blockchain: Blockchain;
dispatcher: Dispatcher;
- onErrorOccurred: (errType: BalanceErrs) => void;
token: Token;
tokenState: TokenState;
userAddress: string;
- isDisabled: boolean;
+ isDisabled?: boolean;
+ onErrorOccurred?: (errType: BalanceErrs) => void;
refetchTokenStateAsync: () => Promise<void>;
}
@@ -57,6 +56,10 @@ const styles: Styles = {
};
export class AllowanceToggle extends React.Component<AllowanceToggleProps, AllowanceToggleState> {
+ public static defaultProps = {
+ onErrorOccurred: _.noop,
+ isDisabled: false,
+ };
constructor(props: AllowanceToggleProps) {
super(props);
this.state = {
diff --git a/packages/website/ts/components/inputs/balance_bounded_input.tsx b/packages/website/ts/components/inputs/balance_bounded_input.tsx
index e5b502b25..968609030 100644
--- a/packages/website/ts/components/inputs/balance_bounded_input.tsx
+++ b/packages/website/ts/components/inputs/balance_bounded_input.tsx
@@ -104,7 +104,7 @@ export class BalanceBoundedInput extends React.Component<BalanceBoundedInputProp
/>
);
}
- private _onValueChange(e: any, amountString: string): void {
+ private _onValueChange(_event: any, amountString: string): void {
this._setAmountState(amountString, this.props.balance, () => {
const isValid = _.isUndefined(this._validate(amountString, this.props.balance));
const isPositiveNumber = utils.isNumeric(amountString) && !_.includes(amountString, '-');
diff --git a/packages/website/ts/components/inputs/expiration_input.tsx b/packages/website/ts/components/inputs/expiration_input.tsx
index 5c68080fe..79dd2f568 100644
--- a/packages/website/ts/components/inputs/expiration_input.tsx
+++ b/packages/website/ts/components/inputs/expiration_input.tsx
@@ -80,7 +80,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const defaultDateTime = utils.initialOrderExpiryUnixTimestampSec();
this.props.updateOrderExpiry(defaultDateTime);
}
- private _onDateChanged(e: any, date: Date): void {
+ private _onDateChanged(_event: any, date: Date): void {
const dateMoment = moment(date);
this.setState({
dateMoment,
@@ -88,7 +88,7 @@ export class ExpirationInput extends React.Component<ExpirationInputProps, Expir
const timestamp = utils.convertToUnixTimestampSeconds(dateMoment, this.state.timeMoment);
this.props.updateOrderExpiry(timestamp);
}
- private _onTimeChanged(e: any, time: Date): void {
+ private _onTimeChanged(_event: any, time: Date): void {
const timeMoment = moment(time);
this.setState({
timeMoment,
diff --git a/packages/website/ts/components/inputs/identicon_address_input.tsx b/packages/website/ts/components/inputs/identicon_address_input.tsx
index a4dc01ba8..6ba7584a7 100644
--- a/packages/website/ts/components/inputs/identicon_address_input.tsx
+++ b/packages/website/ts/components/inputs/identicon_address_input.tsx
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { AddressInput } from 'ts/components/inputs/address_input';
import { Identicon } from 'ts/components/ui/identicon';
diff --git a/packages/website/ts/components/inputs/token_input.tsx b/packages/website/ts/components/inputs/token_input.tsx
index c2c4dd63b..0bd36781e 100644
--- a/packages/website/ts/components/inputs/token_input.tsx
+++ b/packages/website/ts/components/inputs/token_input.tsx
@@ -1,5 +1,4 @@
import { colors } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import Paper from 'material-ui/Paper';
import * as React from 'react';
import { Blockchain } from 'ts/blockchain';
diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx
index e5d152e3e..b4a174a03 100644
--- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx
+++ b/packages/website/ts/components/legacy_portal/legacy_portal.tsx
@@ -1,5 +1,5 @@
import { colors } from '@0xproject/react-shared';
-import { BigNumber, logUtils } from '@0xproject/utils';
+import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
import Paper from 'material-ui/Paper';
@@ -15,27 +15,14 @@ import { EthWrappers } from 'ts/components/eth_wrappers';
import { FillOrder } from 'ts/components/fill_order';
import { Footer } from 'ts/components/footer';
import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_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';
import { FlashMessage } from 'ts/components/ui/flash_message';
-import { Wallet } from 'ts/components/wallet/wallet';
import { GenerateOrderForm } from 'ts/containers/generate_order_form';
import { localStorage } from 'ts/local_storage/local_storage';
import { Dispatcher } from 'ts/redux/dispatcher';
-import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
-import { validator } from 'ts/schemas/validator';
-import {
- BlockchainErrs,
- Environments,
- HashData,
- Order,
- ProviderType,
- ScreenWidths,
- TokenByAddress,
- WebsitePaths,
-} from 'ts/types';
+import { BlockchainErrs, HashData, Order, ProviderType, ScreenWidths, TokenByAddress, WebsitePaths } from 'ts/types';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
import { orderParser } from 'ts/utils/order_parser';
@@ -323,7 +310,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
/>
);
}
- private _renderFillOrder(match: any, location: Location, history: History): React.ReactNode {
+ private _renderFillOrder(_match: any, _location: Location, _history: History): React.ReactNode {
const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache)
? this.props.userSuppliedOrderCache
: this._sharedOrderIfExists;
@@ -342,7 +329,7 @@ export class LegacyPortal extends React.Component<LegacyPortalProps, LegacyPorta
/>
);
}
- private _renderGenerateOrderForm(match: any, location: Location, history: History): React.ReactNode {
+ private _renderGenerateOrderForm(_match: any, _location: Location, _history: History): React.ReactNode {
return (
<GenerateOrderForm
blockchain={this._blockchain}
diff --git a/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx b/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx
index 7469ca14e..1dd164f8b 100644
--- a/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx
+++ b/packages/website/ts/components/legacy_portal/legacy_portal_menu.tsx
@@ -1,8 +1,7 @@
import * as _ from 'lodash';
import * as React from 'react';
import { MenuItem } from 'ts/components/ui/menu_item';
-import { Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { WebsitePaths } from 'ts/types';
export interface LegacyPortalMenuProps {
menuItemStyle: React.CSSProperties;
diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx
index 4066babaf..9879cd387 100644
--- a/packages/website/ts/components/onboarding/onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx
@@ -1,11 +1,9 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { Placement, Popper, PopperChildrenProps } from 'react-popper';
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';
export interface Step {
target: string;
diff --git a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
index eb34a87f2..155c70c5f 100644
--- a/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
+++ b/packages/website/ts/components/onboarding/onboarding_tooltip.tsx
@@ -1,6 +1,5 @@
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';
diff --git a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
index bf52684d7..efb844cb5 100644
--- a/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
+++ b/packages/website/ts/components/onboarding/portal_onboarding_flow.tsx
@@ -2,11 +2,14 @@ import * as _ from 'lodash';
import * as React from 'react';
import { BigNumber } from '@0xproject/utils';
+import { Blockchain } from 'ts/blockchain';
import { OnboardingFlow, Step } from 'ts/components/onboarding/onboarding_flow';
-import { ProviderType, TokenByAddress, TokenStateByAddress } from 'ts/types';
+import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
+import { ProviderType, Token, TokenByAddress, TokenStateByAddress } from 'ts/types';
import { utils } from 'ts/utils/utils';
export interface PortalOnboardingFlowProps {
+ blockchain: Blockchain;
stepIndex: number;
isRunning: boolean;
userAddress: string;
@@ -19,6 +22,7 @@ export interface PortalOnboardingFlowProps {
trackedTokenStateByAddress: TokenStateByAddress;
updateIsRunning: (isRunning: boolean) => void;
updateOnboardingStep: (stepIndex: number) => void;
+ refetchTokenStateAsync: (tokenAddress: string) => Promise<void>;
}
export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowProps> {
@@ -39,7 +43,6 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr
/>
);
}
-
private _getSteps(): Step[] {
const steps: Step[] = [
{
@@ -77,18 +80,33 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr
placement: 'right',
continueButtonDisplay: this._userHasVisibleWeth() ? 'enabled' : 'disabled',
},
+ {
+ target: '.weth-row',
+ content: (
+ <div>
+ Unlock your tokens for trading. You only need to do this once for each token.
+ <div> ETH: {this._renderEthAllowanceToggle()}</div>
+ <div> ZRX: {this._renderZrxAllowanceToggle()}</div>
+ </div>
+ ),
+ placement: 'right',
+ continueButtonDisplay: this._userHasAllowancesForWethAndZrx() ? 'enabled' : 'disabled',
+ },
+ {
+ target: '.wallet',
+ content: 'Congrats! Your wallet is now set up for trading. Use it on any relayer in the 0x ecosystem.',
+ placement: 'right',
+ continueButtonDisplay: 'enabled',
+ },
];
return steps;
}
-
private _isAddressAvailable(): boolean {
return !_.isEmpty(this.props.userAddress);
}
-
private _userHasVisibleEth(): boolean {
return this.props.userEtherBalanceInWei > new BigNumber(0);
}
-
private _userHasVisibleWeth(): boolean {
const ethToken = utils.getEthToken(this.props.tokenByAddress);
if (!ethToken) {
@@ -97,15 +115,25 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr
const wethTokenState = this.props.trackedTokenStateByAddress[ethToken.address];
return wethTokenState.balance > new BigNumber(0);
}
-
+ private _userHasAllowancesForWethAndZrx(): boolean {
+ const ethToken = utils.getEthToken(this.props.tokenByAddress);
+ const zrxToken = utils.getZrxToken(this.props.tokenByAddress);
+ if (ethToken && zrxToken) {
+ const ethTokenAllowance = this.props.trackedTokenStateByAddress[ethToken.address].allowance;
+ const zrxTokenAllowance = this.props.trackedTokenStateByAddress[zrxToken.address].allowance;
+ return ethTokenAllowance > new BigNumber(0) && zrxTokenAllowance > new BigNumber(0);
+ }
+ return false;
+ }
private _overrideOnboardingStateIfShould(): void {
this._autoStartOnboardingIfShould();
this._adjustStepIfShould();
}
private _adjustStepIfShould(): void {
+ const stepIndex = this.props.stepIndex;
if (this._isAddressAvailable()) {
- if (this.props.stepIndex < 2) {
+ if (stepIndex < 2) {
this.props.updateOnboardingStep(2);
}
return;
@@ -115,14 +143,42 @@ export class PortalOnboardingFlow extends React.Component<PortalOnboardingFlowPr
this.props.injectedProviderName,
);
if (isExternallyInjected) {
- this.props.updateOnboardingStep(1);
+ if (stepIndex !== 1) {
+ this.props.updateOnboardingStep(1);
+ }
return;
}
- this.props.updateOnboardingStep(0);
+ if (stepIndex !== 0) {
+ this.props.updateOnboardingStep(0);
+ }
}
private _autoStartOnboardingIfShould(): void {
if (!this.props.isRunning && !this.props.hasBeenSeen && this.props.blockchainIsLoaded) {
this.props.updateIsRunning(true);
}
}
+ private _renderZrxAllowanceToggle(): React.ReactNode {
+ const zrxToken = utils.getZrxToken(this.props.tokenByAddress);
+ return this._renderAllowanceToggle(zrxToken);
+ }
+ private _renderEthAllowanceToggle(): React.ReactNode {
+ const ethToken = utils.getEthToken(this.props.tokenByAddress);
+ return this._renderAllowanceToggle(ethToken);
+ }
+ private _renderAllowanceToggle(token: Token): React.ReactNode {
+ if (!token) {
+ return null;
+ }
+ const tokenState = this.props.trackedTokenStateByAddress[token.address];
+ return (
+ <AllowanceToggle
+ token={token}
+ tokenState={tokenState}
+ isDisabled={!tokenState.isLoaded}
+ blockchain={this.props.blockchain}
+ // tslint:disable-next-line:jsx-no-lambda
+ refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(token.address)}
+ />
+ );
+ }
}
diff --git a/packages/website/ts/components/portal/back_button.tsx b/packages/website/ts/components/portal/back_button.tsx
index 48858613c..2d0bbefc3 100644
--- a/packages/website/ts/components/portal/back_button.tsx
+++ b/packages/website/ts/components/portal/back_button.tsx
@@ -2,7 +2,7 @@ import { Styles } from '@0xproject/react-shared';
import * as React from 'react';
import { Link } from 'react-router-dom';
-import { colors } from 'ts/utils/colors';
+import { colors } from 'ts/style/colors';
export interface BackButtonProps {
to: string;
diff --git a/packages/website/ts/components/portal/drawer_menu.tsx b/packages/website/ts/components/portal/drawer_menu.tsx
index ace11639a..8ac2b9091 100644
--- a/packages/website/ts/components/portal/drawer_menu.tsx
+++ b/packages/website/ts/components/portal/drawer_menu.tsx
@@ -4,8 +4,8 @@ import * as React from 'react';
import { defaultMenuItemEntries, Menu } from 'ts/components/portal/menu';
import { Identicon } from 'ts/components/ui/identicon';
+import { colors } from 'ts/style/colors';
import { WebsitePaths } from 'ts/types';
-import { colors } from 'ts/utils/colors';
import { utils } from 'ts/utils/utils';
const IDENTICON_DIAMETER = 45;
diff --git a/packages/website/ts/components/portal/menu.tsx b/packages/website/ts/components/portal/menu.tsx
index 6e97ee37e..39dab77f5 100644
--- a/packages/website/ts/components/portal/menu.tsx
+++ b/packages/website/ts/components/portal/menu.tsx
@@ -2,9 +2,8 @@ import { Styles } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
import { MenuItem } from 'ts/components/ui/menu_item';
-import { Environments, WebsitePaths } from 'ts/types';
-import { colors } from 'ts/utils/colors';
-import { configs } from 'ts/utils/configs';
+import { colors } from 'ts/style/colors';
+import { WebsitePaths } from 'ts/types';
export interface MenuTheme {
paddingLeft: number;
diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx
index 9aa83546a..48486939b 100644
--- a/packages/website/ts/components/portal/portal.tsx
+++ b/packages/website/ts/components/portal/portal.tsx
@@ -3,7 +3,7 @@ import { BigNumber } from '@0xproject/utils';
import * as _ from 'lodash';
import * as React from 'react';
import * as DocumentTitle from 'react-document-title';
-import { Link, Route, RouteComponentProps, Switch } from 'react-router-dom';
+import { Route, RouteComponentProps, Switch } from 'react-router-dom';
import { Blockchain } from 'ts/blockchain';
import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog';
@@ -34,6 +34,7 @@ import { Dispatcher } from 'ts/redux/dispatcher';
import {
BlockchainErrs,
HashData,
+ ItemByAddress,
Order,
ProviderType,
ScreenWidths,
@@ -43,6 +44,7 @@ import {
TokenVisibility,
WebsitePaths,
} from 'ts/types';
+import { backendClient } from 'ts/utils/backend_client';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
import { orderParser } from 'ts/utils/order_parser';
@@ -233,7 +235,11 @@ export class Portal extends React.Component<PortalProps, PortalState> {
: TokenVisibility.TRACKED;
return (
<div style={styles.root}>
- <PortalOnboardingFlow trackedTokenStateByAddress={this.state.trackedTokenStateByAddress} />
+ <PortalOnboardingFlow
+ blockchain={this._blockchain}
+ trackedTokenStateByAddress={this.state.trackedTokenStateByAddress}
+ refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this)}
+ />
<DocumentTitle title="0x Portal DApp" />
<TopBar
userAddress={this.props.userAddress}
@@ -266,10 +272,6 @@ export class Portal extends React.Component<PortalProps, PortalState> {
toggleDialogFn={updateShouldBlockchainErrDialogBeOpen}
networkId={this.props.networkId}
/>
- <PortalDisclaimerDialog
- isOpen={this.state.isDisclaimerDialogOpen}
- onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
- />
<FlashMessage dispatcher={this.props.dispatcher} flashMessage={this.props.flashMessage} />
{this.props.blockchainIsLoaded && (
<LedgerConfigDialog
@@ -394,18 +396,24 @@ export class Portal extends React.Component<PortalProps, PortalState> {
},
];
return (
- <Switch>
- {_.map(accountManagementItems, item => {
- return (
- <Route
- key={item.pathName}
- path={item.pathName}
- render={this._renderAccountManagementItem.bind(this, item)}
- />
- );
- })}}
- <Route render={this._renderNotFoundMessage.bind(this)} />
- </Switch>
+ <div>
+ <Switch>
+ {_.map(accountManagementItems, item => {
+ return (
+ <Route
+ key={item.pathName}
+ path={item.pathName}
+ render={this._renderAccountManagementItem.bind(this, item)}
+ />
+ );
+ })}}
+ <Route render={this._renderNotFoundMessage.bind(this)} />
+ </Switch>
+ <PortalDisclaimerDialog
+ isOpen={this.state.isDisclaimerDialogOpen}
+ onToggleDialog={this._onPortalDisclaimerAccepted.bind(this)}
+ />
+ </div>
);
}
private _renderAccountManagementItem(item: AccountManagementItem): React.ReactNode {
@@ -426,6 +434,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
userAddress={this.props.userAddress}
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+ isFullWidth={true}
/>
);
}
@@ -435,6 +444,9 @@ export class Portal extends React.Component<PortalProps, PortalState> {
tokenByAddress={this.props.tokenByAddress}
userAddress={this.props.userAddress}
networkId={this.props.networkId}
+ isFullWidth={true}
+ shouldHideHeader={true}
+ isScrollable={false}
/>
);
}
@@ -444,6 +456,8 @@ export class Portal extends React.Component<PortalProps, PortalState> {
blockchain={this._blockchain}
hashData={this.props.hashData}
dispatcher={this.props.dispatcher}
+ isFullWidth={true}
+ shouldHideHeader={true}
/>
);
}
@@ -463,6 +477,8 @@ export class Portal extends React.Component<PortalProps, PortalState> {
tokenByAddress={this.props.tokenByAddress}
dispatcher={this.props.dispatcher}
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+ isFullWidth={true}
+ shouldHideHeader={true}
/>
);
}
@@ -480,6 +496,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
userEtherBalanceInWei={this.props.userEtherBalanceInWei}
networkId={this.props.networkId}
lastForceTokenStateRefetch={this.props.lastForceTokenStateRefetch}
+ isFullWidth={true}
/>
);
}
@@ -587,6 +604,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
return this._blockchain.getTokenBalanceAndAllowanceAsync(userAddressIfExists, tokenAddress);
}),
);
+ const priceByAddress = await this._getPriceByAddressAsync(tokenAddresses);
for (let i = 0; i < tokenAddresses.length; i++) {
// Order is preserved in Promise.all
const [balance, allowance] = balancesAndAllowances[i];
@@ -595,6 +613,7 @@ export class Portal extends React.Component<PortalProps, PortalState> {
balance,
allowance,
isLoaded: true,
+ price: priceByAddress[tokenAddress],
};
}
this.setState({
@@ -602,6 +621,34 @@ export class Portal extends React.Component<PortalProps, PortalState> {
});
}
+ private async _getPriceByAddressAsync(tokenAddresses: string[]): Promise<ItemByAddress<BigNumber>> {
+ if (_.isEmpty(tokenAddresses)) {
+ return {};
+ }
+ // for each input token address, search for the corresponding symbol in this.props.tokenByAddress, if it exists
+ // create a mapping from existing symbols -> address
+ const tokenAddressBySymbol: { [symbol: string]: string } = {};
+ _.each(tokenAddresses, address => {
+ const tokenIfExists = _.get(this.props.tokenByAddress, address);
+ if (!_.isUndefined(tokenIfExists)) {
+ const symbol = tokenIfExists.symbol;
+ tokenAddressBySymbol[symbol] = address;
+ }
+ });
+ const tokenSymbols = _.keys(tokenAddressBySymbol);
+ try {
+ const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols);
+ const priceByAddress = _.mapKeys(priceBySymbol, (_value, symbol) => _.get(tokenAddressBySymbol, symbol));
+ const result = _.mapValues(priceByAddress, price => {
+ const priceBigNumber = new BigNumber(price);
+ return priceBigNumber;
+ });
+ return result;
+ } catch (err) {
+ return {};
+ }
+ }
+
private async _refetchTokenStateAsync(tokenAddress: string): Promise<void> {
await this._fetchBalancesAndAllowancesAsync([tokenAddress]);
}
diff --git a/packages/website/ts/components/portal/section.tsx b/packages/website/ts/components/portal/section.tsx
index 9b172aae0..455ed07c9 100644
--- a/packages/website/ts/components/portal/section.tsx
+++ b/packages/website/ts/components/portal/section.tsx
@@ -1,4 +1,3 @@
-import { Styles } from '@0xproject/react-shared';
import * as React from 'react';
export interface SectionProps {
diff --git a/packages/website/ts/components/redirecter.tsx b/packages/website/ts/components/redirector.tsx
index 629522bbb..a02693003 100644
--- a/packages/website/ts/components/redirecter.tsx
+++ b/packages/website/ts/components/redirector.tsx
@@ -1,10 +1,9 @@
-import * as React from 'react';
import { constants } from 'ts/utils/constants';
-interface RedirecterProps {
+interface RedirectorProps {
location: string;
}
-export function Redirecter(props: RedirecterProps): void {
+export function Redirector(_props: RedirectorProps): void {
window.location.href = constants.URL_ANGELLIST;
}
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 ad6ab3de1..fbb634164 100644
--- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx
@@ -6,9 +6,8 @@ import * as React from 'react';
import { TopTokens } from 'ts/components/relayer_index/relayer_top_tokens';
import { Container } from 'ts/components/ui/container';
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';
+import { colors } from 'ts/style/colors';
+import { WebsiteBackendRelayerInfo } from 'ts/types';
export interface RelayerGridTileProps {
relayerInfo: WebsiteBackendRelayerInfo;
diff --git a/packages/website/ts/components/relayer_index/relayer_index.tsx b/packages/website/ts/components/relayer_index/relayer_index.tsx
index 9ef6eaf59..3c5761bcd 100644
--- a/packages/website/ts/components/relayer_index/relayer_index.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_index.tsx
@@ -1,14 +1,14 @@
import { Styles } from '@0xproject/react-shared';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
-import FlatButton from 'material-ui/FlatButton';
import { GridList } from 'material-ui/GridList';
import * as React from 'react';
import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile';
+import { Retry } from 'ts/components/ui/retry';
+import { colors } from 'ts/style/colors';
import { ScreenWidths, WebsiteBackendRelayerInfo } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
-import { colors } from 'ts/utils/colors';
export interface RelayerIndexProps {
networkId: number;
@@ -63,7 +63,8 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde
const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.relayerInfos);
if (!isReadyToRender) {
return (
- // TODO: consolidate this loading component with the one in portal
+ // TODO: consolidate this loading component with the one in portal and OpenPositions
+ // TODO: possibly refactor into a generic loading container with spinner and retry UI
<div className="center">
{_.isUndefined(this.state.error) ? (
<CircularProgress size={40} thickness={5} />
@@ -124,31 +125,3 @@ export class RelayerIndex extends React.Component<RelayerIndexProps, RelayerInde
}
}
}
-
-interface RetryProps {
- onRetry: () => void;
-}
-const Retry = (props: RetryProps) => (
- <div className="clearfix center" style={{ color: colors.black }}>
- <div className="mx-auto inline-block align-middle" style={{ lineHeight: '44px', textAlign: 'center' }}>
- <div className="h2" style={{ fontFamily: 'Roboto Mono' }}>
- Something went wrong.
- </div>
- <div className="py3">
- <FlatButton
- label={'reload'}
- backgroundColor={colors.black}
- labelStyle={{
- fontSize: 18,
- fontFamily: 'Roboto Mono',
- fontWeight: 'lighter',
- color: colors.white,
- textTransform: 'lowercase',
- }}
- style={{ width: 280, height: 62, borderRadius: 5 }}
- onClick={props.onRetry}
- />
- </div>
- </div>
- </div>
-);
diff --git a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx
index e42f8a81a..a5754180b 100644
--- a/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx
+++ b/packages/website/ts/components/relayer_index/relayer_top_tokens.tsx
@@ -2,7 +2,6 @@ import { colors, EtherscanLinkSuffixes, Styles, utils as sharedUtils } from '@0x
import * as _ from 'lodash';
import * as React from 'react';
-import { TokenIcon } from 'ts/components/ui/token_icon';
import { WebsiteBackendTokenInfo } from 'ts/types';
export interface TopTokensProps {
diff --git a/packages/website/ts/components/sidebar_header.tsx b/packages/website/ts/components/sidebar_header.tsx
index bf46caad9..a14ab54f5 100644
--- a/packages/website/ts/components/sidebar_header.tsx
+++ b/packages/website/ts/components/sidebar_header.tsx
@@ -1,9 +1,6 @@
import { colors } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import * as React from 'react';
-const SHOW_DURATION_MS = 4000;
-
interface SidebarHeaderProps {
title: string;
iconUrl: string;
diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx
index 7a0742bbe..7af80745c 100644
--- a/packages/website/ts/components/token_balances.tsx
+++ b/packages/website/ts/components/token_balances.tsx
@@ -1,19 +1,17 @@
import {
- colors,
constants as sharedConstants,
EtherscanLinkSuffixes,
Networks,
Styles,
utils as sharedUtils,
} from '@0xproject/react-shared';
-import { BigNumber, logUtils } from '@0xproject/utils';
+import { BigNumber, errorUtils, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import Dialog from 'material-ui/Dialog';
import Divider from 'material-ui/Divider';
import FlatButton from 'material-ui/FlatButton';
import FloatingActionButton from 'material-ui/FloatingActionButton';
-import RaisedButton from 'material-ui/RaisedButton';
import ContentAdd from 'material-ui/svg-icons/content/add';
import ContentRemove from 'material-ui/svg-icons/content/remove';
import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
@@ -22,11 +20,11 @@ import ReactTooltip = require('react-tooltip');
import firstBy = require('thenby');
import { Blockchain } from 'ts/blockchain';
import { AssetPicker } from 'ts/components/generate_order/asset_picker';
-import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle';
import { SendButton } from 'ts/components/send_button';
import { HelpTooltip } from 'ts/components/ui/help_tooltip';
import { LifeCycleRaisedButton } from 'ts/components/ui/lifecycle_raised_button';
import { TokenIcon } from 'ts/components/ui/token_icon';
+import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
import { trackedTokenStorage } from 'ts/local_storage/tracked_token_storage';
import { Dispatcher } from 'ts/redux/dispatcher';
import {
@@ -57,7 +55,7 @@ const TOKEN_COL_SPAN_SM = 1;
const styles: Styles = {
bgColor: {
- backgroundColor: colors.grey50,
+ backgroundColor: 'transparent',
},
};
@@ -73,20 +71,22 @@ interface TokenBalancesProps {
userEtherBalanceInWei: BigNumber;
networkId: number;
lastForceTokenStateRefetch: number;
+ isFullWidth?: boolean;
}
interface TokenBalancesState {
errorType: BalanceErrs;
+ trackedTokenStateByAddress: TokenStateByAddress;
isBalanceSpinnerVisible: boolean;
isZRXSpinnerVisible: boolean;
isTokenPickerOpen: boolean;
isAddingToken: boolean;
- trackedTokenStateByAddress: TokenStateByAddress;
}
export class TokenBalances extends React.Component<TokenBalancesProps, TokenBalancesState> {
public static defaultProps: Partial<TokenBalancesProps> = {
userEtherBalanceInWei: new BigNumber(0),
+ isFullWidth: false,
};
private _isUnmounted: boolean;
public constructor(props: TokenBalancesProps) {
@@ -169,7 +169,6 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
/>,
];
const isTestNetwork = utils.isTestNetwork(this.props.networkId);
- const isKovanTestNetwork = this.props.networkId === constants.NETWORK_ID_KOVAN;
const stubColumnStyle = {
display: isTestNetwork ? 'none' : 'table-cell',
};
@@ -187,8 +186,9 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
this.props.userEtherBalanceInWei,
constants.DECIMAL_PLACES_ETH,
);
+ const rootClassName = this.props.isFullWidth ? 'pb2' : 'lg-px4 md-px4 sm-px1 pb2';
return (
- <div className="lg-px4 md-px4 sm-px1 pb2">
+ <div className={rootClassName}>
<h3>{isTestNetwork ? 'Test ether' : 'Ether'}</h3>
<Divider />
<div className="pt2 pb2">
@@ -268,7 +268,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
<div className="inline-block">Allowance</div>
<HelpTooltip style={{ paddingLeft: 4 }} explanation={allowanceExplanation} />
</TableHeaderColumn>
- <TableHeaderColumn>Action</TableHeaderColumn>
+ {isTestNetwork && <TableHeaderColumn>Action</TableHeaderColumn>}
{this.props.screenWidth !== ScreenWidths.Sm && <TableHeaderColumn>Send</TableHeaderColumn>}
</TableRow>
</TableHeader>
@@ -362,28 +362,25 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
</TableRowColumn>
<TableRowColumn>
<AllowanceToggle
- networkId={this.props.networkId}
blockchain={this.props.blockchain}
- dispatcher={this.props.dispatcher}
token={token}
tokenState={tokenState}
onErrorOccurred={this._onErrorOccurred.bind(this)}
- userAddress={this.props.userAddress}
isDisabled={!tokenState.isLoaded}
refetchTokenStateAsync={this._refetchTokenStateAsync.bind(this, token.address)}
/>
</TableRowColumn>
- <TableRowColumn style={{ paddingLeft: actionPaddingX, paddingRight: actionPaddingX }}>
- {isMintable && (
- <LifeCycleRaisedButton
- labelReady="Mint"
- labelLoading={<span style={{ fontSize: 12 }}>Minting...</span>}
- labelComplete="Minted!"
- onClickAsyncFn={this._onMintTestTokensAsync.bind(this, token)}
- />
- )}
- {token.symbol === ZRX_TOKEN_SYMBOL &&
- utils.isTestNetwork(this.props.networkId) && (
+ {utils.isTestNetwork(this.props.networkId) && (
+ <TableRowColumn style={{ paddingLeft: actionPaddingX, paddingRight: actionPaddingX }}>
+ {isMintable && (
+ <LifeCycleRaisedButton
+ labelReady="Mint"
+ labelLoading={<span style={{ fontSize: 12 }}>Minting...</span>}
+ labelComplete="Minted!"
+ onClickAsyncFn={this._onMintTestTokensAsync.bind(this, token)}
+ />
+ )}
+ {token.symbol === ZRX_TOKEN_SYMBOL && (
<LifeCycleRaisedButton
labelReady="Request"
labelLoading="Sending..."
@@ -391,7 +388,8 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
onClickAsyncFn={this._faucetRequestAsync.bind(this, false)}
/>
)}
- </TableRowColumn>
+ </TableRowColumn>
+ )}
{this.props.screenWidth !== ScreenWidths.Sm && (
<TableRowColumn
style={{
@@ -499,7 +497,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
return null; // No error to show
default:
- throw utils.spawnSwitchErr('errorType', this.state.errorType);
+ throw errorUtils.spawnSwitchErr('errorType', this.state.errorType);
}
}
private _onErrorOccurred(errorType: BalanceErrs): void {
@@ -580,7 +578,7 @@ export class TokenBalances extends React.Component<TokenBalancesProps, TokenBala
}
return true;
}
- private _onErrorDialogToggle(isOpen: boolean): void {
+ private _onErrorDialogToggle(_isOpen: boolean): void {
this.setState({
errorType: undefined,
});
diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx
index 8a337119a..cb7c9b483 100644
--- a/packages/website/ts/components/top_bar/provider_display.tsx
+++ b/packages/website/ts/components/top_bar/provider_display.tsx
@@ -9,10 +9,9 @@ import { ProviderPicker } from 'ts/components/top_bar/provider_picker';
import { DropDown } from 'ts/components/ui/drop_down';
import { Identicon } from 'ts/components/ui/identicon';
import { Dispatcher } from 'ts/redux/dispatcher';
+import { colors } from 'ts/style/colors';
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;
diff --git a/packages/website/ts/components/top_bar/provider_picker.tsx b/packages/website/ts/components/top_bar/provider_picker.tsx
index 1ecb8389c..7937f2e9d 100644
--- a/packages/website/ts/components/top_bar/provider_picker.tsx
+++ b/packages/website/ts/components/top_bar/provider_picker.tsx
@@ -1,11 +1,9 @@
import { colors, constants as sharedConstants } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import { RadioButton, RadioButtonGroup } from 'material-ui/RadioButton';
import * as React from 'react';
import { Blockchain } from 'ts/blockchain';
import { Dispatcher } from 'ts/redux/dispatcher';
import { ProviderType } from 'ts/types';
-import { constants } from 'ts/utils/constants';
interface ProviderPickerProps {
networkId: number;
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index e2d791ae3..05cc6e3ad 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -6,19 +6,16 @@ import Menu from 'material-ui/Menu';
import MenuItem from 'material-ui/MenuItem';
import * as React from 'react';
import { Link } from 'react-router-dom';
-import ReactTooltip = require('react-tooltip');
import { Blockchain } from 'ts/blockchain';
import { LegacyPortalMenu } from 'ts/components/legacy_portal/legacy_portal_menu';
import { DrawerMenu } from 'ts/components/portal/drawer_menu';
-import { SidebarHeader } from 'ts/components/sidebar_header';
import { ProviderDisplay } from 'ts/components/top_bar/provider_display';
import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item';
import { DropDown } from 'ts/components/ui/drop_down';
-import { Identicon } from 'ts/components/ui/identicon';
import { Dispatcher } from 'ts/redux/dispatcher';
+import { zIndex } from 'ts/style/z_index';
import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
-import { zIndex } from 'ts/utils/style';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
@@ -165,6 +162,12 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
primaryText={this.props.translate.get(Key.SolCov, Deco.CapWords)}
/>
</Link>,
+ <Link key="subMenuItem-ethereum-types" to={WebsitePaths.EthereumTypes} className="text-decoration-none">
+ <MenuItem
+ style={{ fontSize: styles.menuItem.fontSize }}
+ primaryText={this.props.translate.get(Key.EthereumTypes, Deco.CapWords)}
+ />
+ </Link>,
<a
key="subMenuItem-whitePaper"
target="_blank"
@@ -379,6 +382,14 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
</MenuItem>
</Link>
)}
+ {!this._isViewingEthereumTypesDocs() && (
+ <Link to={WebsitePaths.EthereumTypes} className="text-decoration-none">
+ <MenuItem className="py2">
+ {this.props.translate.get(Key.EthereumTypes, Deco.Cap)}{' '}
+ {this.props.translate.get(Key.Docs, Deco.Cap)}
+ </MenuItem>
+ </Link>
+ )}
{!this._isViewingPortal() && (
<Link to={`${WebsitePaths.Portal}`} className="text-decoration-none">
<MenuItem className="py2">
@@ -418,8 +429,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
) {
return undefined;
}
-
- const sectionTitle = `${this.props.docsInfo.displayName} Docs`;
return (
<div className="lg-hide md-hide">
<NestedSidebarMenu
@@ -507,6 +516,9 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
private _isViewingSubprovidersDocs(): boolean {
return _.includes(this.props.location.pathname, WebsitePaths.Subproviders);
}
+ private _isViewingEthereumTypesDocs(): boolean {
+ return _.includes(this.props.location.pathname, WebsitePaths.EthereumTypes);
+ }
private _isViewingWiki(): boolean {
return _.includes(this.props.location.pathname, WebsitePaths.Wiki);
}
diff --git a/packages/website/ts/components/trade_history/trade_history.tsx b/packages/website/ts/components/trade_history/trade_history.tsx
index 1ca9d866f..84c0f70a8 100644
--- a/packages/website/ts/components/trade_history/trade_history.tsx
+++ b/packages/website/ts/components/trade_history/trade_history.tsx
@@ -13,6 +13,9 @@ interface TradeHistoryProps {
tokenByAddress: TokenByAddress;
userAddress: string;
networkId: number;
+ isFullWidth?: boolean;
+ shouldHideHeader?: boolean;
+ isScrollable?: boolean;
}
interface TradeHistoryState {
@@ -20,6 +23,11 @@ interface TradeHistoryState {
}
export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistoryState> {
+ public static defaultProps: Partial<TradeHistoryProps> = {
+ isFullWidth: false,
+ shouldHideHeader: false,
+ isScrollable: true,
+ };
private _fillPollingIntervalId: number;
public constructor(props: TradeHistoryProps) {
super(props);
@@ -38,13 +46,22 @@ export class TradeHistory extends React.Component<TradeHistoryProps, TradeHistor
window.scrollTo(0, 0);
}
public render(): React.ReactNode {
+ const rootClassName = !this.props.isFullWidth ? 'lg-px4 md-px4 sm-px2' : undefined;
return (
- <div className="lg-px4 md-px4 sm-px2">
- <h3>Trade history</h3>
- <Divider />
- <div className="pt2" style={{ height: 608, overflow: 'scroll' }}>
- {this._renderTrades()}
- </div>
+ <div className={rootClassName}>
+ {!this.props.shouldHideHeader && (
+ <div>
+ <h3>Trade history</h3>
+ <Divider />
+ </div>
+ )}
+ {this.props.isScrollable ? (
+ <div className="pt2" style={{ height: 608, overflow: 'scroll' }}>
+ {this._renderTrades()}
+ </div>
+ ) : (
+ this._renderTrades()
+ )}
</div>
);
}
diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx
new file mode 100644
index 000000000..1f88297de
--- /dev/null
+++ b/packages/website/ts/components/ui/button.tsx
@@ -0,0 +1,81 @@
+import { colors } from '@0xproject/react-shared';
+import { darken } from 'polished';
+import * as React from 'react';
+import { styled } from 'ts/style/theme';
+
+export interface ButtonProps {
+ className?: string;
+ fontSize?: string;
+ fontColor?: string;
+ fontFamily?: string;
+ backgroundColor?: string;
+ borderColor?: string;
+ width?: string;
+ type?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+}
+
+const PlainButton: React.StatelessComponent<ButtonProps> = ({ children, onClick, type, className }) => (
+ <button type={type} className={className} onClick={onClick}>
+ {children}
+ </button>
+);
+
+export const Button = styled(PlainButton)`
+ cursor: pointer;
+ font-size: ${props => props.fontSize};
+ color: ${props => props.fontColor};
+ padding: 0.8em 2.2em;
+ border-radius: 6px;
+ box-shadow: 0px 0px 4px rgba(0, 0, 0, 0.25);
+ font-weight: 500;
+ font-family: ${props => props.fontFamily};
+ width: ${props => props.width};
+ background-color: ${props => props.backgroundColor};
+ border: ${props => (props.borderColor ? `1px solid ${props.borderColor}` : 'none')};
+ &:hover {
+ background-color: ${props => darken(0.1, props.backgroundColor)};
+ }
+ &:active {
+ background-color: ${props => darken(0.2, props.backgroundColor)};
+ }
+`;
+
+Button.defaultProps = {
+ fontSize: '12px',
+ backgroundColor: colors.white,
+ width: 'auto',
+ fontFamily: 'Roboto',
+};
+
+Button.displayName = 'Button';
+
+type CallToActionType = 'light' | 'dark';
+
+export interface CallToActionProps {
+ type?: CallToActionType;
+ fontSize?: string;
+ width?: string;
+}
+
+export const CallToAction: React.StatelessComponent<CallToActionProps> = ({ children, type, fontSize, width }) => {
+ const isLight = type === 'light';
+ const backgroundColor = isLight ? colors.white : colors.heroGrey;
+ const fontColor = isLight ? colors.heroGrey : colors.white;
+ const borderColor = isLight ? undefined : colors.white;
+ return (
+ <Button
+ fontSize={fontSize}
+ backgroundColor={backgroundColor}
+ fontColor={fontColor}
+ width={width}
+ borderColor={borderColor}
+ >
+ {children}
+ </Button>
+ );
+};
+
+CallToAction.defaultProps = {
+ type: 'dark',
+};
diff --git a/packages/website/ts/components/ui/container.tsx b/packages/website/ts/components/ui/container.tsx
index d577447b0..c6a78e181 100644
--- a/packages/website/ts/components/ui/container.tsx
+++ b/packages/website/ts/components/ui/container.tsx
@@ -11,13 +11,20 @@ export interface ContainerProps {
paddingBottom?: StringOrNum;
paddingRight?: StringOrNum;
paddingLeft?: StringOrNum;
+ backgroundColor?: string;
+ borderRadius?: StringOrNum;
maxWidth?: StringOrNum;
- children?: React.ReactNode;
+ isHidden?: boolean;
+ className?: string;
}
-export const Container: React.StatelessComponent<ContainerProps> = (props: ContainerProps) => {
- const { children, ...style } = props;
- return <div style={style}>{children}</div>;
+export const Container: React.StatelessComponent<ContainerProps> = ({ children, className, isHidden, ...style }) => {
+ const visibility = isHidden ? 'hidden' : undefined;
+ return (
+ <div style={{ ...style, visibility }} className={className}>
+ {children}
+ </div>
+ );
};
Container.displayName = 'Container';
diff --git a/packages/website/ts/components/ui/copy_icon.tsx b/packages/website/ts/components/ui/copy_icon.tsx
index 2c2941067..0330d1843 100644
--- a/packages/website/ts/components/ui/copy_icon.tsx
+++ b/packages/website/ts/components/ui/copy_icon.tsx
@@ -1,5 +1,4 @@
import { colors } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import * as React from 'react';
import * as CopyToClipboard from 'react-copy-to-clipboard';
import * as ReactDOM from 'react-dom';
diff --git a/packages/website/ts/components/ui/drop_down.tsx b/packages/website/ts/components/ui/drop_down.tsx
index 98a495581..22cb942f8 100644
--- a/packages/website/ts/components/ui/drop_down.tsx
+++ b/packages/website/ts/components/ui/drop_down.tsx
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import Popover, { PopoverAnimationVertical } from 'material-ui/Popover';
import * as React from 'react';
import { MaterialUIPosition } from 'ts/types';
@@ -43,7 +42,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
public componentWillUnmount(): void {
window.clearInterval(this._popoverCloseCheckIntervalId);
}
- public componentWillReceiveProps(nextProps: DropDownProps): void {
+ public componentWillReceiveProps(_nextProps: DropDownProps): void {
// HACK: If the popoverContent is updated to a different dimension and the users
// mouse is no longer above it, the dropdown can enter an inconsistent state where
// it believes the user is still hovering over it. In order to remedy this, we
diff --git a/packages/website/ts/components/ui/etherscan_icon.tsx b/packages/website/ts/components/ui/etherscan_icon.tsx
index 1b032c112..0beb69123 100644
--- a/packages/website/ts/components/ui/etherscan_icon.tsx
+++ b/packages/website/ts/components/ui/etherscan_icon.tsx
@@ -2,7 +2,6 @@ import { colors, EtherscanLinkSuffixes, utils as sharedUtils } from '@0xproject/
import * as _ from 'lodash';
import * as React from 'react';
import ReactTooltip = require('react-tooltip');
-import { utils } from 'ts/utils/utils';
interface EtherScanIconProps {
addressOrTxHash: string;
diff --git a/packages/website/ts/components/ui/filled_image.tsx b/packages/website/ts/components/ui/filled_image.tsx
new file mode 100644
index 000000000..7f58ee5b9
--- /dev/null
+++ b/packages/website/ts/components/ui/filled_image.tsx
@@ -0,0 +1,18 @@
+import * as React from 'react';
+
+export interface FilledImageProps {
+ src: string;
+}
+export const FilledImage = (props: FilledImageProps) => (
+ <div
+ style={{
+ width: '100%',
+ height: '100%',
+ objectFit: 'cover',
+ backgroundImage: `url(${props.src})`,
+ backgroundRepeat: 'no-repeat',
+ backgroundPosition: 'center',
+ backgroundSize: 'cover',
+ }}
+ />
+);
diff --git a/packages/website/ts/components/ui/input.tsx b/packages/website/ts/components/ui/input.tsx
new file mode 100644
index 000000000..e01a71a53
--- /dev/null
+++ b/packages/website/ts/components/ui/input.tsx
@@ -0,0 +1,43 @@
+import { colors } from '@0xproject/react-shared';
+import * as React from 'react';
+import { styled } from 'ts/style/theme';
+
+export interface InputProps {
+ className?: string;
+ value?: string;
+ width?: string;
+ fontSize?: string;
+ fontColor?: string;
+ placeholderColor?: string;
+ placeholder?: string;
+ backgroundColor?: string;
+ onChange?: (event: React.ChangeEvent<HTMLInputElement>) => void;
+}
+
+const PlainInput: React.StatelessComponent<InputProps> = ({ value, className, placeholder, onChange }) => (
+ <input className={className} value={value} onChange={onChange} placeholder={placeholder} />
+);
+
+export const Input = styled(PlainInput)`
+ font-size: ${props => props.fontSize};
+ width: ${props => props.width};
+ padding: 0.8em 1.2em;
+ border-radius: 3px;
+ font-family: 'Roboto Mono';
+ color: ${props => props.fontColor};
+ border: none;
+ background-color: ${props => props.backgroundColor};
+ &::placeholder {
+ color: ${props => props.placeholderColor};
+ }
+`;
+
+Input.defaultProps = {
+ width: 'auto',
+ backgroundColor: colors.white,
+ fontColor: colors.darkestGrey,
+ placeholderColor: colors.darkGrey,
+ fontSize: '12px',
+};
+
+Input.displayName = 'Input';
diff --git a/packages/website/ts/components/ui/island.tsx b/packages/website/ts/components/ui/island.tsx
index f5480c9c9..de90b664f 100644
--- a/packages/website/ts/components/ui/island.tsx
+++ b/packages/website/ts/components/ui/island.tsx
@@ -1,6 +1,5 @@
import * as React from 'react';
-import { Styleable } from 'ts/types';
-import { colors } from 'ts/utils/colors';
+import { colors } from 'ts/style/colors';
export interface IslandProps {
style?: React.CSSProperties;
diff --git a/packages/website/ts/components/ui/lifecycle_raised_button.tsx b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
index b06978f16..380fbc77d 100644
--- a/packages/website/ts/components/ui/lifecycle_raised_button.tsx
+++ b/packages/website/ts/components/ui/lifecycle_raised_button.tsx
@@ -1,8 +1,7 @@
import { colors } from '@0xproject/react-shared';
-import * as _ from 'lodash';
+import { errorUtils } from '@0xproject/utils';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
-import { utils } from 'ts/utils/utils';
const COMPLETE_STATE_SHOW_LENGTH_MS = 2000;
@@ -63,7 +62,7 @@ export class LifeCycleRaisedButton extends React.Component<LifeCycleRaisedButton
label = this.props.labelComplete;
break;
default:
- throw utils.spawnSwitchErr('ButtonState', this.state.buttonState);
+ throw errorUtils.spawnSwitchErr('ButtonState', this.state.buttonState);
}
return (
<RaisedButton
diff --git a/packages/website/ts/components/ui/overlay.tsx b/packages/website/ts/components/ui/overlay.tsx
index bb2ed8e59..8b126a6d5 100644
--- a/packages/website/ts/components/ui/overlay.tsx
+++ b/packages/website/ts/components/ui/overlay.tsx
@@ -1,8 +1,7 @@
-import { colors } from '@0xproject/react-shared';
import * as _ from 'lodash';
import * as React from 'react';
-import { zIndex } from 'ts/utils/style';
+import { zIndex } from 'ts/style/z_index';
export interface OverlayProps {
children?: React.ReactNode;
diff --git a/packages/website/ts/components/ui/party.tsx b/packages/website/ts/components/ui/party.tsx
index 0d86a6db5..a25550475 100644
--- a/packages/website/ts/components/ui/party.tsx
+++ b/packages/website/ts/components/ui/party.tsx
@@ -4,7 +4,6 @@ import * as React from 'react';
import ReactTooltip = require('react-tooltip');
import { EthereumAddress } from 'ts/components/ui/ethereum_address';
import { Identicon } from 'ts/components/ui/identicon';
-import { utils } from 'ts/utils/utils';
const IMAGE_DIMENSION = 100;
const IDENTICON_DIAMETER = 95;
diff --git a/packages/website/ts/components/ui/retry.tsx b/packages/website/ts/components/ui/retry.tsx
new file mode 100644
index 000000000..543b7df4b
--- /dev/null
+++ b/packages/website/ts/components/ui/retry.tsx
@@ -0,0 +1,32 @@
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+import { colors } from 'ts/style/colors';
+
+const BUTTON_TEXT = 'reload';
+
+export interface RetryProps {
+ onRetry: () => void;
+}
+export const Retry = (props: RetryProps) => (
+ <div className="clearfix center" style={{ color: colors.black }}>
+ <div className="mx-auto inline-block align-middle" style={{ lineHeight: '44px', textAlign: 'center' }}>
+ <div className="h2" style={{ fontFamily: 'Roboto Mono' }}>
+ Something went wrong.
+ </div>
+ <div className="py3">
+ <Button
+ type="button"
+ backgroundColor={colors.black}
+ width="290px"
+ fontColor={colors.white}
+ fontSize="18px"
+ fontFamily="Roboto Mono"
+ onClick={props.onRetry}
+ >
+ {BUTTON_TEXT}
+ </Button>
+ </div>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/components/ui/swap_icon.tsx b/packages/website/ts/components/ui/swap_icon.tsx
index 4a6000d1b..f1d1ae7d4 100644
--- a/packages/website/ts/components/ui/swap_icon.tsx
+++ b/packages/website/ts/components/ui/swap_icon.tsx
@@ -1,5 +1,4 @@
import { colors } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import * as React from 'react';
interface SwapIconProps {
diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx
new file mode 100644
index 000000000..7e47f1d09
--- /dev/null
+++ b/packages/website/ts/components/ui/text.tsx
@@ -0,0 +1,41 @@
+import { colors } from '@0xproject/react-shared';
+import * as React from 'react';
+import { styled } from 'ts/style/theme';
+
+export type TextTag = 'p' | 'div' | 'span' | 'label';
+
+export interface TextProps {
+ className?: string;
+ Tag?: TextTag;
+ fontSize?: string;
+ fontFamily?: string;
+ fontColor?: string;
+ lineHeight?: string;
+ minHeight?: string;
+ center?: boolean;
+ fontWeight?: number | string;
+}
+
+const PlainText: React.StatelessComponent<TextProps> = ({ children, className, Tag }) => (
+ <Tag className={className}>{children}</Tag>
+);
+
+export const Text = styled(PlainText)`
+ font-family: ${props => props.fontFamily};
+ font-weight: ${props => props.fontWeight};
+ font-size: ${props => props.fontSize};
+ ${props => (props.lineHeight ? `line-height: ${props.lineHeight}` : '')};
+ ${props => (props.center ? 'text-align: center' : '')};
+ color: ${props => props.fontColor};
+ ${props => (props.minHeight ? `min-height: ${props.minHeight}` : '')};
+`;
+
+Text.defaultProps = {
+ fontFamily: 'Roboto',
+ fontWeight: 400,
+ fontColor: colors.white,
+ fontSize: '14px',
+ Tag: 'div',
+};
+
+Text.displayName = 'Text';
diff --git a/packages/website/ts/components/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx
index 7059ca350..4523b0ac9 100644
--- a/packages/website/ts/components/wallet/wallet.tsx
+++ b/packages/website/ts/components/wallet/wallet.tsx
@@ -1,29 +1,18 @@
-import {
- constants as sharedConstants,
- EtherscanLinkSuffixes,
- Styles,
- utils as sharedUtils,
-} from '@0xproject/react-shared';
-import { BigNumber } from '@0xproject/utils';
+import { EtherscanLinkSuffixes, Styles, utils as sharedUtils } from '@0xproject/react-shared';
+import { BigNumber, errorUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
-import FlatButton from 'material-ui/FlatButton';
import FloatingActionButton from 'material-ui/FloatingActionButton';
import { ListItem } from 'material-ui/List';
import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
import ContentAdd from 'material-ui/svg-icons/content/add';
import ContentRemove from 'material-ui/svg-icons/content/remove';
-import NavigationArrowDownward from 'material-ui/svg-icons/navigation/arrow-downward';
-import NavigationArrowUpward from 'material-ui/svg-icons/navigation/arrow-upward';
-import Close from 'material-ui/svg-icons/navigation/close';
import * as React from 'react';
import { Link } from 'react-router-dom';
-import ReactTooltip = require('react-tooltip');
import firstBy = require('thenby');
import { Blockchain } from 'ts/blockchain';
-import { AllowanceToggle } from 'ts/components/inputs/allowance_toggle';
import { Container } from 'ts/components/ui/container';
import { IconButton } from 'ts/components/ui/icon_button';
import { Identicon } from 'ts/components/ui/identicon';
@@ -31,11 +20,12 @@ 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';
+import { AllowanceToggle } from 'ts/containers/inputs/allowance_toggle';
import { Dispatcher } from 'ts/redux/dispatcher';
+import { colors } from 'ts/style/colors';
+import { zIndex } from 'ts/style/z_index';
import {
- BalanceErrs,
BlockchainErrs,
- ItemByAddress,
ProviderType,
ScreenWidths,
Side,
@@ -45,10 +35,7 @@ import {
TokenStateByAddress,
WebsitePaths,
} from 'ts/types';
-import { backendClient } from 'ts/utils/backend_client';
-import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants';
-import { zIndex } from 'ts/utils/style';
import { utils } from 'ts/utils/utils';
import { styles as walletItemStyles } from 'ts/utils/wallet_item_styles';
@@ -137,7 +124,7 @@ const styles: Styles = {
const ETHER_ICON_PATH = '/images/ether.png';
const ICON_DIMENSION = 28;
-const TOKEN_AMOUNT_DISPLAY_PRECISION = 3;
+const TOKEN_AMOUNT_DISPLAY_PRECISION = 5;
const BODY_ITEM_KEY = 'BODY';
const HEADER_ITEM_KEY = 'HEADER';
const FOOTER_ITEM_KEY = 'FOOTER';
@@ -148,10 +135,8 @@ const NO_ALLOWANCE_TOGGLE_SPACE_WIDTH = 56;
const ACCOUNT_PATH = `${WebsitePaths.Portal}/account`;
export class Wallet extends React.Component<WalletProps, WalletState> {
- private _isUnmounted: boolean;
constructor(props: WalletProps) {
super(props);
- this._isUnmounted = false;
this.state = {
wrappedEtherDirection: undefined,
isHoveringSidebar: false,
@@ -185,7 +170,6 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
);
}
private _renderDisconnectedHeaderRows(): React.ReactElement<{}> {
- const userAddress = this.props.userAddress;
const primaryText = 'wallet';
return (
<StandardIconRow
@@ -238,7 +222,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
</div>
);
}
- private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void {
+ private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
this.setState({
isHoveringSidebar: true,
});
@@ -330,7 +314,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
);
return _.map(trackedTokensStartingWithEtherToken, this._renderTokenRow.bind(this));
}
- private _renderTokenRow(token: Token, index: number): React.ReactNode {
+ private _renderTokenRow(token: Token, _index: number): React.ReactNode {
const tokenState = this.props.trackedTokenStateByAddress[token.address];
const tokenLink = sharedUtils.getEtherScanLinkIfExists(
token.address,
@@ -430,15 +414,12 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
);
}
private _renderAllowanceToggle(config: AllowanceToggleConfig): React.ReactNode {
+ // TODO: Error handling
return (
<AllowanceToggle
- networkId={this.props.networkId}
blockchain={this.props.blockchain}
- dispatcher={this.props.dispatcher}
token={config.token}
tokenState={config.tokenState}
- onErrorOccurred={_.noop} // TODO: Error handling
- userAddress={this.props.userAddress}
isDisabled={!config.tokenState.isLoaded}
refetchTokenStateAsync={async () => this.props.refetchTokenStateAsync(config.token.address)}
/>
@@ -450,14 +431,19 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
symbol: string,
isLoading: boolean = false,
): React.ReactNode {
- const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
- const formattedAmount = unitAmount.toPrecision(TOKEN_AMOUNT_DISPLAY_PRECISION);
- const result = `${formattedAmount} ${symbol}`;
- return (
- <PlaceHolder hideChildren={isLoading}>
- <div style={styles.amountLabel}>{result}</div>
- </PlaceHolder>
- );
+ if (isLoading) {
+ return (
+ <PlaceHolder hideChildren={isLoading}>
+ <div style={styles.amountLabel}>0.00 XXX</div>
+ </PlaceHolder>
+ );
+ } else {
+ const unitAmount = Web3Wrapper.toUnitAmount(amount, decimals);
+ const precision = Math.min(TOKEN_AMOUNT_DISPLAY_PRECISION, unitAmount.decimalPlaces());
+ const formattedAmount = unitAmount.toFixed(precision);
+ const result = `${formattedAmount} ${symbol}`;
+ return <div style={styles.amountLabel}>{result}</div>;
+ }
}
private _renderValue(
amount: BigNumber,
@@ -502,7 +488,7 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
buttonIconName = 'zmdi-long-arrow-up';
break;
default:
- throw utils.spawnSwitchErr('wrappedEtherDirection', wrappedEtherDirection);
+ throw errorUtils.spawnSwitchErr('wrappedEtherDirection', wrappedEtherDirection);
}
}
const onClick = isWrappedEtherDirectionOpen
@@ -512,45 +498,6 @@ export class Wallet extends React.Component<WalletProps, WalletState> {
<IconButton iconName={buttonIconName} labelText={buttonLabel} onClick={onClick} color={colors.mediumBlue} />
);
}
- private _getInitialTrackedTokenStateByAddress(tokenAddresses: string[]): TokenStateByAddress {
- const trackedTokenStateByAddress: TokenStateByAddress = {};
- _.each(tokenAddresses, tokenAddress => {
- trackedTokenStateByAddress[tokenAddress] = {
- balance: new BigNumber(0),
- allowance: new BigNumber(0),
- isLoaded: false,
- };
- });
- return trackedTokenStateByAddress;
- }
-
- private async _getPriceByAddressAsync(tokenAddresses: string[]): Promise<ItemByAddress<BigNumber>> {
- if (_.isEmpty(tokenAddresses)) {
- return {};
- }
- // for each input token address, search for the corresponding symbol in this.props.tokenByAddress, if it exists
- // create a mapping from existing symbols -> address
- const tokenAddressBySymbol: { [symbol: string]: string } = {};
- _.each(tokenAddresses, address => {
- const tokenIfExists = _.get(this.props.tokenByAddress, address);
- if (!_.isUndefined(tokenIfExists)) {
- const symbol = tokenIfExists.symbol;
- tokenAddressBySymbol[symbol] = address;
- }
- });
- const tokenSymbols = _.keys(tokenAddressBySymbol);
- try {
- const priceBySymbol = await backendClient.getPriceInfoAsync(tokenSymbols);
- const priceByAddress = _.mapKeys(priceBySymbol, (value, symbol) => _.get(tokenAddressBySymbol, symbol));
- const result = _.mapValues(priceByAddress, price => {
- const priceBigNumber = new BigNumber(price);
- return priceBigNumber;
- });
- return result;
- } catch (err) {
- return {};
- }
- }
private _openWrappedEtherActionRow(wrappedEtherDirection: Side): void {
this.setState({
wrappedEtherDirection,
diff --git a/packages/website/ts/components/wallet/wallet_disconnected_item.tsx b/packages/website/ts/components/wallet/wallet_disconnected_item.tsx
index 17fd8a19e..1015dce29 100644
--- a/packages/website/ts/components/wallet/wallet_disconnected_item.tsx
+++ b/packages/website/ts/components/wallet/wallet_disconnected_item.tsx
@@ -1,10 +1,9 @@
import { Styles } from '@0xproject/react-shared';
import FlatButton from 'material-ui/FlatButton';
-import ActionAccountBalanceWallet from 'material-ui/svg-icons/action/account-balance-wallet';
import * as React from 'react';
+import { colors } from 'ts/style/colors';
import { ProviderType } from 'ts/types';
-import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants';
import { utils } from 'ts/utils/utils';
diff --git a/packages/website/ts/components/wallet/wrap_ether_item.tsx b/packages/website/ts/components/wallet/wrap_ether_item.tsx
index 1dfcffadf..f65257142 100644
--- a/packages/website/ts/components/wallet/wrap_ether_item.tsx
+++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx
@@ -3,15 +3,14 @@ import { BigNumber, logUtils } from '@0xproject/utils';
import { Web3Wrapper } from '@0xproject/web3-wrapper';
import * as _ from 'lodash';
import FlatButton from 'material-ui/FlatButton';
-import { ListItem } from 'material-ui/List';
import * as React from 'react';
import { Blockchain } from 'ts/blockchain';
import { EthAmountInput } from 'ts/components/inputs/eth_amount_input';
import { TokenAmountInput } from 'ts/components/inputs/token_amount_input';
import { Dispatcher } from 'ts/redux/dispatcher';
+import { colors } from 'ts/style/colors';
import { BlockchainCallErrs, Side, Token } from 'ts/types';
-import { colors } from 'ts/utils/colors';
import { constants } from 'ts/utils/constants';
import { errorReporter } from 'ts/utils/error_reporter';
import { utils } from 'ts/utils/utils';
@@ -146,7 +145,7 @@ export class WrapEtherItem extends React.Component<WrapEtherItemProps, WrapEther
</div>
);
}
- private _onValueChange(isValid: boolean, amount?: BigNumber): void {
+ private _onValueChange(_isValid: boolean, amount?: BigNumber): void {
this.setState({
currentInputAmount: amount,
});
diff --git a/packages/website/ts/containers/about.ts b/packages/website/ts/containers/about.ts
index ce8fd3afb..3b1c99d79 100644
--- a/packages/website/ts/containers/about.ts
+++ b/packages/website/ts/containers/about.ts
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -15,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: AboutProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: AboutProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/connect_documentation.ts b/packages/website/ts/containers/connect_documentation.ts
index 698d605c9..f939ef0df 100644
--- a/packages/website/ts/containers/connect_documentation.ts
+++ b/packages/website/ts/containers/connect_documentation.ts
@@ -1,13 +1,11 @@
import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { DocPackages } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -91,7 +89,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/ethereum_types_documentation.ts b/packages/website/ts/containers/ethereum_types_documentation.ts
new file mode 100644
index 000000000..285438835
--- /dev/null
+++ b/packages/website/ts/containers/ethereum_types_documentation.ts
@@ -0,0 +1,122 @@
+import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+import { DocPackages } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { Translate } from 'ts/utils/translate';
+
+/* tslint:disable:no-var-requires */
+const IntroMarkdown = require('md/docs/ethereum_types/introduction');
+const InstallationMarkdown = require('md/docs/ethereum_types/installation');
+/* tslint:enable:no-var-requires */
+
+const docSections = {
+ introduction: 'introduction',
+ installation: 'installation',
+ types: docConstants.TYPES_SECTION_NAME,
+};
+
+const docsInfoConfig: DocsInfoConfig = {
+ id: DocPackages.EthereumTypes,
+ type: SupportedDocJson.TypeDoc,
+ displayName: 'Ethereum Types',
+ packageUrl: 'https://github.com/0xProject/0x-monorepo/packages/ethereum-types',
+ menu: {
+ introduction: [docSections.introduction],
+ install: [docSections.installation],
+ types: [docSections.types],
+ },
+ sectionNameToMarkdown: {
+ [docSections.introduction]: IntroMarkdown,
+ [docSections.installation]: InstallationMarkdown,
+ },
+ sectionNameToModulePath: {
+ [docSections.types]: ['"index"'],
+ },
+ visibleConstructors: [],
+ menuSubsectionToVersionWhenIntroduced: {},
+ sections: docSections,
+ typeConfigs: {
+ // Note: This needs to be kept in sync with the types exported in index.ts. Unfortunately there is
+ // currently no way to extract the re-exported types from index.ts via TypeDoc :(
+ publicTypes: [
+ 'Provider',
+ 'JSONRPCErrorCallback',
+ 'Provider',
+ 'ContractAbi',
+ 'AbiDefinition',
+ 'FunctionAbi',
+ 'ConstructorStateMutability',
+ 'StateMutability',
+ 'MethodAbi',
+ 'ConstructorAbi',
+ 'FallbackAbi',
+ 'EventParameter',
+ 'EventAbi',
+ 'DataItem',
+ 'OpCode',
+ // 'StructLog', // TODO: This type breaks the docs so we don't render it for now
+ 'TransactionTrace',
+ 'Unit',
+ 'JSONRPCRequestPayload',
+ 'JSONRPCResponsePayload',
+ 'BlockWithoutTransactionData',
+ 'BlockWithTransactionData',
+ 'Transaction',
+ 'TxData',
+ 'CallData',
+ 'FilterObject',
+ 'LogTopic',
+ 'DecodedLogEntry',
+ 'DecodedLogEntryEvent',
+ 'LogEntryEvent',
+ 'LogEntry',
+ 'TxDataPayable',
+ 'TransactionReceipt',
+ 'AbiType',
+ 'ContractEventArg',
+ 'DecodedLogArgs',
+ 'LogWithDecodedArgs',
+ 'RawLog',
+ 'BlockParamLiteral',
+ 'BlockParam',
+ 'RawLogEntry',
+ 'SolidityTypes',
+ 'TransactionReceiptWithDecodedLogs',
+ ],
+ typeNameToExternalLink: {
+ BigNumber: constants.URL_BIGNUMBERJS_GITHUB,
+ },
+ },
+};
+const docsInfo = new DocsInfo(docsInfoConfig);
+
+interface ConnectedState {
+ docsVersion: string;
+ availableDocVersions: string[];
+ docsInfo: DocsInfo;
+ translate: Translate;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
+ docsVersion: state.docsVersion,
+ availableDocVersions: state.availableDocVersions,
+ translate: state.translate,
+ docsInfo,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const Documentation: React.ComponentClass<DocPageProps> = connect(mapStateToProps, mapDispatchToProps)(
+ DocPageComponent,
+);
diff --git a/packages/website/ts/containers/faq.ts b/packages/website/ts/containers/faq.ts
index b539e33c9..a2b5735f6 100644
--- a/packages/website/ts/containers/faq.ts
+++ b/packages/website/ts/containers/faq.ts
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -15,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: FAQProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: FAQProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/generate_order_form.ts b/packages/website/ts/containers/generate_order_form.ts
index 98c9b8cd6..92296dbab 100644
--- a/packages/website/ts/containers/generate_order_form.ts
+++ b/packages/website/ts/containers/generate_order_form.ts
@@ -1,6 +1,5 @@
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Blockchain } from 'ts/blockchain';
@@ -13,6 +12,8 @@ interface GenerateOrderFormProps {
blockchain: Blockchain;
hashData: HashData;
dispatcher: Dispatcher;
+ isFullWidth?: boolean;
+ shouldHideHeader?: boolean;
}
interface ConnectedState {
@@ -29,7 +30,7 @@ interface ConnectedState {
lastForceTokenStateRefetch: number;
}
-const mapStateToProps = (state: State, ownProps: GenerateOrderFormProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: GenerateOrderFormProps): ConnectedState => ({
blockchainErr: state.blockchainErr,
blockchainIsLoaded: state.blockchainIsLoaded,
orderExpiryTimestamp: state.orderExpiryTimestamp,
diff --git a/packages/website/ts/containers/inputs/allowance_toggle.ts b/packages/website/ts/containers/inputs/allowance_toggle.ts
new file mode 100644
index 000000000..545708f92
--- /dev/null
+++ b/packages/website/ts/containers/inputs/allowance_toggle.ts
@@ -0,0 +1,41 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { Blockchain } from 'ts/blockchain';
+import { State } from 'ts/redux/reducer';
+import { BalanceErrs, Token, TokenState } from 'ts/types';
+
+import { AllowanceToggle as AllowanceToggleComponent } from 'ts/components/inputs/allowance_toggle';
+import { Dispatcher } from 'ts/redux/dispatcher';
+
+interface AllowanceToggleProps {
+ blockchain: Blockchain;
+ onErrorOccurred?: (errType: BalanceErrs) => void;
+ token: Token;
+ tokenState: TokenState;
+ isDisabled?: boolean;
+ refetchTokenStateAsync: () => Promise<void>;
+}
+
+interface ConnectedState {
+ networkId: number;
+ userAddress: string;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: AllowanceToggleProps): ConnectedState => ({
+ networkId: state.networkId,
+ userAddress: state.userAddress,
+});
+
+const mapDispatchTopProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const AllowanceToggle: React.ComponentClass<AllowanceToggleProps> = connect(
+ mapStateToProps,
+ mapDispatchTopProps,
+)(AllowanceToggleComponent);
diff --git a/packages/website/ts/containers/jobs.ts b/packages/website/ts/containers/jobs.ts
new file mode 100644
index 000000000..b18485882
--- /dev/null
+++ b/packages/website/ts/containers/jobs.ts
@@ -0,0 +1,28 @@
+import * as React from 'react';
+import { connect } from 'react-redux';
+import { Dispatch } from 'redux';
+import { Jobs as JobsComponent, JobsProps } from 'ts/pages/jobs/jobs';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { State } from 'ts/redux/reducer';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+
+interface ConnectedState {
+ translate: Translate;
+ screenWidth: ScreenWidths;
+}
+
+interface ConnectedDispatch {
+ dispatcher: Dispatcher;
+}
+
+const mapStateToProps = (state: State, _ownProps: JobsProps): ConnectedState => ({
+ translate: state.translate,
+ screenWidth: state.screenWidth,
+});
+
+const mapDispatchToProps = (dispatch: Dispatch<State>): ConnectedDispatch => ({
+ dispatcher: new Dispatcher(dispatch),
+});
+
+export const Jobs: React.ComponentClass<JobsProps> = connect(mapStateToProps, mapDispatchToProps)(JobsComponent);
diff --git a/packages/website/ts/containers/json_schemas_documentation.ts b/packages/website/ts/containers/json_schemas_documentation.ts
index 154c65ffc..67740d4c6 100644
--- a/packages/website/ts/containers/json_schemas_documentation.ts
+++ b/packages/website/ts/containers/json_schemas_documentation.ts
@@ -1,14 +1,11 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
-import { constants } from 'ts/utils/constants';
+import { DocPackages } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -73,7 +70,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/landing.ts b/packages/website/ts/containers/landing.ts
index a620bb12e..972ed4c23 100644
--- a/packages/website/ts/containers/landing.ts
+++ b/packages/website/ts/containers/landing.ts
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -15,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: LandingProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: LandingProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/legacy_portal.ts b/packages/website/ts/containers/legacy_portal.ts
index eae450c21..e99f47fb7 100644
--- a/packages/website/ts/containers/legacy_portal.ts
+++ b/packages/website/ts/containers/legacy_portal.ts
@@ -37,7 +37,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: LegacyPortalComponentProps): ConnectedState => {
+const mapStateToProps = (state: State, _ownProps: LegacyPortalComponentProps): ConnectedState => {
const receiveAssetToken = state.sideToAssetToken[Side.Receive];
const depositAssetToken = state.sideToAssetToken[Side.Deposit];
const receiveAddress = !_.isUndefined(receiveAssetToken.address)
diff --git a/packages/website/ts/containers/not_found.ts b/packages/website/ts/containers/not_found.ts
index dd151e2c8..f384dab89 100644
--- a/packages/website/ts/containers/not_found.ts
+++ b/packages/website/ts/containers/not_found.ts
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -15,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: NotFoundProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: NotFoundProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/order_utils_documentation.ts b/packages/website/ts/containers/order_utils_documentation.ts
index 64aa7300f..37b7f2273 100644
--- a/packages/website/ts/containers/order_utils_documentation.ts
+++ b/packages/website/ts/containers/order_utils_documentation.ts
@@ -1,13 +1,11 @@
-import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
+import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { DocPackages } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -83,7 +81,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/portal.ts b/packages/website/ts/containers/portal.ts
index b8c8fb999..5876e65f5 100644
--- a/packages/website/ts/containers/portal.ts
+++ b/packages/website/ts/containers/portal.ts
@@ -34,7 +34,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: PortalComponentProps): ConnectedState => {
+const mapStateToProps = (state: State, _ownProps: PortalComponentProps): ConnectedState => {
const receiveAssetToken = state.sideToAssetToken[Side.Receive];
const depositAssetToken = state.sideToAssetToken[Side.Deposit];
const receiveAddress = !_.isUndefined(receiveAssetToken.address)
diff --git a/packages/website/ts/containers/portal_onboarding_flow.ts b/packages/website/ts/containers/portal_onboarding_flow.ts
index 0ad9aef13..746adf0ba 100644
--- a/packages/website/ts/containers/portal_onboarding_flow.ts
+++ b/packages/website/ts/containers/portal_onboarding_flow.ts
@@ -2,6 +2,7 @@ import { BigNumber } from '@0xproject/utils';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
+import { Blockchain } from 'ts/blockchain';
import { ActionTypes, ProviderType, TokenByAddress, TokenStateByAddress } from 'ts/types';
import { PortalOnboardingFlow as PortalOnboardingFlowComponent } from 'ts/components/onboarding/portal_onboarding_flow';
@@ -9,6 +10,8 @@ import { State } from 'ts/redux/reducer';
interface PortalOnboardingFlowProps {
trackedTokenStateByAddress: TokenStateByAddress;
+ blockchain: Blockchain;
+ refetchTokenStateAsync: (tokenAddress: string) => Promise<void>;
}
interface ConnectedState {
@@ -28,7 +31,7 @@ interface ConnectedDispatch {
updateOnboardingStep: (stepIndex: number) => void;
}
-const mapStateToProps = (state: State, ownProps: PortalOnboardingFlowProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: PortalOnboardingFlowProps): ConnectedState => ({
stepIndex: state.portalOnboardingStep,
isRunning: state.isPortalOnboardingShowing,
userAddress: state.userAddress,
diff --git a/packages/website/ts/containers/smart_contracts_documentation.ts b/packages/website/ts/containers/smart_contracts_documentation.ts
index b1b2ea922..c88c3b365 100644
--- a/packages/website/ts/containers/smart_contracts_documentation.ts
+++ b/packages/website/ts/containers/smart_contracts_documentation.ts
@@ -1,13 +1,12 @@
import { DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
import { Networks } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, SmartContractDocSections as Sections, WebsitePaths } from 'ts/types';
+import { DocPackages, SmartContractDocSections as Sections } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -76,7 +75,7 @@ interface ConnectedDispatch {
docsInfo: DocsInfo;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/sol_compiler_documentation.ts b/packages/website/ts/containers/sol_compiler_documentation.ts
index 2f6486146..8720e2c1d 100644
--- a/packages/website/ts/containers/sol_compiler_documentation.ts
+++ b/packages/website/ts/containers/sol_compiler_documentation.ts
@@ -1,14 +1,11 @@
import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
-import { constants } from 'ts/utils/constants';
+import { DocPackages } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -70,7 +67,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/sol_cov_documentation.ts b/packages/website/ts/containers/sol_cov_documentation.ts
index bc05b6854..a8009071f 100644
--- a/packages/website/ts/containers/sol_cov_documentation.ts
+++ b/packages/website/ts/containers/sol_cov_documentation.ts
@@ -1,14 +1,11 @@
import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
-import { constants } from 'ts/utils/constants';
+import { DocPackages } from 'ts/types';
import { Translate } from 'ts/utils/translate';
/* tslint:disable:no-var-requires */
@@ -99,7 +96,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/subproviders_documentation.ts b/packages/website/ts/containers/subproviders_documentation.ts
index 2178baea8..6d4230e53 100644
--- a/packages/website/ts/containers/subproviders_documentation.ts
+++ b/packages/website/ts/containers/subproviders_documentation.ts
@@ -1,13 +1,11 @@
import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { DocPackages } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -130,7 +128,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/web3_wrapper_documentation.ts b/packages/website/ts/containers/web3_wrapper_documentation.ts
index 17754ca66..b04a83ac4 100644
--- a/packages/website/ts/containers/web3_wrapper_documentation.ts
+++ b/packages/website/ts/containers/web3_wrapper_documentation.ts
@@ -1,13 +1,11 @@
import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { DocPackages } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -107,7 +105,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
translate: state.translate,
diff --git a/packages/website/ts/containers/wiki.ts b/packages/website/ts/containers/wiki.ts
index 2cb87d0a1..357f8bbf4 100644
--- a/packages/website/ts/containers/wiki.ts
+++ b/packages/website/ts/containers/wiki.ts
@@ -1,4 +1,3 @@
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
@@ -15,7 +14,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: WikiProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: WikiProps): ConnectedState => ({
translate: state.translate,
});
diff --git a/packages/website/ts/containers/zero_ex_js_documentation.ts b/packages/website/ts/containers/zero_ex_js_documentation.ts
index f68e2335f..a8890a07a 100644
--- a/packages/website/ts/containers/zero_ex_js_documentation.ts
+++ b/packages/website/ts/containers/zero_ex_js_documentation.ts
@@ -1,13 +1,11 @@
import { constants as docConstants, DocsInfo, DocsInfoConfig, SupportedDocJson } from '@0xproject/react-docs';
-import * as _ from 'lodash';
import * as React from 'react';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { DocPage as DocPageComponent, DocPageProps } from 'ts/pages/documentation/doc_page';
import { Dispatcher } from 'ts/redux/dispatcher';
import { State } from 'ts/redux/reducer';
-import { DocPackages, Environments, WebsitePaths } from 'ts/types';
-import { configs } from 'ts/utils/configs';
+import { DocPackages } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -103,6 +101,9 @@ const docsInfoConfig: DocsInfoConfig = {
'"0x.js/src/contract_wrappers/generated/ether_token"',
'"0x.js/src/contract_wrappers/generated/token"',
'"0x.js/src/contract_wrappers/generated/exchange"',
+ '"0x.js/src/generated_contract_wrappers/ether_token"',
+ '"0x.js/src/generated_contract_wrappers/token"',
+ '"0x.js/src/generated_contract_wrappers/exchange"',
],
},
menuSubsectionToVersionWhenIntroduced: {
@@ -208,7 +209,7 @@ interface ConnectedDispatch {
dispatcher: Dispatcher;
}
-const mapStateToProps = (state: State, ownProps: DocPageProps): ConnectedState => ({
+const mapStateToProps = (state: State, _ownProps: DocPageProps): ConnectedState => ({
docsVersion: state.docsVersion,
availableDocVersions: state.availableDocVersions,
docsInfo,
diff --git a/packages/website/ts/index.tsx b/packages/website/ts/index.tsx
index a6bfe7dd2..249b4fdc9 100644
--- a/packages/website/ts/index.tsx
+++ b/packages/website/ts/index.tsx
@@ -4,9 +4,10 @@ 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 { Redirecter } from 'ts/components/redirecter';
+import { Redirector } from 'ts/components/redirector';
import { About } from 'ts/containers/about';
import { FAQ } from 'ts/containers/faq';
+import { Jobs } from 'ts/containers/jobs';
import { Landing } from 'ts/containers/landing';
import { NotFound } from 'ts/containers/not_found';
import { Wiki } from 'ts/containers/wiki';
@@ -69,6 +70,9 @@ const LazySubprovidersDocumentation = createLazyComponent('Documentation', async
const LazyOrderUtilsDocumentation = createLazyComponent('Documentation', async () =>
System.import<any>(/* webpackChunkName: "orderUtilsDocs" */ 'ts/containers/order_utils_documentation'),
);
+const LazyEthereumTypesDocumentation = createLazyComponent('Documentation', async () =>
+ System.import<any>(/* webpackChunkName: "ethereumTypesDocs" */ 'ts/containers/ethereum_types_documentation'),
+);
analytics.init();
// tslint:disable-next-line:no-floating-promises
@@ -83,8 +87,12 @@ render(
<Switch>
<Route exact={true} path="/" component={Landing as any} />
<Redirect from="/otc" to={`${WebsitePaths.Portal}`} />
-
- <Route path={WebsitePaths.Jobs} component={Redirecter as any} />
+ {/* TODO: Remove this once we ship the jobs page*/}
+ {utils.shouldShowJobsPage() ? (
+ <Route path={WebsitePaths.Jobs} component={Jobs as any} />
+ ) : (
+ <Route path={WebsitePaths.Jobs} component={Redirector as any} />
+ )}
<Route path={WebsitePaths.Portal} component={LazyPortal} />
<Route path={WebsitePaths.FAQ} component={FAQ as any} />
<Route path={WebsitePaths.About} component={About as any} />
@@ -116,6 +124,10 @@ render(
path={`${WebsitePaths.SmartContracts}/:version?`}
component={LazySmartContractsDocumentation}
/>
+ <Route
+ path={`${WebsitePaths.EthereumTypes}/:version?`}
+ component={LazyEthereumTypesDocumentation}
+ />
{/* Legacy endpoints */}
<Route
diff --git a/packages/website/ts/local_storage/trade_history_storage.tsx b/packages/website/ts/local_storage/trade_history_storage.tsx
index cc764d98e..2e2f4e64e 100644
--- a/packages/website/ts/local_storage/trade_history_storage.tsx
+++ b/packages/website/ts/local_storage/trade_history_storage.tsx
@@ -57,7 +57,7 @@ export const tradeHistoryStorage = {
return {};
}
const userFillsByHash = JSON.parse(userFillsJSONString);
- _.each(userFillsByHash, (fill, hash) => {
+ _.each(userFillsByHash, fill => {
fill.paidMakerFee = new BigNumber(fill.paidMakerFee);
fill.paidTakerFee = new BigNumber(fill.paidTakerFee);
fill.filledTakerTokenAmount = new BigNumber(fill.filledTakerTokenAmount);
diff --git a/packages/website/ts/pages/about/about.tsx b/packages/website/ts/pages/about/about.tsx
index ac67ca968..3136dbca3 100644
--- a/packages/website/ts/pages/about/about.tsx
+++ b/packages/website/ts/pages/about/about.tsx
@@ -8,7 +8,6 @@ import { TopBar } from 'ts/components/top_bar/top_bar';
import { Profile } from 'ts/pages/about/profile';
import { Dispatcher } from 'ts/redux/dispatcher';
import { ProfileInfo, WebsitePaths } from 'ts/types';
-import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
diff --git a/packages/website/ts/pages/documentation/doc_page.tsx b/packages/website/ts/pages/documentation/doc_page.tsx
index 17efc56ed..8159bbd49 100644
--- a/packages/website/ts/pages/documentation/doc_page.tsx
+++ b/packages/website/ts/pages/documentation/doc_page.tsx
@@ -1,5 +1,4 @@
-import { DocAgnosticFormat, DocsInfo, Documentation, DoxityDocObj } from '@0xproject/react-docs';
-import { MenuSubsectionsBySection } from '@0xproject/react-shared';
+import { DocAgnosticFormat, DocsInfo, Documentation } from '@0xproject/react-docs';
import findVersions = require('find-versions');
import * as _ from 'lodash';
import * as React from 'react';
@@ -9,7 +8,6 @@ import { SidebarHeader } from 'ts/components/sidebar_header';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Dispatcher } from 'ts/redux/dispatcher';
import { DocPackages } from 'ts/types';
-import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
import { docUtils } from 'ts/utils/doc_utils';
import { Translate } from 'ts/utils/translate';
@@ -35,6 +33,7 @@ const docIdToSubpackageName: { [id: string]: string } = {
[DocPackages.SolCov]: 'sol-cov',
[DocPackages.Subproviders]: 'subproviders',
[DocPackages.OrderUtils]: 'order-utils',
+ [DocPackages.EthereumTypes]: 'ethereum-types',
};
export interface DocPageProps {
diff --git a/packages/website/ts/pages/faq/question.tsx b/packages/website/ts/pages/faq/question.tsx
index 28ea6881a..f80985257 100644
--- a/packages/website/ts/pages/faq/question.tsx
+++ b/packages/website/ts/pages/faq/question.tsx
@@ -1,5 +1,4 @@
import { colors } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import { Card, CardHeader, CardText } from 'material-ui/Card';
import * as React from 'react';
diff --git a/packages/website/ts/pages/jobs/benefits.tsx b/packages/website/ts/pages/jobs/benefits.tsx
new file mode 100644
index 000000000..006facc83
--- /dev/null
+++ b/packages/website/ts/pages/jobs/benefits.tsx
@@ -0,0 +1,109 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { FilledImage } from 'ts/components/ui/filled_image';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+const IMAGE_PATHS = ['/images/jobs/location1.png', '/images/jobs/location2.png', '/images/jobs/location3.png'];
+const BENEFIT_ITEM_PROPS_LIST: BenefitItemProps[] = [
+ {
+ bulletColor: '#6FCF97',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#56CCF2',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#EB5757',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#6FCF97',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#56CCF2',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+];
+const LARGE_LAYOUT_HEIGHT = 937;
+const LARGE_LAYOUT_BENEFITS_LIST_PADDING_LEFT = 205;
+const HEADER_TEXT = 'Benefits';
+const BENEFIT_ITEM_MIN_HEIGHT = 150;
+
+export interface BenefitsProps {
+ screenWidth: ScreenWidths;
+}
+
+export const Benefits = (props: BenefitsProps) => (
+ <div style={{ backgroundColor: colors.jobsPageBackground }}>
+ {props.screenWidth === ScreenWidths.Sm ? <SmallLayout /> : <LargeLayout />}
+ </div>
+);
+
+const LargeLayout = () => (
+ <div className="flex" style={{ height: LARGE_LAYOUT_HEIGHT }}>
+ <div style={{ width: '43%', height: '100%' }}>
+ <ImageGrid />
+ </div>
+ <div
+ className="pr4"
+ style={{ paddingLeft: LARGE_LAYOUT_BENEFITS_LIST_PADDING_LEFT, width: '57%', height: '100%' }}
+ >
+ <BenefitsList />
+ </div>
+ </div>
+);
+
+const SmallLayout = () => (
+ <div>
+ <FilledImage src={_.head(IMAGE_PATHS)} />
+ <BenefitsList />
+ </div>
+);
+
+export const BenefitsList = () => {
+ return (
+ <div>
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(BENEFIT_ITEM_PROPS_LIST, valueItemProps => <BenefitItem {...valueItemProps} />)}
+ </div>
+ );
+};
+interface BenefitItemProps {
+ bulletColor: string;
+ description: string;
+}
+
+const BenefitItem: React.StatelessComponent<BenefitItemProps> = ({ bulletColor, description }) => (
+ <div style={{ minHeight: BENEFIT_ITEM_MIN_HEIGHT }}>
+ <ListItem bulletColor={bulletColor}>
+ <div style={{ fontSize: 16, lineHeight: 1.5 }}>{description}</div>
+ </ListItem>
+ </div>
+);
+
+const ImageGrid = () => (
+ <div style={{ width: '100%', height: '100%' }}>
+ <div className="flex" style={{ height: '67%' }}>
+ <FilledImage src={IMAGE_PATHS[0]} />
+ </div>
+ <div className="clearfix" style={{ height: '33%' }}>
+ <div className="col lg-col-6 md-col-6 col-12" style={{ height: '100%' }}>
+ <FilledImage src={IMAGE_PATHS[1]} />
+ </div>
+ <div className="col lg-col-6 md-col-6 col-12" style={{ height: '100%' }}>
+ <FilledImage src={IMAGE_PATHS[2]} />
+ </div>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/pages/jobs/jobs.tsx b/packages/website/ts/pages/jobs/jobs.tsx
new file mode 100644
index 000000000..314669ee9
--- /dev/null
+++ b/packages/website/ts/pages/jobs/jobs.tsx
@@ -0,0 +1,81 @@
+import { colors, utils as sharedUtils } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import * as DocumentTitle from 'react-document-title';
+
+import { Footer } from 'ts/components/footer';
+import { TopBar } from 'ts/components/top_bar/top_bar';
+import { FilledImage } from 'ts/components/ui/filled_image';
+import { Benefits } from 'ts/pages/jobs/benefits';
+import { Join0x } from 'ts/pages/jobs/join_0x';
+import { Mission } from 'ts/pages/jobs/mission';
+import { OpenPositions } from 'ts/pages/jobs/open_positions';
+import { PhotoRail } from 'ts/pages/jobs/photo_rail';
+import { Teams } from 'ts/pages/jobs/teams';
+import { Values } from 'ts/pages/jobs/values';
+import { Dispatcher } from 'ts/redux/dispatcher';
+import { ScreenWidths } from 'ts/types';
+import { Translate } from 'ts/utils/translate';
+import { utils } from 'ts/utils/utils';
+
+const OPEN_POSITIONS_HASH = 'positions';
+const THROTTLE_TIMEOUT = 100;
+const PHOTO_RAIL_IMAGES = ['/images/jobs/office1.png', '/images/jobs/office2.png', '/images/jobs/office3.png'];
+
+export interface JobsProps {
+ location: Location;
+ translate: Translate;
+ dispatcher: Dispatcher;
+ screenWidth: ScreenWidths;
+}
+
+export interface JobsState {}
+
+export class Jobs extends React.Component<JobsProps, JobsState> {
+ // TODO: consolidate this small screen scaffolding into one place (its being used in portal and docs as well)
+ private _throttledScreenWidthUpdate: () => void;
+ public constructor(props: JobsProps) {
+ super(props);
+ this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT);
+ }
+ public componentDidMount(): void {
+ window.addEventListener('resize', this._throttledScreenWidthUpdate);
+ window.scrollTo(0, 0);
+ }
+ public render(): React.ReactNode {
+ return (
+ <div>
+ <DocumentTitle title="Jobs" />
+ <TopBar
+ blockchainIsLoaded={false}
+ location={this.props.location}
+ style={{ backgroundColor: colors.white, position: 'relative' }}
+ translate={this.props.translate}
+ />
+ <Join0x onCallToActionClick={this._onJoin0xCallToActionClick.bind(this)} />
+ <Mission screenWidth={this.props.screenWidth} />
+ {this._isSmallScreen() ? (
+ <FilledImage src={_.head(PHOTO_RAIL_IMAGES)} />
+ ) : (
+ <PhotoRail images={PHOTO_RAIL_IMAGES} />
+ )}
+ <Values />
+ <Benefits screenWidth={this.props.screenWidth} />
+ <Teams screenWidth={this.props.screenWidth} />
+ <OpenPositions hash={OPEN_POSITIONS_HASH} screenWidth={this.props.screenWidth} />
+ <Footer translate={this.props.translate} dispatcher={this.props.dispatcher} />
+ </div>
+ );
+ }
+ private _onJoin0xCallToActionClick(): void {
+ sharedUtils.setUrlHash(OPEN_POSITIONS_HASH);
+ }
+ private _updateScreenWidth(): void {
+ const newScreenWidth = utils.getScreenWidth();
+ this.props.dispatcher.updateScreenWidth(newScreenWidth);
+ }
+ private _isSmallScreen(): boolean {
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ return isSmallScreen;
+ }
+}
diff --git a/packages/website/ts/pages/jobs/join_0x.tsx b/packages/website/ts/pages/jobs/join_0x.tsx
new file mode 100644
index 000000000..72cce3b89
--- /dev/null
+++ b/packages/website/ts/pages/jobs/join_0x.tsx
@@ -0,0 +1,41 @@
+import { colors } from '@0xproject/react-shared';
+
+import * as React from 'react';
+
+import { Button } from 'ts/components/ui/button';
+
+const BUTTON_TEXT = 'view open positions';
+
+export interface Join0xProps {
+ onCallToActionClick: () => void;
+}
+
+export const Join0x = (props: Join0xProps) => (
+ <div className="clearfix center lg-py4 md-py4" style={{ backgroundColor: colors.white, color: colors.black }}>
+ <div className="mx-auto inline-block align-middle py4" style={{ lineHeight: '44px', textAlign: 'center' }}>
+ <div className="h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
+ Join 0x
+ </div>
+ <div
+ className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 h4 sm-center"
+ style={{ fontFamily: 'Roboto', lineHeight: 2, maxWidth: 537 }}
+ >
+ 0x is transforming the way that value is exchanged on a global scale. Come join us in San Francisco or
+ work remotely anywhere in the world to help create the infrastructure of a new tokenized economy.
+ </div>
+ <div className="py3">
+ <Button
+ type="button"
+ backgroundColor={colors.black}
+ width="290px"
+ fontColor={colors.white}
+ fontSize="18px"
+ fontFamily="Roboto Mono"
+ onClick={props.onCallToActionClick}
+ >
+ {BUTTON_TEXT}
+ </Button>
+ </div>
+ </div>
+ </div>
+);
diff --git a/packages/website/ts/pages/jobs/list/header_item.tsx b/packages/website/ts/pages/jobs/list/header_item.tsx
new file mode 100644
index 000000000..ac214904c
--- /dev/null
+++ b/packages/website/ts/pages/jobs/list/header_item.tsx
@@ -0,0 +1,26 @@
+import * as React from 'react';
+
+import { Text } from 'ts/components/ui/text';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+
+export interface HeaderItemProps {
+ headerText?: string;
+}
+export const HeaderItem: React.StatelessComponent<HeaderItemProps> = ({ headerText }) => {
+ return (
+ <div className="h2 lg-py4 md-py4 sm-py3">
+ <ListItem>
+ <Text
+ fontFamily="Roboto Mono"
+ fontSize="24px"
+ lineHeight="1.25"
+ minHeight="1.25em"
+ fontColor={colors.black}
+ >
+ {headerText}
+ </Text>
+ </ListItem>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/list/list_item.tsx b/packages/website/ts/pages/jobs/list/list_item.tsx
new file mode 100644
index 000000000..d7838bc01
--- /dev/null
+++ b/packages/website/ts/pages/jobs/list/list_item.tsx
@@ -0,0 +1,15 @@
+import * as React from 'react';
+
+export interface ListItemProps {
+ bulletColor?: string;
+}
+export const ListItem: React.StatelessComponent<ListItemProps> = ({ bulletColor, children }) => {
+ return (
+ <div className="flex items-center">
+ <svg className="flex-none lg-px2 md-px2 sm-pl2" height="26" width="26">
+ <circle cx="13" cy="13" r="13" fill={bulletColor || 'transparent'} />
+ </svg>
+ <div className="flex-auto px2">{children}</div>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/mission.tsx b/packages/website/ts/pages/jobs/mission.tsx
new file mode 100644
index 000000000..f7f874e04
--- /dev/null
+++ b/packages/website/ts/pages/jobs/mission.tsx
@@ -0,0 +1,56 @@
+import * as React from 'react';
+
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+export interface MissionProps {
+ screenWidth: ScreenWidths;
+}
+export const Mission = (props: MissionProps) => {
+ const isSmallScreen = props.screenWidth === ScreenWidths.Sm;
+ const image = (
+ <div className="col lg-col-6 md-col-6 col-12 sm-py2 px2 center">
+ <img src="/images/jobs/map.png" style={{ width: '100%' }} />
+ </div>
+ );
+ const missionStatementStyle = !isSmallScreen ? { height: 364, lineHeight: '364px' } : undefined;
+ const missionStatement = (
+ <div className="col lg-col-6 md-col-6 col-12 center" style={missionStatementStyle}>
+ <div
+ className="mx-auto inline-block align-middle"
+ style={{ maxWidth: 385, lineHeight: '44px', textAlign: 'center' }}
+ >
+ <div className="h2 sm-center sm-pt3" style={{ fontFamily: 'Roboto Mono' }}>
+ Our Mission
+ </div>
+ <div
+ className="pb2 lg-pt2 md-pt2 sm-pt3 sm-px3 h4 sm-center"
+ style={{ fontFamily: 'Roboto', lineHeight: 2, maxWidth: 537 }}
+ >
+ We believe a system can exist in which all world value is accessible to anyone, anywhere, regardless
+ of where you happen to be born.
+ </div>
+ </div>
+ </div>
+ );
+ return (
+ <div
+ className="container lg-py4 md-py4"
+ style={{ backgroundColor: colors.jobsPageBackground, color: colors.black }}
+ >
+ <div className="mx-auto clearfix sm-py4">
+ {isSmallScreen ? (
+ <div>
+ {missionStatement}
+ {image}
+ </div>
+ ) : (
+ <div>
+ {image}
+ {missionStatement}
+ </div>
+ )}
+ </div>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/open_positions.tsx b/packages/website/ts/pages/jobs/open_positions.tsx
new file mode 100644
index 000000000..f3d980315
--- /dev/null
+++ b/packages/website/ts/pages/jobs/open_positions.tsx
@@ -0,0 +1,192 @@
+import * as _ from 'lodash';
+import CircularProgress from 'material-ui/CircularProgress';
+import { Table, TableBody, TableHeader, TableHeaderColumn, TableRow, TableRowColumn } from 'material-ui/Table';
+import * as React from 'react';
+
+import { Retry } from 'ts/components/ui/retry';
+import { Text } from 'ts/components/ui/text';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+import { styled } from 'ts/style/theme';
+import { ScreenWidths, WebsiteBackendJobInfo } from 'ts/types';
+import { backendClient } from 'ts/utils/backend_client';
+
+const labelStyle = { fontFamily: 'Roboto Mono', fontSize: 18 };
+const HEADER_TEXT = 'Open Positions';
+const TABLE_ROW_MIN_HEIGHT = 100;
+
+export interface OpenPositionsProps {
+ hash: string;
+ screenWidth: ScreenWidths;
+}
+export interface OpenPositionsState {
+ jobInfos?: WebsiteBackendJobInfo[];
+ error?: Error;
+}
+
+export class OpenPositions extends React.Component<OpenPositionsProps, OpenPositionsState> {
+ private _isUnmounted: boolean;
+ constructor(props: OpenPositionsProps) {
+ super(props);
+ this._isUnmounted = false;
+ this.state = {
+ jobInfos: undefined,
+ error: undefined,
+ };
+ }
+ public componentWillMount(): void {
+ // tslint:disable-next-line:no-floating-promises
+ this._fetchJobInfosAsync();
+ }
+ public componentWillUnmount(): void {
+ this._isUnmounted = true;
+ }
+ public render(): React.ReactNode {
+ const isReadyToRender = _.isUndefined(this.state.error) && !_.isUndefined(this.state.jobInfos);
+ return (
+ <div id={this.props.hash} className="mx-auto max-width-4">
+ {isReadyToRender ? this._renderBody() : this._renderLoading()}
+ </div>
+ );
+ }
+ private _renderBody(): React.ReactNode {
+ const isSmallScreen = this.props.screenWidth === ScreenWidths.Sm;
+ return isSmallScreen ? this._renderList() : this._renderTable();
+ }
+ private _renderLoading(): React.ReactNode {
+ return (
+ // TODO: consolidate this loading component with the one in portal and RelayerIndex
+ // TODO: possibly refactor into a generic loading container with spinner and retry UI
+ <div className="center">
+ {_.isUndefined(this.state.error) ? (
+ <CircularProgress size={40} thickness={5} />
+ ) : (
+ <Retry onRetry={this._fetchJobInfosAsync.bind(this)} />
+ )}
+ </div>
+ );
+ }
+ private _renderList(): React.ReactNode {
+ return (
+ <div style={{ backgroundColor: colors.jobsPageBackground }}>
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(this.state.jobInfos, jobInfo => (
+ <JobInfoListItem
+ key={jobInfo.id}
+ title={jobInfo.title}
+ description={jobInfo.department}
+ onClick={this._openJobInfoUrl.bind(this, jobInfo)}
+ />
+ ))}
+ </div>
+ );
+ }
+ private _renderTable(): React.ReactNode {
+ return (
+ <div>
+ <HeaderItem headerText={HEADER_TEXT} />
+ <Table selectable={false} onCellClick={this._onCellClick.bind(this)}>
+ <TableHeader displaySelectAll={false} adjustForCheckbox={false}>
+ <TableRow>
+ <TableHeaderColumn colSpan={5} style={labelStyle}>
+ Position
+ </TableHeaderColumn>
+ <TableHeaderColumn colSpan={3} style={labelStyle}>
+ Department
+ </TableHeaderColumn>
+ <TableHeaderColumn colSpan={4} style={labelStyle}>
+ Office
+ </TableHeaderColumn>
+ </TableRow>
+ </TableHeader>
+ <TableBody displayRowCheckbox={false} showRowHover={true}>
+ {_.map(this.state.jobInfos, jobInfo => {
+ return this._renderJobInfoTableRow(jobInfo);
+ })}
+ </TableBody>
+ </Table>
+ </div>
+ );
+ }
+ private _renderJobInfoTableRow(jobInfo: WebsiteBackendJobInfo): React.ReactNode {
+ return (
+ <TableRow
+ key={jobInfo.id}
+ hoverable={true}
+ displayBorder={false}
+ style={{ height: TABLE_ROW_MIN_HEIGHT, border: 2 }}
+ >
+ <TableRowColumn colSpan={5} style={labelStyle}>
+ {jobInfo.title}
+ </TableRowColumn>
+ <TableRowColumn colSpan={3} style={labelStyle}>
+ {jobInfo.department}
+ </TableRowColumn>
+ <TableRowColumn colSpan={4} style={labelStyle}>
+ {jobInfo.office}
+ </TableRowColumn>
+ </TableRow>
+ );
+ }
+ private async _fetchJobInfosAsync(): Promise<void> {
+ try {
+ if (!this._isUnmounted) {
+ this.setState({
+ jobInfos: undefined,
+ error: undefined,
+ });
+ }
+ const jobInfos = await backendClient.getJobInfosAsync();
+ if (!this._isUnmounted) {
+ this.setState({
+ jobInfos,
+ });
+ }
+ } catch (error) {
+ if (!this._isUnmounted) {
+ this.setState({
+ error,
+ });
+ }
+ }
+ }
+ private _onCellClick(rowNumber: number): void {
+ if (_.isUndefined(this.state.jobInfos)) {
+ return;
+ }
+ const jobInfo = this.state.jobInfos[rowNumber];
+ this._openJobInfoUrl(jobInfo);
+ }
+
+ private _openJobInfoUrl(jobInfo: WebsiteBackendJobInfo): void {
+ const url = jobInfo.url;
+ window.open(url, '_blank');
+ }
+}
+
+export interface JobInfoListItemProps {
+ title?: string;
+ description?: string;
+ onClick?: (event: React.MouseEvent<HTMLElement>) => void;
+}
+
+const PlainJobInfoListItem: React.StatelessComponent<JobInfoListItemProps> = ({ title, description, onClick }) => (
+ <div className="mb3" onClick={onClick}>
+ <ListItem>
+ <Text fontWeight="bold" fontSize="16px" fontColor={colors.mediumBlue}>
+ {title + ' ›'}
+ </Text>
+ <Text className="pt1" fontSize="16px" fontColor={colors.darkGrey}>
+ {description}
+ </Text>
+ </ListItem>
+ </div>
+);
+
+export const JobInfoListItem = styled(PlainJobInfoListItem)`
+ cursor: pointer;
+ &:hover {
+ opacity: 0.5;
+ }
+`;
diff --git a/packages/website/ts/pages/jobs/photo_rail.tsx b/packages/website/ts/pages/jobs/photo_rail.tsx
new file mode 100644
index 000000000..acc9dcb91
--- /dev/null
+++ b/packages/website/ts/pages/jobs/photo_rail.tsx
@@ -0,0 +1,22 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { FilledImage } from 'ts/components/ui/filled_image';
+
+export interface PhotoRailProps {
+ images: string[];
+}
+
+export const PhotoRail = (props: PhotoRailProps) => {
+ return (
+ <div className="clearfix" style={{ height: 490 }}>
+ {_.map(props.images, (image: string) => {
+ return (
+ <div key={image} className="col lg-col-4 md-col-4 col-12 center" style={{ height: '100%' }}>
+ <FilledImage src={image} />
+ </div>
+ );
+ })}
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/teams.tsx b/packages/website/ts/pages/jobs/teams.tsx
new file mode 100644
index 000000000..80b036396
--- /dev/null
+++ b/packages/website/ts/pages/jobs/teams.tsx
@@ -0,0 +1,90 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Text } from 'ts/components/ui/text';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+import { ScreenWidths } from 'ts/types';
+
+const TEAM_ITEM_PROPS_COLUMN1: TeamItemProps[] = [
+ {
+ bulletColor: '#EB5757',
+ title: 'User Growth',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#EB5757',
+ title: 'Governance',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+];
+const TEAM_ITEM_PROPS_COLUMN2: TeamItemProps[] = [
+ {
+ bulletColor: '#EB5757',
+ title: 'Developer Tools',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+ {
+ bulletColor: '#EB5757',
+ title: 'Marketing',
+ description:
+ 'Donec eget auctor mauris, a imperdiet ante. Ut a tellus ullamcorper, pharetra nibh sed, dignissim mauris. Quisque vel magna vitae nisi scelerisque commodo sed eget dolor. Maecenas vehicula orci',
+ },
+];
+const HEADER_TEXT = 'Our Teams';
+const MINIMUM_ITEM_HEIGHT = 240;
+
+export interface TeamsProps {
+ screenWidth: ScreenWidths;
+}
+
+export const Teams = (props: TeamsProps) => (props.screenWidth === ScreenWidths.Sm ? <SmallLayout /> : <LargeLayout />);
+
+const LargeLayout = () => (
+ <div className="mx-auto max-width-4 clearfix pb4">
+ <div className="col lg-col-6 md-col-6 col-12">
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(TEAM_ITEM_PROPS_COLUMN1, teamItemProps => <TeamItem {...teamItemProps} />)}
+ </div>
+ <div className="col lg-col-6 md-col-6 col-12">
+ <HeaderItem headerText=" " />
+ {_.map(TEAM_ITEM_PROPS_COLUMN2, teamItemProps => <TeamItem {...teamItemProps} />)}
+ </div>
+ </div>
+);
+
+const SmallLayout = () => (
+ <div>
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(_.concat(TEAM_ITEM_PROPS_COLUMN1, TEAM_ITEM_PROPS_COLUMN2), teamItemProps => (
+ <TeamItem {...teamItemProps} />
+ ))}
+ </div>
+);
+
+interface TeamItemProps {
+ bulletColor: string;
+ title: string;
+ description: string;
+}
+
+export const TeamItem: React.StatelessComponent<TeamItemProps> = ({ bulletColor, title, description }) => {
+ return (
+ <div style={{ minHeight: MINIMUM_ITEM_HEIGHT }}>
+ <ListItem bulletColor={bulletColor}>
+ <Text fontWeight="bold" fontSize="16px" fontColor={colors.black}>
+ {title}
+ </Text>
+ </ListItem>
+ <ListItem>
+ <Text className="pt1" fontSize="16px" lineHeight="2em" fontColor={colors.black}>
+ {description}
+ </Text>
+ </ListItem>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/jobs/values.tsx b/packages/website/ts/pages/jobs/values.tsx
new file mode 100644
index 000000000..c7c4d5726
--- /dev/null
+++ b/packages/website/ts/pages/jobs/values.tsx
@@ -0,0 +1,60 @@
+import * as _ from 'lodash';
+import * as React from 'react';
+
+import { Text } from 'ts/components/ui/text';
+import { HeaderItem } from 'ts/pages/jobs/list/header_item';
+import { ListItem } from 'ts/pages/jobs/list/list_item';
+import { colors } from 'ts/style/colors';
+
+const VALUE_ITEM_PROPS_LIST: ValueItemProps[] = [
+ {
+ bulletColor: '#6FCF97',
+ title: 'Ethics/Doing the right thing',
+ description: 'orem ipsum dolor sit amet, consectetur adipiscing elit.',
+ },
+ {
+ bulletColor: '#56CCF2',
+ title: 'Consistently ship',
+ description: 'orem ipsum dolor sit amet, consectetur adipiscing elit.',
+ },
+ {
+ bulletColor: '#EB5757',
+ title: 'Focus on long term impact',
+ description: 'orem ipsum dolor sit amet, consectetur adipiscing elit.',
+ },
+];
+
+const HEADER_TEXT = 'Our Values';
+const VALUE_ITEM_MIN_HEIGHT = 150;
+
+export const Values = () => {
+ return (
+ <div className="mx-auto max-width-4">
+ <HeaderItem headerText={HEADER_TEXT} />
+ {_.map(VALUE_ITEM_PROPS_LIST, valueItemProps => <ValueItem {...valueItemProps} />)}
+ </div>
+ );
+};
+
+interface ValueItemProps {
+ bulletColor: string;
+ title: string;
+ description: string;
+}
+
+export const ValueItem: React.StatelessComponent<ValueItemProps> = ({ bulletColor, title, description }) => {
+ return (
+ <div style={{ minHeight: VALUE_ITEM_MIN_HEIGHT }}>
+ <ListItem bulletColor={bulletColor}>
+ <Text fontWeight="bold" fontSize="16x" fontColor={colors.black}>
+ {title}
+ </Text>
+ </ListItem>
+ <ListItem>
+ <Text className="pt1" fontSize="16x" lineHeight="2em" fontColor={colors.black}>
+ {description}
+ </Text>
+ </ListItem>
+ </div>
+ );
+};
diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx
index 02ecfa117..f091778f4 100644
--- a/packages/website/ts/pages/landing/landing.tsx
+++ b/packages/website/ts/pages/landing/landing.tsx
@@ -1,11 +1,13 @@
import { colors } from '@0xproject/react-shared';
import * as _ from 'lodash';
-import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
import DocumentTitle = require('react-document-title');
import { Link } from 'react-router-dom';
import { Footer } from 'ts/components/footer';
+import { SubscribeForm } from 'ts/components/forms/subscribe_form';
import { TopBar } from 'ts/components/top_bar/top_bar';
+import { CallToAction } from 'ts/components/ui/button';
+import { Container } from 'ts/components/ui/container';
import { Dispatcher } from 'ts/redux/dispatcher';
import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
@@ -220,23 +222,12 @@ export class Landing extends React.Component<LandingProps, LandingState> {
}
private _renderHero(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- const buttonLabelStyle: React.CSSProperties = {
- textTransform: 'none',
- fontSize: isSmallScreen ? 12 : 14,
- fontWeight: 400,
- };
- const lightButtonStyle: React.CSSProperties = {
- borderRadius: 6,
- border: '1px solid #D8D8D8',
- lineHeight: '33px',
- height: 38,
- };
const left = 'col lg-col-7 md-col-7 col-12 lg-pl4 md-pl4 sm-pl0 sm-px3 sm-center';
return (
<div className="clearfix py4" style={{ backgroundColor: colors.heroGrey }}>
<div className="mx-auto max-width-4 clearfix">
{this._renderWhatsNew()}
- <div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-my4 md-my4 sm-mt2 sm-mb4 clearfix">
+ <div className="lg-pt4 md-pt4 sm-pt2 lg-pb4 md-pb4 lg-mt4 md-mt4 sm-mt2 sm-mb4 clearfix">
<div className="col lg-col-5 md-col-5 col-12 sm-center">
<img src="/images/landing/hero_chip_image.png" height={isSmallScreen ? 300 : 395} />
</div>
@@ -268,40 +259,31 @@ export class Landing extends React.Component<LandingProps, LandingState> {
>
{this.props.translate.get(Key.TopTagline)}
</div>
- <div className="pt3 clearfix sm-mx-auto" style={{ maxWidth: 389 }}>
- <div className="lg-pr2 md-pr2 col col-6 sm-center">
+ <Container className="pt3 clearfix sm-mx-auto" maxWidth="390px">
+ <div className="lg-pr2 md-pr2 lg-col lg-col-6 sm-center sm-col sm-col-12 mb2">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
- <RaisedButton
- style={{ borderRadius: 6, minWidth: 157.36 }}
- buttonStyle={{ borderRadius: 6 }}
- labelStyle={buttonLabelStyle}
- label={this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
- onClick={_.noop}
- />
+ <CallToAction width="175px" type="light">
+ {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
+ </CallToAction>
</Link>
</div>
- <div className="col col-6 sm-center">
+ <div className="lg-col lg-col-6 sm-center sm-col sm-col-12">
<a
href={constants.URL_ZEROEX_CHAT}
target="_blank"
className="text-decoration-none"
>
- <RaisedButton
- style={{ borderRadius: 6, minWidth: 150 }}
- buttonStyle={lightButtonStyle}
- labelColor="white"
- backgroundColor={colors.heroGrey}
- labelStyle={buttonLabelStyle}
- label={this.props.translate.get(Key.CommunityCallToAction, Deco.Cap)}
- onClick={_.noop}
- />
+ <CallToAction width="175px">
+ {this.props.translate.get(Key.CommunityCallToAction, Deco.Cap)}
+ </CallToAction>
</a>
</div>
- </div>
+ </Container>
</div>
</div>
</div>
</div>
+ {this.props.translate.getLanguage() === Language.English && <SubscribeForm />}
</div>
);
}
@@ -349,6 +331,9 @@ export class Landing extends React.Component<LandingProps, LandingState> {
case ScreenWidths.Lg:
colWidth = isRelayersOnly ? 2 : 2 - i % 2;
break;
+
+ default:
+ throw new Error(`Encountered unknown ScreenWidths value: ${this.state.screenWidth}`);
}
return (
<div key={`project-${project.logoFileName}`} className={`col col-${colWidth} center`}>
@@ -753,17 +738,6 @@ export class Landing extends React.Component<LandingProps, LandingState> {
}
private _renderCallToAction(): React.ReactNode {
const isSmallScreen = this.state.screenWidth === ScreenWidths.Sm;
- const buttonLabelStyle: React.CSSProperties = {
- textTransform: 'none',
- fontSize: 15,
- fontWeight: 400,
- };
- const lightButtonStyle: React.CSSProperties = {
- borderRadius: 6,
- border: `1px solid ${colors.grey500}`,
- lineHeight: '33px',
- height: 49,
- };
const callToActionClassNames =
'lg-pr3 md-pr3 lg-right-align md-right-align sm-center sm-px3 h4 lg-table-cell md-table-cell';
return (
@@ -782,15 +756,9 @@ export class Landing extends React.Component<LandingProps, LandingState> {
</div>
<div className="sm-center sm-pt2 lg-table-cell md-table-cell">
<Link to={WebsitePaths.ZeroExJs} className="text-decoration-none">
- <RaisedButton
- style={{ borderRadius: 6, minWidth: 150 }}
- buttonStyle={lightButtonStyle}
- labelColor={colors.white}
- backgroundColor={colors.heroGrey}
- labelStyle={buttonLabelStyle}
- label={this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
- onClick={_.noop}
- />
+ <CallToAction fontSize="15px">
+ {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
+ </CallToAction>
</Link>
</div>
</div>
@@ -806,7 +774,4 @@ export class Landing extends React.Component<LandingProps, LandingState> {
});
}
}
- private _onLanguageSelected(language: Language): void {
- this.props.dispatcher.updateSelectedLanguage(language);
- }
} // tslint:disable:max-file-line-count
diff --git a/packages/website/ts/pages/not_found.tsx b/packages/website/ts/pages/not_found.tsx
index 674271636..2fe3b1f45 100644
--- a/packages/website/ts/pages/not_found.tsx
+++ b/packages/website/ts/pages/not_found.tsx
@@ -1,5 +1,3 @@
-import { Styles } from '@0xproject/react-shared';
-import * as _ from 'lodash';
import * as React from 'react';
import { Footer } from 'ts/components/footer';
import { TopBar } from 'ts/components/top_bar/top_bar';
@@ -13,7 +11,7 @@ export interface NotFoundProps {
dispatcher: Dispatcher;
}
-export const NotFound = (props: NotFoundProps) => {
+export const NotFound = (_props: NotFoundProps) => {
return (
<div>
<TopBar blockchainIsLoaded={false} location={this.props.location} translate={this.props.translate} />
diff --git a/packages/website/ts/pages/wiki/wiki.tsx b/packages/website/ts/pages/wiki/wiki.tsx
index 720c1cc37..9659900be 100644
--- a/packages/website/ts/pages/wiki/wiki.tsx
+++ b/packages/website/ts/pages/wiki/wiki.tsx
@@ -4,23 +4,19 @@ import {
HeaderSizes,
MarkdownSection,
NestedSidebarMenu,
- SectionHeader,
Styles,
utils as sharedUtils,
} from '@0xproject/react-shared';
-import { logUtils } from '@0xproject/utils';
import * as _ from 'lodash';
import CircularProgress from 'material-ui/CircularProgress';
import RaisedButton from 'material-ui/RaisedButton';
import * as React from 'react';
import DocumentTitle = require('react-document-title');
-import { scroller } from 'react-scroll';
import { SidebarHeader } from 'ts/components/sidebar_header';
import { TopBar } from 'ts/components/top_bar/top_bar';
import { Dispatcher } from 'ts/redux/dispatcher';
-import { Article, ArticlesBySection, WebsitePaths } from 'ts/types';
+import { Article, ArticlesBySection } from 'ts/types';
import { backendClient } from 'ts/utils/backend_client';
-import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
import { utils } from 'ts/utils/utils';
@@ -237,7 +233,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
}
return menuSubsectionsBySection;
}
- private _onSidebarHover(event: React.FormEvent<HTMLInputElement>): void {
+ private _onSidebarHover(_event: React.FormEvent<HTMLInputElement>): void {
this.setState({
isHoveringSidebar: true,
});
@@ -247,7 +243,7 @@ export class Wiki extends React.Component<WikiProps, WikiState> {
isHoveringSidebar: false,
});
}
- private _onHashChanged(event: any): void {
+ private _onHashChanged(_event: any): void {
const hash = window.location.hash.slice(1);
sharedUtils.scrollToHash(hash, sharedConstants.SCROLL_CONTAINER_ID);
}
diff --git a/packages/website/ts/schemas/validator.ts b/packages/website/ts/schemas/validator.ts
index dac0f0098..3fd013002 100644
--- a/packages/website/ts/schemas/validator.ts
+++ b/packages/website/ts/schemas/validator.ts
@@ -1,5 +1,4 @@
import { SchemaValidator } from '@0xproject/json-schemas';
-import { Schema as JSONSchema, Validator } from 'jsonschema';
import { orderMetadataSchema } from 'ts/schemas/metadata_schema';
import { portalOrderSchema } from 'ts/schemas/portal_order_schema';
import { portalTokenMetadataSchema } from 'ts/schemas/portal_token_metadata';
diff --git a/packages/website/ts/utils/colors.ts b/packages/website/ts/style/colors.ts
index 5ffdd6ba7..b15000d7a 100644
--- a/packages/website/ts/utils/colors.ts
+++ b/packages/website/ts/style/colors.ts
@@ -11,6 +11,8 @@ const appColors = {
wrapEtherConfirmationButton: sharedColors.mediumBlue,
drawerMenuBackground: '#4a4a4a',
menuItemDefaultSelectedBackground: '#424242',
+ jobsPageBackground: sharedColors.grey50,
+ jobsPageOpenPositionRow: sharedColors.grey100,
};
export const colors = {
diff --git a/packages/website/ts/style/theme.ts b/packages/website/ts/style/theme.ts
new file mode 100644
index 000000000..ce7d6975d
--- /dev/null
+++ b/packages/website/ts/style/theme.ts
@@ -0,0 +1,17 @@
+import * as styledComponents from 'styled-components';
+
+// tslint:disable:no-unnecessary-type-assertion
+const {
+ default: styled,
+ css,
+ injectGlobal,
+ keyframes,
+ ThemeProvider,
+} = styledComponents as styledComponents.ThemedStyledComponentsModule<IThemeInterface>;
+// tslint:enable:no-unnecessary-type-assertion
+
+export interface IThemeInterface {}
+
+export const theme = {};
+
+export { styled, css, injectGlobal, keyframes, ThemeProvider };
diff --git a/packages/website/ts/utils/style.ts b/packages/website/ts/style/z_index.ts
index 0411cdd91..0411cdd91 100644
--- a/packages/website/ts/utils/style.ts
+++ b/packages/website/ts/style/z_index.ts
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index 9567e129b..24e86a901 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -1,6 +1,5 @@
import { ECSignature } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
-import * as _ from 'lodash';
import * as React from 'react';
export enum Side {
@@ -370,6 +369,7 @@ export enum WebsitePaths {
SolCov = '/docs/sol-cov',
Subproviders = '/docs/subproviders',
OrderUtils = '/docs/order-utils',
+ EthereumTypes = '/docs/ethereum-types',
Jobs = '/jobs',
}
@@ -383,6 +383,7 @@ export enum DocPackages {
SolCov = 'SOL_COV',
Subproviders = 'SUBPROVIDERS',
OrderUtils = 'ORDER_UTILS',
+ EthereumTypes = 'ETHEREUM_TYPES',
}
export enum Key {
@@ -434,6 +435,7 @@ export enum Key {
SolCompiler = 'SOL_COMPILER',
JsonSchemas = 'JSON_SCHEMAS',
SolCov = 'SOL_COV',
+ EthereumTypes = 'ETHEREUM_TYPES',
Subproviders = 'SUBPROVIDERS',
Blog = 'BLOG',
Forum = 'FORUM',
@@ -534,4 +536,12 @@ export interface WebsiteBackendTokenInfo {
export interface WebsiteBackendGasInfo {
average: number;
}
+
+export interface WebsiteBackendJobInfo {
+ id: number;
+ title: string;
+ department: string;
+ office: string;
+ url: string;
+}
// tslint:disable:max-file-line-count
diff --git a/packages/website/ts/utils/backend_client.ts b/packages/website/ts/utils/backend_client.ts
index c440b1604..835a6ef4d 100644
--- a/packages/website/ts/utils/backend_client.ts
+++ b/packages/website/ts/utils/backend_client.ts
@@ -1,19 +1,31 @@
import * as _ from 'lodash';
-import { ArticlesBySection, WebsiteBackendGasInfo, WebsiteBackendPriceInfo, WebsiteBackendRelayerInfo } from 'ts/types';
+import {
+ ArticlesBySection,
+ WebsiteBackendGasInfo,
+ WebsiteBackendJobInfo,
+ WebsiteBackendPriceInfo,
+ WebsiteBackendRelayerInfo,
+} from 'ts/types';
import { fetchUtils } from 'ts/utils/fetch_utils';
import { utils } from 'ts/utils/utils';
const ETH_GAS_STATION_ENDPOINT = '/eth_gas_station';
+const JOBS_ENDPOINT = '/jobs';
const PRICES_ENDPOINT = '/prices';
const RELAYERS_ENDPOINT = '/relayers';
const WIKI_ENDPOINT = '/wiki';
+const SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT = '/newsletter_subscriber/substack';
export const backendClient = {
async getGasInfoAsync(): Promise<WebsiteBackendGasInfo> {
const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), ETH_GAS_STATION_ENDPOINT);
return result;
},
+ async getJobInfosAsync(): Promise<WebsiteBackendJobInfo[]> {
+ const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), JOBS_ENDPOINT);
+ return result;
+ },
async getPriceInfoAsync(tokenSymbols: string[]): Promise<WebsiteBackendPriceInfo> {
if (_.isEmpty(tokenSymbols)) {
return {};
@@ -33,4 +45,11 @@ export const backendClient = {
const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), WIKI_ENDPOINT);
return result;
},
+ async subscribeToNewsletterAsync(email: string): Promise<Response> {
+ const result = await fetchUtils.postAsync(utils.getBackendBaseUrl(), SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT, {
+ email,
+ referrer: window.location.href,
+ });
+ return result;
+ },
};
diff --git a/packages/website/ts/utils/configs.ts b/packages/website/ts/utils/configs.ts
index e72a7f201..ace8a5ba0 100644
--- a/packages/website/ts/utils/configs.ts
+++ b/packages/website/ts/utils/configs.ts
@@ -1,6 +1,5 @@
import * as _ from 'lodash';
import { Environments, OutdatedWrappedEtherByNetworkId, PublicNodeUrlsByNetworkId } from 'ts/types';
-import { utils } from 'ts/utils/utils';
const BASE_URL = window.location.origin;
const isDevelopment = _.includes(
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index 9dc1d492c..d281c5738 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -1,4 +1,3 @@
-import { Networks } from '@0xproject/react-shared';
import { BigNumber } from '@0xproject/utils';
export const constants = {
diff --git a/packages/website/ts/utils/doc_utils.ts b/packages/website/ts/utils/doc_utils.ts
index 2a599bcbe..7768835fb 100644
--- a/packages/website/ts/utils/doc_utils.ts
+++ b/packages/website/ts/utils/doc_utils.ts
@@ -3,12 +3,11 @@ import { logUtils } from '@0xproject/utils';
import findVersions = require('find-versions');
import * as _ from 'lodash';
import { S3FileObject, VersionToFilePath } from 'ts/types';
-import { utils } from 'ts/utils/utils';
import convert = require('xml-js');
export const docUtils = {
async getVersionToFilePathAsync(s3DocJsonRoot: string, folderName: string): Promise<VersionToFilePath> {
- const versionFilePaths = await this.getVersionFileNamesAsync(s3DocJsonRoot, folderName);
+ const versionFilePaths = await docUtils.getVersionFileNamesAsync(s3DocJsonRoot, folderName);
const versionToFilePath: VersionToFilePath = {};
_.each(versionFilePaths, filePath => {
const [version] = findVersions(filePath);
diff --git a/packages/website/ts/utils/error_reporter.ts b/packages/website/ts/utils/error_reporter.ts
index 19f563880..f875141fe 100644
--- a/packages/website/ts/utils/error_reporter.ts
+++ b/packages/website/ts/utils/error_reporter.ts
@@ -2,7 +2,6 @@ import { logUtils } from '@0xproject/utils';
import { Environments } from 'ts/types';
import { configs } from 'ts/utils/configs';
import { constants } from 'ts/utils/constants';
-import { utils } from 'ts/utils/utils';
// Suggested way to include Rollbar with Webpack
// https://github.com/rollbar/rollbar.js/tree/master/examples/webpack
@@ -38,7 +37,7 @@ export const errorReporter = {
return; // Let's not log development errors to rollbar
}
- return new Promise((resolve, reject) => {
+ return new Promise((resolve, _reject) => {
rollbar.error(err, (rollbarErr: Error) => {
if (rollbarErr) {
logUtils.log(`Error reporting to rollbar, ignoring: ${rollbarErr}`);
diff --git a/packages/website/ts/utils/fetch_utils.ts b/packages/website/ts/utils/fetch_utils.ts
index d2e902db5..513f7e479 100644
--- a/packages/website/ts/utils/fetch_utils.ts
+++ b/packages/website/ts/utils/fetch_utils.ts
@@ -4,22 +4,38 @@ import * as queryString from 'query-string';
import { errorReporter } from 'ts/utils/error_reporter';
+const logErrorIfPresent = (response: Response, requestedURL: string) => {
+ if (response.status !== 200) {
+ const errorText = `Error requesting url: ${requestedURL}, ${response.status}: ${response.statusText}`;
+ logUtils.log(errorText);
+ const error = Error(errorText);
+ // tslint:disable-next-line:no-floating-promises
+ errorReporter.reportAsync(error);
+ throw error;
+ }
+};
+
export const fetchUtils = {
async requestAsync(baseUrl: string, path: string, queryParams?: object): Promise<any> {
const query = queryStringFromQueryParams(queryParams);
const url = `${baseUrl}${path}${query}`;
const response = await fetch(url);
- if (response.status !== 200) {
- const errorText = `Error requesting url: ${url}, ${response.status}: ${response.statusText}`;
- logUtils.log(errorText);
- const error = Error(errorText);
- // tslint:disable-next-line:no-floating-promises
- errorReporter.reportAsync(error);
- throw error;
- }
+ logErrorIfPresent(response, url);
const result = await response.json();
return result;
},
+ async postAsync(baseUrl: string, path: string, body: object): Promise<Response> {
+ const url = `${baseUrl}${path}`;
+ const response = await fetch(url, {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify(body),
+ });
+ logErrorIfPresent(response, url);
+ return response;
+ },
};
function queryStringFromQueryParams(queryParams?: object): string {
diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts
index b9d962b75..fdee264b2 100644
--- a/packages/website/ts/utils/utils.ts
+++ b/packages/website/ts/utils/utils.ts
@@ -1,6 +1,6 @@
import { ContractWrappersError, ExchangeContractErrs } from '@0xproject/contract-wrappers';
import { OrderError } from '@0xproject/order-utils';
-import { constants as sharedConstants, EtherscanLinkSuffixes, Networks } from '@0xproject/react-shared';
+import { constants as sharedConstants, Networks } from '@0xproject/react-shared';
import { ECSignature, Provider } from '@0xproject/types';
import { BigNumber } from '@0xproject/utils';
import deepEqual = require('deep-equal');
@@ -33,9 +33,6 @@ export const utils = {
throw new Error(message);
}
},
- spawnSwitchErr(name: string, value: any): Error {
- return new Error(`Unexpected switch value: ${value} encountered for ${name}`);
- },
isNumeric(n: string): boolean {
return !isNaN(parseFloat(n)) && isFinite(Number(n));
},
@@ -155,7 +152,7 @@ export const utils = {
const intervalId = setTimeout(() => {
resolve(false);
}, getApiVersionTimeoutMs);
- u2f.getApiVersion((version: number) => {
+ u2f.getApiVersion((_version: number) => {
clearTimeout(intervalId);
resolve(true);
});
@@ -282,7 +279,7 @@ export const utils = {
if (document.readyState === 'complete') {
return; // Already loaded
}
- return new Promise<void>((resolve, reject) => {
+ return new Promise<void>((resolve, _reject) => {
window.onload = () => resolve();
});
},
@@ -321,9 +318,18 @@ export const utils = {
shouldShowPortalV2(): boolean {
return this.isDevelopment() || this.isStaging() || this.isDogfood();
},
+ shouldShowJobsPage(): boolean {
+ return this.isDevelopment() || this.isStaging() || this.isDogfood();
+ },
getEthToken(tokenByAddress: TokenByAddress): Token {
+ return utils.getTokenBySymbol(constants.ETHER_TOKEN_SYMBOL, tokenByAddress);
+ },
+ getZrxToken(tokenByAddress: TokenByAddress): Token {
+ return utils.getTokenBySymbol(constants.ZRX_TOKEN_SYMBOL, tokenByAddress);
+ },
+ getTokenBySymbol(symbol: string, tokenByAddress: TokenByAddress): Token {
const tokens = _.values(tokenByAddress);
- const etherToken = _.find(tokens, { symbol: constants.ETHER_TOKEN_SYMBOL });
- return etherToken;
+ const token = _.find(tokens, { symbol });
+ return token;
},
};
diff --git a/packages/website/ts/utils/wallet_item_styles.ts b/packages/website/ts/utils/wallet_item_styles.ts
index 6b038efd2..9d6033d74 100644
--- a/packages/website/ts/utils/wallet_item_styles.ts
+++ b/packages/website/ts/utils/wallet_item_styles.ts
@@ -1,6 +1,6 @@
import { Styles } from '@0xproject/react-shared';
-import { colors } from 'ts/utils/colors';
+import { colors } from 'ts/style/colors';
export const styles: Styles = {
focusedItem: {