aboutsummaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
authorFabio Berger <me@fabioberger.com>2018-09-17 22:36:59 +0800
committerGitHub <noreply@github.com>2018-09-17 22:36:59 +0800
commitfe38adfa0869661ecd5f263222c92689cd1621a7 (patch)
treed95427265a1fe31ecb39180ed969fd372cec54c8 /packages
parentf4a4fefe422a5b2140d5bb394a7f06f842352c69 (diff)
parent92ee7c2194904235463fe525187a54c22fe1120a (diff)
downloaddexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.tar
dexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.tar.gz
dexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.tar.bz2
dexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.tar.lz
dexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.tar.xz
dexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.tar.zst
dexon-sol-tools-fe38adfa0869661ecd5f263222c92689cd1621a7.zip
Merge pull request #1027 from 0xProject/dev-dropdown
New Topbar Developers Dropdown
Diffstat (limited to 'packages')
-rw-r--r--packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol10
-rw-r--r--packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol1
-rw-r--r--packages/contracts/test/exchange/internal.ts4
-rw-r--r--packages/contracts/test/utils/test_with_reference.ts72
-rw-r--r--packages/contracts/test/utils_test/test_with_reference.ts63
-rw-r--r--packages/react-shared/src/utils/colors.ts2
-rw-r--r--packages/website/package.json2
-rw-r--r--packages/website/translations/chinese.json9
-rw-r--r--packages/website/translations/english.json9
-rw-r--r--packages/website/translations/korean.json9
-rw-r--r--packages/website/translations/russian.json9
-rw-r--r--packages/website/translations/spanish.json9
-rw-r--r--packages/website/ts/components/dropdowns/developers_drop_down.tsx188
-rw-r--r--packages/website/ts/components/top_bar/top_bar.tsx129
-rw-r--r--packages/website/ts/components/ui/drop_down.tsx3
-rw-r--r--packages/website/ts/types.ts7
-rw-r--r--packages/website/ts/utils/constants.ts1
-rw-r--r--packages/website/ts/utils/translate.ts7
18 files changed, 367 insertions, 167 deletions
diff --git a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol
index a7ff400b9..9e816716c 100644
--- a/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol
+++ b/packages/contracts/src/2.0.0/extensions/Forwarder/MixinExchangeWrapper.sol
@@ -69,20 +69,14 @@ contract MixinExchangeWrapper is
fillOrderCalldata, // write output over input
128 // output size is 128 bytes
)
- switch success
- case 0 {
- mstore(fillResults, 0)
- mstore(add(fillResults, 32), 0)
- mstore(add(fillResults, 64), 0)
- mstore(add(fillResults, 96), 0)
- }
- case 1 {
+ if success {
mstore(fillResults, mload(fillOrderCalldata))
mstore(add(fillResults, 32), mload(add(fillOrderCalldata, 32)))
mstore(add(fillResults, 64), mload(add(fillOrderCalldata, 64)))
mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))
}
}
+ // fillResults values will be 0 by default if call was unsuccessful
return fillResults;
}
diff --git a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol
index 39fa724cc..a5459a21e 100644
--- a/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol
+++ b/packages/contracts/src/2.0.0/protocol/Exchange/MixinWrapperFunctions.sol
@@ -96,6 +96,7 @@ contract MixinWrapperFunctions is
mstore(add(fillResults, 96), mload(add(fillOrderCalldata, 96)))
}
}
+ // fillResults values will be 0 by default if call was unsuccessful
return fillResults;
}
diff --git a/packages/contracts/test/exchange/internal.ts b/packages/contracts/test/exchange/internal.ts
index 2521665c2..de381fca3 100644
--- a/packages/contracts/test/exchange/internal.ts
+++ b/packages/contracts/test/exchange/internal.ts
@@ -67,9 +67,7 @@ describe('Exchange core internal functions', () => {
overflowErrorForSendTransaction = new Error(
await getRevertReasonOrErrorMessageForSendTransactionAsync(RevertReason.Uint256Overflow),
);
- divisionByZeroErrorForCall = new Error(
- await getRevertReasonOrErrorMessageForSendTransactionAsync(RevertReason.DivisionByZero),
- );
+ divisionByZeroErrorForCall = new Error(RevertReason.DivisionByZero);
invalidOpcodeErrorForCall = new Error(await getInvalidOpcodeErrorMessageForCallAsync());
});
// Note(albrow): Don't forget to add beforeEach and afterEach calls to reset
diff --git a/packages/contracts/test/utils/test_with_reference.ts b/packages/contracts/test/utils/test_with_reference.ts
index 599b1eed4..b80be4a6c 100644
--- a/packages/contracts/test/utils/test_with_reference.ts
+++ b/packages/contracts/test/utils/test_with_reference.ts
@@ -6,6 +6,34 @@ import { chaiSetup } from './chai_setup';
chaiSetup.configure();
const expect = chai.expect;
+class Value<T> {
+ public value: T;
+ constructor(value: T) {
+ this.value = value;
+ }
+}
+
+// tslint:disable-next-line: max-classes-per-file
+class ErrorMessage {
+ public error: string;
+ constructor(message: string) {
+ this.error = message;
+ }
+}
+
+type PromiseResult<T> = Value<T> | ErrorMessage;
+
+// TODO(albrow): This seems like a generic utility function that could exist in
+// lodash. We should replace it by a library implementation, or move it to our
+// own.
+async function evaluatePromise<T>(promise: Promise<T>): Promise<PromiseResult<T>> {
+ try {
+ return new Value<T>(await promise);
+ } catch (e) {
+ return new ErrorMessage(e.message);
+ }
+}
+
export async function testWithReferenceFuncAsync<P0, R>(
referenceFunc: (p0: P0) => Promise<R>,
testFunc: (p0: P0) => Promise<R>,
@@ -64,39 +92,31 @@ export async function testWithReferenceFuncAsync(
testFuncAsync: (...args: any[]) => Promise<any>,
values: any[],
): Promise<void> {
- let expectedResult: any;
- let expectedErr: string | undefined;
- try {
- expectedResult = await referenceFuncAsync(...values);
- } catch (e) {
- expectedErr = e.message;
- }
- let actualResult: any | undefined;
- try {
- actualResult = await testFuncAsync(...values);
- if (!_.isUndefined(expectedErr)) {
+ // Measure correct behaviour
+ const expected = await evaluatePromise(referenceFuncAsync(...values));
+
+ // Measure actual behaviour
+ const actual = await evaluatePromise(testFuncAsync(...values));
+
+ // Compare behaviour
+ if (expected instanceof ErrorMessage) {
+ // If we expected an error, check if the actual error message contains the
+ // expected error message.
+ if (!(actual instanceof ErrorMessage)) {
throw new Error(
- `Expected error containing ${expectedErr} but got no error\n\tTest case: ${_getTestCaseString(
+ `Expected error containing ${expected.error} but got no error\n\tTest case: ${_getTestCaseString(
referenceFuncAsync,
values,
)}`,
);
}
- } catch (e) {
- if (_.isUndefined(expectedErr)) {
- throw new Error(`${e.message}\n\tTest case: ${_getTestCaseString(referenceFuncAsync, values)}`);
- } else {
- expect(e.message).to.contain(
- expectedErr,
- `${e.message}\n\tTest case: ${_getTestCaseString(referenceFuncAsync, values)}`,
- );
- }
- }
- if (!_.isUndefined(actualResult) && !_.isUndefined(expectedResult)) {
- expect(actualResult).to.deep.equal(
- expectedResult,
- `Test case: ${_getTestCaseString(referenceFuncAsync, values)}`,
+ expect(actual.error).to.contain(
+ expected.error,
+ `${actual.error}\n\tTest case: ${_getTestCaseString(referenceFuncAsync, values)}`,
);
+ } else {
+ // If we do not expect an error, compare actual and expected directly.
+ expect(actual).to.deep.equal(expected, `Test case ${_getTestCaseString(referenceFuncAsync, values)}`);
}
}
diff --git a/packages/contracts/test/utils_test/test_with_reference.ts b/packages/contracts/test/utils_test/test_with_reference.ts
new file mode 100644
index 000000000..8d633cd1f
--- /dev/null
+++ b/packages/contracts/test/utils_test/test_with_reference.ts
@@ -0,0 +1,63 @@
+import * as chai from 'chai';
+
+import { chaiSetup } from '../utils/chai_setup';
+import { testWithReferenceFuncAsync } from '../utils/test_with_reference';
+
+chaiSetup.configure();
+const expect = chai.expect;
+
+async function divAsync(x: number, y: number): Promise<number> {
+ if (y === 0) {
+ throw new Error('MathError: divide by zero');
+ }
+ return x / y;
+}
+
+// returns an async function that always returns the given value.
+function alwaysValueFunc(value: number): (x: number, y: number) => Promise<number> {
+ return async (x: number, y: number) => value;
+}
+
+// returns an async function which always throws/rejects with the given error
+// message.
+function alwaysFailFunc(errMessage: string): (x: number, y: number) => Promise<number> {
+ return async (x: number, y: number) => {
+ throw new Error(errMessage);
+ };
+}
+
+describe('testWithReferenceFuncAsync', () => {
+ it('passes when both succeed and actual === expected', async () => {
+ await testWithReferenceFuncAsync(alwaysValueFunc(0.5), divAsync, [1, 2]);
+ });
+
+ it('passes when both fail and actual error contains expected error', async () => {
+ await testWithReferenceFuncAsync(alwaysFailFunc('divide by zero'), divAsync, [1, 0]);
+ });
+
+ it('fails when both succeed and actual !== expected', async () => {
+ expect(testWithReferenceFuncAsync(alwaysValueFunc(3), divAsync, [1, 2])).to.be.rejectedWith(
+ 'Test case {"x":1,"y":2}: expected { value: 0.5 } to deeply equal { value: 3 }',
+ );
+ });
+
+ it('fails when both fail and actual error does not contain expected error', async () => {
+ expect(
+ testWithReferenceFuncAsync(alwaysFailFunc('Unexpected math error'), divAsync, [1, 0]),
+ ).to.be.rejectedWith(
+ 'MathError: divide by zero\n\tTest case: {"x":1,"y":0}: expected \'MathError: divide by zero\' to include \'Unexpected math error\'',
+ );
+ });
+
+ it('fails when referenceFunc succeeds and testFunc fails', async () => {
+ expect(testWithReferenceFuncAsync(alwaysValueFunc(0), divAsync, [1, 0])).to.be.rejectedWith(
+ 'Test case {"x":1,"y":0}: expected { error: \'MathError: divide by zero\' } to deeply equal { value: 0 }',
+ );
+ });
+
+ it('fails when referenceFunc fails and testFunc succeeds', async () => {
+ expect(testWithReferenceFuncAsync(alwaysFailFunc('divide by zero'), divAsync, [1, 2])).to.be.rejectedWith(
+ 'Expected error containing divide by zero but got no error\n\tTest case: {"x":1,"y":2}',
+ );
+ });
+});
diff --git a/packages/react-shared/src/utils/colors.ts b/packages/react-shared/src/utils/colors.ts
index 7d047a50e..5a20eeaa1 100644
--- a/packages/react-shared/src/utils/colors.ts
+++ b/packages/react-shared/src/utils/colors.ts
@@ -8,6 +8,7 @@ const baseColors = {
greyishPink: '#E6E5E5',
grey300: '#E0E0E0',
beigeWhite: '#E4E4E4',
+ lightBgGrey: '#EDEDED',
grey350: '#cacaca',
grey400: '#BDBDBD',
lightGrey: '#BBBBBB',
@@ -15,6 +16,7 @@ const baseColors = {
grey: '#A5A5A5',
darkGrey: '#818181',
landingLinkGrey: '#919191',
+ linkSectionGrey: '#999999',
grey700: '#616161',
grey750: '#515151',
grey800: '#424242',
diff --git a/packages/website/package.json b/packages/website/package.json
index 9b6a0ba36..0a223bcb2 100644
--- a/packages/website/package.json
+++ b/packages/website/package.json
@@ -21,7 +21,7 @@
"@0xproject/contract-wrappers": "^0.0.5",
"@0xproject/order-utils": "^0.0.9",
"@0xproject/react-docs": "^1.0.7",
- "@0xproject/react-shared": "^0.2.3",
+ "@0xproject/react-shared": "^1.0.8",
"@0xproject/subproviders": "^2.0.1",
"@0xproject/types": "^0.8.1",
"@0xproject/typescript-typings": "^0.4.3",
diff --git a/packages/website/translations/chinese.json b/packages/website/translations/chinese.json
index ed1a6044a..93e740a14 100644
--- a/packages/website/translations/chinese.json
+++ b/packages/website/translations/chinese.json
@@ -78,5 +78,12 @@
"WEBSITE": "网站",
"DEVELOPERS": "首页",
"HOME": "Rocket.chat",
- "ROCKETCHAT": "开发人员"
+ "ROCKETCHAT": "开发人员",
+ "BUILD_A_RELAYER": "build a relayer",
+ "ETHEREUM_DEVELOPMENT": "ethereum development",
+ "INTRO_TUTORIAL": "intro tutorial",
+ "TRADING_TUTORIAL": "trading tutorial",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github"
}
diff --git a/packages/website/translations/english.json b/packages/website/translations/english.json
index 541c29997..a75b73501 100644
--- a/packages/website/translations/english.json
+++ b/packages/website/translations/english.json
@@ -80,5 +80,12 @@
"DEVELOPERS": "developers",
"HOME": "home",
"ROCKETCHAT": "rocket.chat",
- "TRADE_CALL_TO_ACTION": "trade on 0x"
+ "TRADE_CALL_TO_ACTION": "trade on 0x",
+ "BUILD_A_RELAYER": "build a relayer",
+ "ETHEREUM_DEVELOPMENT": "ethereum development",
+ "INTRO_TUTORIAL": "intro tutorial",
+ "TRADING_TUTORIAL": "trading tutorial",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github"
}
diff --git a/packages/website/translations/korean.json b/packages/website/translations/korean.json
index 8892f2dee..e6fbcb4cc 100644
--- a/packages/website/translations/korean.json
+++ b/packages/website/translations/korean.json
@@ -78,5 +78,12 @@
"WEBSITE": "Website",
"HOME": "홈",
"ROCKETCHAT": "Rocket.chat",
- "DEVELOPERS": "개발자"
+ "DEVELOPERS": "개발자",
+ "BUILD_A_RELAYER": "build a relayer",
+ "ETHEREUM_DEVELOPMENT": "ethereum development",
+ "INTRO_TUTORIAL": "intro tutorial",
+ "TRADING_TUTORIAL": "trading tutorial",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github"
}
diff --git a/packages/website/translations/russian.json b/packages/website/translations/russian.json
index 41a7a990d..779bc8173 100644
--- a/packages/website/translations/russian.json
+++ b/packages/website/translations/russian.json
@@ -78,5 +78,12 @@
"WEBSITE": "Веб-сайт",
"DEVELOPERS": "Домашняя страница",
"HOME": "Rocket.chat",
- "ROCKETCHAT": "Для разработчиков"
+ "ROCKETCHAT": "Для разработчиков",
+ "BUILD_A_RELAYER": "build a relayer",
+ "ETHEREUM_DEVELOPMENT": "ethereum development",
+ "INTRO_TUTORIAL": "intro tutorial",
+ "TRADING_TUTORIAL": "trading tutorial",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github"
}
diff --git a/packages/website/translations/spanish.json b/packages/website/translations/spanish.json
index 7780190ac..54a463f98 100644
--- a/packages/website/translations/spanish.json
+++ b/packages/website/translations/spanish.json
@@ -79,5 +79,12 @@
"WEBSITE": "website",
"DEVELOPERS": "inicio",
"HOME": "rocket.chat",
- "ROCKETCHAT": "desarrolladores"
+ "ROCKETCHAT": "desarrolladores",
+ "BUILD_A_RELAYER": "build a relayer",
+ "ETHEREUM_DEVELOPMENT": "ethereum development",
+ "INTRO_TUTORIAL": "intro tutorial",
+ "TRADING_TUTORIAL": "trading tutorial",
+ "VIEW_ALL_DOCUMENTATION": "view all documentation",
+ "SANDBOX": "0x.js sandbox",
+ "GITHUB": "github"
}
diff --git a/packages/website/ts/components/dropdowns/developers_drop_down.tsx b/packages/website/ts/components/dropdowns/developers_drop_down.tsx
new file mode 100644
index 000000000..d66e75722
--- /dev/null
+++ b/packages/website/ts/components/dropdowns/developers_drop_down.tsx
@@ -0,0 +1,188 @@
+import { colors } from '@0xproject/react-shared';
+import * as _ from 'lodash';
+import * as React from 'react';
+import { Link } from 'react-router-dom';
+import { Container } from 'ts/components/ui/container';
+import { DropDown } from 'ts/components/ui/drop_down';
+import { Text } from 'ts/components/ui/text';
+import { Deco, Key, ObjectMap, WebsitePaths } from 'ts/types';
+import { constants } from 'ts/utils/constants';
+import { Translate } from 'ts/utils/translate';
+
+interface LinkInfo {
+ link: string;
+ shouldOpenNewTab: boolean;
+}
+
+const gettingStartedKeyToLinkInfo1: ObjectMap<LinkInfo> = {
+ [Key.BuildARelayer]: {
+ link: `${WebsitePaths.Wiki}#Build-A-Relayer`,
+ shouldOpenNewTab: false,
+ },
+ [Key.IntroTutorial]: {
+ link: `${WebsitePaths.Wiki}#Create,-Validate,-Fill-Order`,
+ shouldOpenNewTab: false,
+ },
+};
+const gettingStartedKeyToLinkInfo2: ObjectMap<LinkInfo> = {
+ [Key.TradingTutorial]: {
+ link: `${WebsitePaths.Wiki}#Find,-Submit,-Fill-Order-From-Relayer`,
+ shouldOpenNewTab: false,
+ },
+ [Key.EthereumDevelopment]: {
+ link: `${WebsitePaths.Wiki}#Ethereum-Development`,
+ shouldOpenNewTab: false,
+ },
+};
+const popularDocsToLinkInfos: ObjectMap<LinkInfo> = {
+ [Key.ZeroExJs]: {
+ link: WebsitePaths.ZeroExJs,
+ shouldOpenNewTab: false,
+ },
+ [Key.Connect]: {
+ link: WebsitePaths.Connect,
+ shouldOpenNewTab: false,
+ },
+ [Key.SmartContract]: {
+ link: WebsitePaths.SmartContracts,
+ shouldOpenNewTab: false,
+ },
+};
+const usefulLinksToLinkInfo: ObjectMap<LinkInfo> = {
+ [Key.Github]: {
+ link: constants.URL_GITHUB_ORG,
+ shouldOpenNewTab: true,
+ },
+ [Key.Whitepaper]: {
+ link: WebsitePaths.Whitepaper,
+ shouldOpenNewTab: true,
+ },
+ [Key.Sandbox]: {
+ link: constants.URL_SANDBOX,
+ shouldOpenNewTab: true,
+ },
+};
+
+interface DevelopersDropDownProps {
+ translate: Translate;
+ menuItemStyles: React.CSSProperties;
+ menuIconStyle: React.CSSProperties;
+}
+
+interface DevelopersDropDownState {}
+
+export class DevelopersDropDown extends React.Component<DevelopersDropDownProps, DevelopersDropDownState> {
+ public render(): React.ReactNode {
+ const activeNode = (
+ <Container className="flex relative" paddingRight="10">
+ <Text fontColor={this.props.menuIconStyle.color}>
+ {this.props.translate.get(Key.Developers, Deco.Cap)}
+ </Text>
+ </Container>
+ );
+ return (
+ <DropDown
+ activeNode={activeNode}
+ popoverContent={this._renderDropdownMenu()}
+ anchorOrigin={{ horizontal: 'left', vertical: 'bottom' }}
+ targetOrigin={{ horizontal: 'left', vertical: 'top' }}
+ style={this.props.menuItemStyles}
+ popoverStyle={{ borderRadius: 4, width: 427, height: 373, marginTop: 10 }}
+ />
+ );
+ }
+ private _renderDropdownMenu(): React.ReactNode {
+ const dropdownMenu = (
+ <div>
+ <Container padding="1.75rem">
+ {this._renderTitle('Getting started')}
+ <div className="flex">
+ <div className="pr4 mr2">{this._renderLinkSection(gettingStartedKeyToLinkInfo1)}</div>
+ <div>{this._renderLinkSection(gettingStartedKeyToLinkInfo2)}</div>
+ </div>
+ </Container>
+ <div
+ style={{
+ width: '100%',
+ height: 1,
+ backgroundColor: colors.grey300,
+ }}
+ />
+ <div className="flex" style={{ padding: '1.75rem' }}>
+ <div className="pr4 mr2">
+ <div>{this._renderTitle('Popular docs')}</div>
+ <div>{this._renderLinkSection(popularDocsToLinkInfos)}</div>
+ </div>
+ <div>
+ <div>{this._renderTitle('Useful links')}</div>
+ <div>{this._renderLinkSection(usefulLinksToLinkInfo)}</div>
+ </div>
+ </div>
+ <div
+ style={{
+ padding: '0.8rem',
+ textAlign: 'center',
+ backgroundColor: colors.lightBgGrey,
+ borderBottomLeftRadius: 4,
+ borderBottomRightRadius: 4,
+ }}
+ >
+ <Link
+ to={WebsitePaths.ZeroExJs}
+ className="text-decoration-none"
+ style={{
+ color: colors.lightBlueA700,
+ fontWeight: 'bold',
+ fontSize: 14,
+ }}
+ >
+ {this.props.translate.get(Key.ViewAllDocumentation, Deco.Upper)}
+ </Link>
+ </div>
+ </div>
+ );
+ return dropdownMenu;
+ }
+ private _renderTitle(title: string): React.ReactNode {
+ return (
+ <div
+ style={{
+ color: colors.linkSectionGrey,
+ fontSize: 14,
+ paddingBottom: 12,
+ fontWeight: 600,
+ letterSpacing: 1,
+ }}
+ >
+ {title.toUpperCase()}
+ </div>
+ );
+ }
+ private _renderLinkSection(keyToLinkInfo: ObjectMap<LinkInfo>): React.ReactNode {
+ const linkStyle: React.CSSProperties = {
+ color: colors.lightBlueA700,
+ fontFamily: 'Roboto, Roboto Mono',
+ };
+ const numLinks = _.size(keyToLinkInfo);
+ let i = 0;
+ const links = _.map(keyToLinkInfo, (linkInfo: LinkInfo, key: string) => {
+ i++;
+ const isLast = i === numLinks;
+ const linkText = this.props.translate.get(key as Key, Deco.CapWords);
+ return (
+ <div className={`pr1 pt1 ${!isLast && 'pb1'}`} key={`dev-dropdown-link-${key}`}>
+ {linkInfo.shouldOpenNewTab ? (
+ <a target="_blank" className="text-decoration-none" style={linkStyle} href={linkInfo.link}>
+ {linkText}
+ </a>
+ ) : (
+ <Link to={linkInfo.link} className="text-decoration-none" style={linkStyle}>
+ {linkText}
+ </Link>
+ )}
+ </div>
+ );
+ });
+ return <div>{links}</div>;
+ }
+}
diff --git a/packages/website/ts/components/top_bar/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx
index 9ef8211a9..8f1137b44 100644
--- a/packages/website/ts/components/top_bar/top_bar.tsx
+++ b/packages/website/ts/components/top_bar/top_bar.tsx
@@ -8,18 +8,17 @@ import {
} from '@0xproject/react-shared';
import * as _ from 'lodash';
import Drawer from 'material-ui/Drawer';
-import Menu from 'material-ui/Menu';
import MenuItem from 'material-ui/MenuItem';
import * as React from 'react';
import { Link } from 'react-router-dom';
import { Blockchain } from 'ts/blockchain';
+import { DevelopersDropDown } from 'ts/components/dropdowns/developers_drop_down';
import { DrawerMenu } from 'ts/components/portal/drawer_menu';
import { ProviderDisplay } from 'ts/components/top_bar/provider_display';
import { TopBarMenuItem } from 'ts/components/top_bar/top_bar_menu_item';
import { Container } from 'ts/components/ui/container';
-import { DropDown } from 'ts/components/ui/drop_down';
import { Dispatcher } from 'ts/redux/dispatcher';
-import { Deco, Key, ProviderType, WebsiteLegacyPaths, WebsitePaths } from 'ts/types';
+import { Deco, Key, ProviderType, WebsitePaths } from 'ts/types';
import { constants } from 'ts/utils/constants';
import { Translate } from 'ts/utils/translate';
@@ -129,111 +128,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
? 'flex mx-auto items-center max-width-4'
: 'flex mx-auto items-center';
const height = isExpandedDisplayType ? EXPANDED_HEIGHT : DEFAULT_HEIGHT;
- const developerSectionMenuItems = [
- <Link key="subMenuItem-zeroEx" to={WebsitePaths.ZeroExJs} className="text-decoration-none">
- <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="0x.js" />
- </Link>,
- <Link key="subMenuItem-smartContracts" to={WebsitePaths.SmartContracts} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.SmartContract, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-0xconnect" to={WebsitePaths.Connect} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Connect, Deco.CapWords)}
- />
- </Link>,
- <a
- key="subMenuItem-standard-relayer-api"
- target="_blank"
- className="text-decoration-none"
- href={constants.URL_STANDARD_RELAYER_API_GITHUB}
- >
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.StandardRelayerApi, Deco.CapWords)}
- />
- </a>,
- <Link key="subMenuItem-jsonSchema" to={WebsitePaths.JSONSchemas} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.JsonSchemas, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-subproviders" to={WebsitePaths.Subproviders} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Subproviders, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-web3Wrapper" to={WebsitePaths.Web3Wrapper} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Web3Wrapper, Deco.CapWords)}
- />
- </Link>,
- <Link
- key="subMenuItem-contractWrappers"
- to={WebsitePaths.ContractWrappers}
- className="text-decoration-none"
- >
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.ContractWrappers, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-orderUtils" to={WebsitePaths.OrderUtils} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.OrderUtils, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-orderWatcher" to={WebsitePaths.OrderWatcher} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.OrderWatcher, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-sol-compiler" to={WebsitePaths.SolCompiler} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.SolCompiler, Deco.CapWords)}
- />
- </Link>,
- <Link key="subMenuItem-sol-cov" to={WebsitePaths.SolCov} className="text-decoration-none">
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- 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"
- className="text-decoration-none"
- href={`${WebsitePaths.Whitepaper}`}
- >
- <MenuItem
- style={{ fontSize: styles.menuItem.fontSize }}
- primaryText={this.props.translate.get(Key.Whitepaper, Deco.CapWords)}
- />
- </a>,
- <a
- key="subMenuItem-github"
- target="_blank"
- className="text-decoration-none"
- href={constants.URL_GITHUB_ORG}
- >
- <MenuItem style={{ fontSize: styles.menuItem.fontSize }} primaryText="GitHub" />
- </a>,
- ];
const bottomBorderStyle = this._shouldDisplayBottomBar() ? styles.bottomBar : {};
const fullWidthClasses = isExpandedDisplayType ? 'pr4' : '';
const logoUrl = isNightVersion ? '/images/protocol_logo_white.png' : '/images/protocol_logo_black.png';
@@ -245,15 +139,6 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
color: isNightVersion ? 'white' : 'black',
cursor: 'pointer',
};
- const activeNode = (
- <div className="flex relative" style={{ color: menuIconStyle.color }}>
- <div style={{ paddingRight: 10 }}>{this.props.translate.get(Key.Developers, Deco.Cap)}</div>
- <div className="absolute" style={{ paddingLeft: 3, right: 3, top: -2 }}>
- <i className="zmdi zmdi-caret-right" style={{ fontSize: 22 }} />
- </div>
- </div>
- );
- const popoverContent = <Menu style={{ color: colors.darkGrey }}>{developerSectionMenuItems}</Menu>;
return (
<div
style={{ ...styles.topBar, ...bottomBorderStyle, ...this.props.style, ...{ height } }}
@@ -273,12 +158,10 @@ export class TopBar extends React.Component<TopBarProps, TopBarState> {
{!this._isViewingPortal() && (
<div className={menuClasses}>
<div className="flex items-center justify-between">
- <DropDown
- activeNode={activeNode}
- popoverContent={popoverContent}
- anchorOrigin={{ horizontal: 'middle', vertical: 'bottom' }}
- targetOrigin={{ horizontal: 'middle', vertical: 'top' }}
- style={styles.menuItem}
+ <DevelopersDropDown
+ menuItemStyles={styles.menuItem}
+ translate={this.props.translate}
+ menuIconStyle={menuIconStyle}
/>
<TopBarMenuItem
title={this.props.translate.get(Key.Wiki, Deco.Cap)}
diff --git a/packages/website/ts/components/ui/drop_down.tsx b/packages/website/ts/components/ui/drop_down.tsx
index 4d5caef08..1daaeb1c3 100644
--- a/packages/website/ts/components/ui/drop_down.tsx
+++ b/packages/website/ts/components/ui/drop_down.tsx
@@ -21,6 +21,7 @@ export interface DropDownProps {
zDepth?: number;
activateEvent?: DropdownMouseEvent;
closeEvent?: DropdownMouseEvent;
+ popoverStyle?: React.CSSProperties;
}
interface DropDownState {
@@ -34,6 +35,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
zDepth: 1,
activateEvent: DropdownMouseEvent.Hover,
closeEvent: DropdownMouseEvent.Hover,
+ popoverStyle: {},
};
private _isHovering: boolean;
private _popoverCloseCheckIntervalId: number;
@@ -77,6 +79,7 @@ export class DropDown extends React.Component<DropDownProps, DropDownState> {
useLayerForClickAway={this.props.closeEvent === DropdownMouseEvent.Click}
animated={false}
zDepth={this.props.zDepth}
+ style={this.props.popoverStyle}
>
<div
onMouseEnter={this._onHover.bind(this)}
diff --git a/packages/website/ts/types.ts b/packages/website/ts/types.ts
index c637171dd..2c94fe910 100644
--- a/packages/website/ts/types.ts
+++ b/packages/website/ts/types.ts
@@ -468,6 +468,13 @@ export enum Key {
Home = 'HOME',
RocketChat = 'ROCKETCHAT',
TradeCallToAction = 'TRADE_CALL_TO_ACTION',
+ BuildARelayer = 'BUILD_A_RELAYER',
+ EthereumDevelopment = 'ETHEREUM_DEVELOPMENT',
+ IntroTutorial = 'INTRO_TUTORIAL',
+ TradingTutorial = 'TRADING_TUTORIAL',
+ ViewAllDocumentation = 'VIEW_ALL_DOCUMENTATION',
+ Sandbox = 'SANDBOX',
+ Github = 'GITHUB',
}
export enum SmartContractDocSections {
diff --git a/packages/website/ts/utils/constants.ts b/packages/website/ts/utils/constants.ts
index 005d17823..2b4aa5209 100644
--- a/packages/website/ts/utils/constants.ts
+++ b/packages/website/ts/utils/constants.ts
@@ -83,6 +83,7 @@ export const constants = {
URL_PARITY_CHROME_STORE:
'https://chrome.google.com/webstore/detail/parity-ethereum-integrati/himekenlppkgeaoeddcliojfddemadig',
URL_REDDIT: 'https://reddit.com/r/0xproject',
+ URL_SANDBOX: 'https://codesandbox.io/s/1qmjyp7p5j',
URL_STANDARD_RELAYER_API_GITHUB: 'https://github.com/0xProject/standard-relayer-api/blob/master/README.md',
URL_TWITTER: 'https://twitter.com/0xproject',
URL_WETH_IO: 'https://weth.io/',
diff --git a/packages/website/ts/utils/translate.ts b/packages/website/ts/utils/translate.ts
index 1ee1a59c5..5595e6e0f 100644
--- a/packages/website/ts/utils/translate.ts
+++ b/packages/website/ts/utils/translate.ts
@@ -80,7 +80,12 @@ export class Translate {
case Deco.CapWords:
const words = text.split(' ');
- const capitalizedWords = _.map(words, w => this._capitalize(w));
+ const capitalizedWords = _.map(words, (w: string, i: number) => {
+ if (w.length === 1) {
+ return w;
+ }
+ return this._capitalize(w);
+ });
text = capitalizedWords.join(' ');
break;