diff --git a/packages/website/ts/components/legacy_portal/legacy_portal.tsx b/packages/website/ts/components/legacy_portal/legacy_portal.tsx index 6a3a543038..e5d152e3ed 100644 --- a/packages/website/ts/components/legacy_portal/legacy_portal.tsx +++ b/packages/website/ts/components/legacy_portal/legacy_portal.tsx @@ -38,6 +38,7 @@ import { } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; +import { orderParser } from 'ts/utils/order_parser'; import { Translate } from 'ts/utils/translate'; import { utils } from 'ts/utils/utils'; @@ -86,7 +87,7 @@ export class LegacyPortal extends React.Component { - const queryPair = queryParam.split('='); - return queryPair[0] === 'order'; - }); - if (_.isUndefined(orderQueryParam)) { - return undefined; - } - const orderPair = orderQueryParam.split('='); - if (orderPair.length !== 2) { - return undefined; - } - - const order = JSON.parse(decodeURIComponent(orderPair[1])); - const validationResult = validator.validate(order, portalOrderSchema); - if (validationResult.errors.length > 0) { - logUtils.log(`Invalid shared order: ${validationResult.errors}`); - return undefined; - } - return order; - } private _updateScreenWidth(): void { const newScreenWidth = utils.getScreenWidth(); this.props.dispatcher.updateScreenWidth(newScreenWidth); diff --git a/packages/website/ts/components/portal/menu.tsx b/packages/website/ts/components/portal/menu.tsx index 6a3301549f..6e97ee37e4 100644 --- a/packages/website/ts/components/portal/menu.tsx +++ b/packages/website/ts/components/portal/menu.tsx @@ -43,9 +43,14 @@ export const defaultMenuItemEntries: MenuItemEntry[] = [ iconName: 'zmdi-circle-o', }, { - to: `${WebsitePaths.Portal}/direct`, - labelText: 'Trade direct', - iconName: 'zmdi-swap', + to: `${WebsitePaths.Portal}/generate`, + labelText: 'Generate order', + iconName: 'zmdi-arrow-right-top', + }, + { + to: `${WebsitePaths.Portal}/fill`, + labelText: 'Fill order', + iconName: 'zmdi-arrow-left-bottom', }, ]; diff --git a/packages/website/ts/components/portal/portal.tsx b/packages/website/ts/components/portal/portal.tsx index e083937913..589ad00ad2 100644 --- a/packages/website/ts/components/portal/portal.tsx +++ b/packages/website/ts/components/portal/portal.tsx @@ -10,6 +10,7 @@ import { BlockchainErrDialog } from 'ts/components/dialogs/blockchain_err_dialog import { LedgerConfigDialog } from 'ts/components/dialogs/ledger_config_dialog'; import { PortalDisclaimerDialog } from 'ts/components/dialogs/portal_disclaimer_dialog'; import { EthWrappers } from 'ts/components/eth_wrappers'; +import { FillOrder } from 'ts/components/fill_order'; import { AssetPicker } from 'ts/components/generate_order/asset_picker'; import { BackButton } from 'ts/components/portal/back_button'; import { Loading } from 'ts/components/portal/loading'; @@ -42,6 +43,7 @@ import { } from 'ts/types'; import { configs } from 'ts/utils/configs'; import { constants } from 'ts/utils/constants'; +import { orderParser } from 'ts/utils/order_parser'; import { Translate } from 'ts/utils/translate'; import { utils } from 'ts/utils/utils'; @@ -116,9 +118,11 @@ const styles: Styles = { export class Portal extends React.Component { private _blockchain: Blockchain; + private _sharedOrderIfExists: Order; private _throttledScreenWidthUpdate: () => void; constructor(props: PortalProps) { super(props); + this._sharedOrderIfExists = orderParser.parse(window.location.search); this._throttledScreenWidthUpdate = _.throttle(this._updateScreenWidth.bind(this), THROTTLE_TIMEOUT); const didAcceptPortalDisclaimer = localStorage.getItemIfExists(constants.LOCAL_STORAGE_KEY_ACCEPT_DISCLAIMER); const hasAcceptedDisclaimer = @@ -336,9 +340,14 @@ export class Portal extends React.Component { render: this._renderTradeHistory.bind(this), }, { - pathName: `${WebsitePaths.Portal}/direct`, - headerText: 'Trade Direct', - render: this._renderTradeDirect.bind(this), + pathName: `${WebsitePaths.Portal}/generate`, + headerText: 'Generate Order', + render: this._renderGenerateOrderForm.bind(this), + }, + { + pathName: `${WebsitePaths.Portal}/fill`, + headerText: 'Fill Order', + render: this._renderFillOrder.bind(this), }, ]; return ( @@ -386,7 +395,7 @@ export class Portal extends React.Component { /> ); } - private _renderTradeDirect(match: any, location: Location, history: History): React.ReactNode { + private _renderGenerateOrderForm(): React.ReactNode { return ( { /> ); } + private _renderFillOrder(): React.ReactNode { + const initialFillOrder = !_.isUndefined(this.props.userSuppliedOrderCache) + ? this.props.userSuppliedOrderCache + : this._sharedOrderIfExists; + return ( + + ); + } private _renderTokenBalances(): React.ReactNode { const allTokens = _.values(this.props.tokenByAddress); const trackedTokens = _.filter(allTokens, t => t.isTracked); diff --git a/packages/website/ts/utils/order_parser.ts b/packages/website/ts/utils/order_parser.ts new file mode 100644 index 0000000000..be08da80e5 --- /dev/null +++ b/packages/website/ts/utils/order_parser.ts @@ -0,0 +1,33 @@ +import { logUtils } from '@0xproject/utils'; +import * as _ from 'lodash'; + +import { portalOrderSchema } from 'ts/schemas/portal_order_schema'; +import { validator } from 'ts/schemas/validator'; +import { Order } from 'ts/types'; + +export const orderParser = { + parse(queryString: string): Order | undefined { + if (queryString.length === 0) { + return undefined; + } + const queryParams = queryString.substring(1).split('&'); + const orderQueryParam = _.find(queryParams, queryParam => { + const queryPair = queryParam.split('='); + return queryPair[0] === 'order'; + }); + if (_.isUndefined(orderQueryParam)) { + return undefined; + } + const orderPair = orderQueryParam.split('='); + if (orderPair.length !== 2) { + return undefined; + } + const order = JSON.parse(decodeURIComponent(orderPair[1])); + const validationResult = validator.validate(order, portalOrderSchema); + if (validationResult.errors.length > 0) { + logUtils.log(`Invalid shared order: ${validationResult.errors}`); + return undefined; + } + return order; + }, +};