From 3a7f26f6200bd3796a5207f62c0bdd18858db0e1 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 1 Jun 2018 11:04:56 -0700 Subject: Have basic newsletter subscribe form working --- .../website/ts/components/forms/subscribe_form.tsx | 68 ++++++++++++++++++++++ packages/website/ts/components/token_balances.tsx | 2 +- packages/website/ts/pages/landing/landing.tsx | 2 + packages/website/ts/utils/backend_client.ts | 8 +++ packages/website/ts/utils/fetch_utils.ts | 12 ++++ packages/website/ts/utils/utils.ts | 3 +- 6 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 packages/website/ts/components/forms/subscribe_form.tsx (limited to 'packages/website') 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..8bb0f4fc7 --- /dev/null +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -0,0 +1,68 @@ +import { colors } from '@0xproject/react-shared'; +import * as React from 'react'; + +import RaisedButton from 'material-ui/RaisedButton'; +import { backendClient } from 'ts/utils/backend_client'; + +export interface SubscribeFormProps {} + +export enum SubscribeFormStatus { + None, + Error, + Success, + Loading, +} + +export interface SubscribeFormState { + emailText: string; + status: SubscribeFormStatus; +} + +export class SubscribeForm extends React.Component { + public state = { + emailText: '', + status: SubscribeFormStatus.None, + }; + public render(): React.ReactNode { + return ( +
+ Subscribe to our newsletter for 0x relayer and dApp updates +
+ + +
+
+ ); + } + private _handleEmailInputChange(event: React.ChangeEvent): void { + this.setState({ emailText: event.target.value }); + } + private async _handleSubscribeClickAsync(): Promise { + this._setStatus(SubscribeFormStatus.Loading); + const success = await backendClient.subscribeToNewsletterAsync(this.state.emailText); + const status = success ? SubscribeFormStatus.Success : SubscribeFormStatus.Error; + this._setStatus(status); + } + private _setStatus(status: SubscribeFormStatus): void { + this.setState({ status }); + } +} diff --git a/packages/website/ts/components/token_balances.tsx b/packages/website/ts/components/token_balances.tsx index f5a51dabb..022968941 100644 --- a/packages/website/ts/components/token_balances.tsx +++ b/packages/website/ts/components/token_balances.tsx @@ -77,11 +77,11 @@ interface TokenBalancesProps { interface TokenBalancesState { errorType: BalanceErrs; + trackedTokenStateByAddress: TokenStateByAddress; isBalanceSpinnerVisible: boolean; isZRXSpinnerVisible: boolean; isTokenPickerOpen: boolean; isAddingToken: boolean; - trackedTokenStateByAddress: TokenStateByAddress; } export class TokenBalances extends React.Component { diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index 02ecfa117..016c62a30 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -5,6 +5,7 @@ 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 { Dispatcher } from 'ts/redux/dispatcher'; import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types'; @@ -298,6 +299,7 @@ export class Landing extends React.Component { + diff --git a/packages/website/ts/utils/backend_client.ts b/packages/website/ts/utils/backend_client.ts index c440b1604..fb7c21c59 100644 --- a/packages/website/ts/utils/backend_client.ts +++ b/packages/website/ts/utils/backend_client.ts @@ -8,6 +8,7 @@ const ETH_GAS_STATION_ENDPOINT = '/eth_gas_station'; 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 { @@ -33,4 +34,11 @@ export const backendClient = { const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), WIKI_ENDPOINT); return result; }, + async subscribeToNewsletterAsync(email: string): Promise { + const result = await fetchUtils.postAsync(utils.getBackendBaseUrl(), SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT, { + email, + referrer: window.location.href, + }); + return result.status === 200; + }, }; diff --git a/packages/website/ts/utils/fetch_utils.ts b/packages/website/ts/utils/fetch_utils.ts index d2e902db5..e65ac64e1 100644 --- a/packages/website/ts/utils/fetch_utils.ts +++ b/packages/website/ts/utils/fetch_utils.ts @@ -20,6 +20,18 @@ export const fetchUtils = { const result = await response.json(); return result; }, + + async postAsync(baseUrl: string, path: string, body: object): Promise { + const url = `${baseUrl}${path}`; + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(body), + }); + 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..10381845b 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -306,7 +306,8 @@ export const utils = { return parsedProviderName; }, getBackendBaseUrl(): string { - return isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; + return 'http://localhost:3000'; + // return isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; }, isDevelopment(): boolean { return configs.ENVIRONMENT === Environments.DEVELOPMENT; -- cgit v1.2.3 From 817d9b0d3e1becdb2e8dbf51caa09edab8d14ab0 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 1 Jun 2018 11:40:06 -0700 Subject: Add styled-components and polished --- packages/website/package.json | 2 ++ .../website/ts/components/forms/subscribe_form.tsx | 4 ++-- .../website/ts/components/inputs/allowance_toggle.tsx | 2 +- .../ts/components/onboarding/onboarding_flow.tsx | 2 +- packages/website/ts/components/portal/back_button.tsx | 2 +- packages/website/ts/components/portal/drawer_menu.tsx | 2 +- packages/website/ts/components/portal/menu.tsx | 2 +- .../ts/components/relayer_index/relayer_grid_tile.tsx | 2 +- .../ts/components/relayer_index/relayer_index.tsx | 2 +- .../ts/components/top_bar/provider_display.tsx | 4 ++-- packages/website/ts/components/top_bar/top_bar.tsx | 2 +- packages/website/ts/components/ui/island.tsx | 2 +- packages/website/ts/components/ui/overlay.tsx | 2 +- packages/website/ts/components/wallet/wallet.tsx | 4 ++-- .../ts/components/wallet/wallet_disconnected_item.tsx | 2 +- .../website/ts/components/wallet/wrap_ether_item.tsx | 2 +- packages/website/ts/style/colors.ts | 19 +++++++++++++++++++ packages/website/ts/style/theme.ts | 15 +++++++++++++++ packages/website/ts/style/z_index.ts | 5 +++++ packages/website/ts/utils/colors.ts | 19 ------------------- packages/website/ts/utils/style.ts | 5 ----- packages/website/ts/utils/wallet_item_styles.ts | 2 +- 22 files changed, 60 insertions(+), 43 deletions(-) create mode 100644 packages/website/ts/style/colors.ts create mode 100644 packages/website/ts/style/theme.ts create mode 100644 packages/website/ts/style/z_index.ts delete mode 100644 packages/website/ts/utils/colors.ts delete mode 100644 packages/website/ts/utils/style.ts (limited to 'packages/website') diff --git a/packages/website/package.json b/packages/website/package.json index a17964f2b..54780f600 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -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/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 8bb0f4fc7..3a6d0901f 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -58,8 +58,8 @@ export class SubscribeForm extends React.Component { this._setStatus(SubscribeFormStatus.Loading); - const success = await backendClient.subscribeToNewsletterAsync(this.state.emailText); - const status = success ? SubscribeFormStatus.Success : SubscribeFormStatus.Error; + const isSuccess = await backendClient.subscribeToNewsletterAsync(this.state.emailText); + const status = isSuccess ? SubscribeFormStatus.Success : SubscribeFormStatus.Error; this._setStatus(status); } private _setStatus(status: SubscribeFormStatus): void { diff --git a/packages/website/ts/components/inputs/allowance_toggle.tsx b/packages/website/ts/components/inputs/allowance_toggle.tsx index d61dfa87d..a8df4935a 100644 --- a/packages/website/ts/components/inputs/allowance_toggle.tsx +++ b/packages/website/ts/components/inputs/allowance_toggle.tsx @@ -5,9 +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'; diff --git a/packages/website/ts/components/onboarding/onboarding_flow.tsx b/packages/website/ts/components/onboarding/onboarding_flow.tsx index 4066babaf..158ac23ec 100644 --- a/packages/website/ts/components/onboarding/onboarding_flow.tsx +++ b/packages/website/ts/components/onboarding/onboarding_flow.tsx @@ -5,7 +5,7 @@ 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'; +import { zIndex } from 'ts/style/z_index'; export interface Step { target: string; 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 6a3301549..7d4bc38d2 100644 --- a/packages/website/ts/components/portal/menu.tsx +++ b/packages/website/ts/components/portal/menu.tsx @@ -2,8 +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 { colors } from 'ts/style/colors'; import { Environments, WebsitePaths } from 'ts/types'; -import { colors } from 'ts/utils/colors'; import { configs } from 'ts/utils/configs'; export interface MenuTheme { 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..41febebe9 100644 --- a/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx +++ b/packages/website/ts/components/relayer_index/relayer_grid_tile.tsx @@ -7,8 +7,8 @@ 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 { colors } from 'ts/style/colors'; import { Token, WebsiteBackendRelayerInfo } from 'ts/types'; -import { colors } from 'ts/utils/colors'; 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..683f7084b 100644 --- a/packages/website/ts/components/relayer_index/relayer_index.tsx +++ b/packages/website/ts/components/relayer_index/relayer_index.tsx @@ -6,9 +6,9 @@ import { GridList } from 'material-ui/GridList'; import * as React from 'react'; import { RelayerGridTile } from 'ts/components/relayer_index/relayer_grid_tile'; +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; diff --git a/packages/website/ts/components/top_bar/provider_display.tsx b/packages/website/ts/components/top_bar/provider_display.tsx index 679ec07dc..3edf11e19 100644 --- a/packages/website/ts/components/top_bar/provider_display.tsx +++ b/packages/website/ts/components/top_bar/provider_display.tsx @@ -8,10 +8,10 @@ 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 { zIndex } from 'ts/style/z_index'; 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/top_bar.tsx b/packages/website/ts/components/top_bar/top_bar.tsx index db8e3cb82..ac1dd7d99 100644 --- a/packages/website/ts/components/top_bar/top_bar.tsx +++ b/packages/website/ts/components/top_bar/top_bar.tsx @@ -16,9 +16,9 @@ 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'; diff --git a/packages/website/ts/components/ui/island.tsx b/packages/website/ts/components/ui/island.tsx index f5480c9c9..802a7830a 100644 --- a/packages/website/ts/components/ui/island.tsx +++ b/packages/website/ts/components/ui/island.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; +import { colors } from 'ts/style/colors'; import { Styleable } from 'ts/types'; -import { colors } from 'ts/utils/colors'; export interface IslandProps { style?: React.CSSProperties; diff --git a/packages/website/ts/components/ui/overlay.tsx b/packages/website/ts/components/ui/overlay.tsx index bb2ed8e59..acca8194f 100644 --- a/packages/website/ts/components/ui/overlay.tsx +++ b/packages/website/ts/components/ui/overlay.tsx @@ -2,7 +2,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/wallet/wallet.tsx b/packages/website/ts/components/wallet/wallet.tsx index 30d1285f4..62d3e5af7 100644 --- a/packages/website/ts/components/wallet/wallet.tsx +++ b/packages/website/ts/components/wallet/wallet.tsx @@ -30,6 +30,8 @@ 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 { Dispatcher } from 'ts/redux/dispatcher'; +import { colors } from 'ts/style/colors'; +import { zIndex } from 'ts/style/z_index'; import { BalanceErrs, BlockchainErrs, @@ -44,9 +46,7 @@ import { 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'; diff --git a/packages/website/ts/components/wallet/wallet_disconnected_item.tsx b/packages/website/ts/components/wallet/wallet_disconnected_item.tsx index 39a62e1fb..9207d7ff2 100644 --- a/packages/website/ts/components/wallet/wallet_disconnected_item.tsx +++ b/packages/website/ts/components/wallet/wallet_disconnected_item.tsx @@ -3,8 +3,8 @@ 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..50b64d05c 100644 --- a/packages/website/ts/components/wallet/wrap_ether_item.tsx +++ b/packages/website/ts/components/wallet/wrap_ether_item.tsx @@ -10,8 +10,8 @@ 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'; diff --git a/packages/website/ts/style/colors.ts b/packages/website/ts/style/colors.ts new file mode 100644 index 000000000..5ffdd6ba7 --- /dev/null +++ b/packages/website/ts/style/colors.ts @@ -0,0 +1,19 @@ +import { colors as sharedColors } from '@0xproject/react-shared'; + +const appColors = { + walletBoxShadow: 'rgba(56, 59, 137, 0.2)', + walletBorder: '#ededee', + walletDefaultItemBackground: '#fbfbfc', + walletFocusedItemBackground: '#f0f1f4', + allowanceToggleShadow: 'rgba(0, 0, 0, 0)', + allowanceToggleOffTrack: '#adadad', + allowanceToggleOnTrack: sharedColors.mediumBlue, + wrapEtherConfirmationButton: sharedColors.mediumBlue, + drawerMenuBackground: '#4a4a4a', + menuItemDefaultSelectedBackground: '#424242', +}; + +export const colors = { + ...sharedColors, + ...appColors, +}; diff --git a/packages/website/ts/style/theme.ts b/packages/website/ts/style/theme.ts new file mode 100644 index 000000000..9e447e7ee --- /dev/null +++ b/packages/website/ts/style/theme.ts @@ -0,0 +1,15 @@ +import * as styledComponents from 'styled-components'; + +const { + default: styled, + css, + injectGlobal, + keyframes, + ThemeProvider, +} = styledComponents as styledComponents.ThemedStyledComponentsModule; + +export interface IThemeInterface {} + +export const theme = {}; + +export { styled, css, injectGlobal, keyframes, ThemeProvider }; diff --git a/packages/website/ts/style/z_index.ts b/packages/website/ts/style/z_index.ts new file mode 100644 index 000000000..0411cdd91 --- /dev/null +++ b/packages/website/ts/style/z_index.ts @@ -0,0 +1,5 @@ +export const zIndex = { + topBar: 1100, + overlay: 1105, + aboveOverlay: 1106, +}; diff --git a/packages/website/ts/utils/colors.ts b/packages/website/ts/utils/colors.ts deleted file mode 100644 index 5ffdd6ba7..000000000 --- a/packages/website/ts/utils/colors.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { colors as sharedColors } from '@0xproject/react-shared'; - -const appColors = { - walletBoxShadow: 'rgba(56, 59, 137, 0.2)', - walletBorder: '#ededee', - walletDefaultItemBackground: '#fbfbfc', - walletFocusedItemBackground: '#f0f1f4', - allowanceToggleShadow: 'rgba(0, 0, 0, 0)', - allowanceToggleOffTrack: '#adadad', - allowanceToggleOnTrack: sharedColors.mediumBlue, - wrapEtherConfirmationButton: sharedColors.mediumBlue, - drawerMenuBackground: '#4a4a4a', - menuItemDefaultSelectedBackground: '#424242', -}; - -export const colors = { - ...sharedColors, - ...appColors, -}; diff --git a/packages/website/ts/utils/style.ts b/packages/website/ts/utils/style.ts deleted file mode 100644 index 0411cdd91..000000000 --- a/packages/website/ts/utils/style.ts +++ /dev/null @@ -1,5 +0,0 @@ -export const zIndex = { - topBar: 1100, - overlay: 1105, - aboveOverlay: 1106, -}; 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: { -- cgit v1.2.3 From 073a96cf63a8b2e5639d15133d09545f7bde1388 Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 1 Jun 2018 17:25:50 -0700 Subject: Implement subscription form --- .../website/ts/components/forms/subscribe_form.tsx | 121 +++++++++++++++------ packages/website/ts/components/ui/button.tsx | 79 ++++++++++++++ packages/website/ts/components/ui/container.tsx | 15 ++- packages/website/ts/components/ui/input.tsx | 43 ++++++++ packages/website/ts/components/ui/text.tsx | 56 ++++++++++ packages/website/ts/pages/landing/landing.tsx | 38 ++----- packages/website/ts/utils/backend_client.ts | 4 +- 7 files changed, 288 insertions(+), 68 deletions(-) create mode 100644 packages/website/ts/components/ui/button.tsx create mode 100644 packages/website/ts/components/ui/input.tsx create mode 100644 packages/website/ts/components/ui/text.tsx (limited to 'packages/website') diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 3a6d0901f..99686efce 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -1,7 +1,12 @@ import { colors } from '@0xproject/react-shared'; import * as React from 'react'; -import RaisedButton from 'material-ui/RaisedButton'; +import { Button } from 'ts/components/ui/button'; +import { Input } from 'ts/components/ui/input'; +import { Text } from 'ts/components/ui/text'; +import { logUtils } from '@0xproject/utils'; +import { Container } from 'ts/components/ui/container'; +import { styled } from 'ts/style/theme'; import { backendClient } from 'ts/utils/backend_client'; export interface SubscribeFormProps {} @@ -15,54 +20,102 @@ export enum SubscribeFormStatus { export interface SubscribeFormState { emailText: string; + lastSubmittedEmail: string; status: SubscribeFormStatus; } export class SubscribeForm extends React.Component { public state = { emailText: '', + lastSubmittedEmail: '', status: SubscribeFormStatus.None, }; public render(): React.ReactNode { + const formFontSize = '15px'; return ( -
- Subscribe to our newsletter for 0x relayer and dApp updates -
- - -
-
+ + + + Subscribe to our newsletter for 0x relayer and dApp updates + + +
+ + + + + + + + +
+ {this._renderMessage()} +
); } + 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; + } + return ( + + + {message || 'spacer text'} + + + ); + } + private _handleEmailInputChange(event: React.ChangeEvent): void { this.setState({ emailText: event.target.value }); } - private async _handleSubscribeClickAsync(): Promise { - this._setStatus(SubscribeFormStatus.Loading); - const isSuccess = await backendClient.subscribeToNewsletterAsync(this.state.emailText); - const status = isSuccess ? SubscribeFormStatus.Success : SubscribeFormStatus.Error; - this._setStatus(status); + private async _handleFormSubmitAsync(event: React.FormEvent): Promise { + event.preventDefault(); + if (!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._setStatus(status); + } catch (error) { + logUtils.log(error); + this._setStatus(SubscribeFormStatus.Error); + } finally { + this.setState({ emailText: '' }); + } } - private _setStatus(status: SubscribeFormStatus): void { - this.setState({ status }); + private _setStatus(status: SubscribeFormStatus, then?: () => void): void { + this.setState({ status }, then); } } diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx new file mode 100644 index 000000000..e6e31374f --- /dev/null +++ b/packages/website/ts/components/ui/button.tsx @@ -0,0 +1,79 @@ +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; + backgroundColor?: string; + borderColor?: string; + width?: string; + type?: string; + onClick?: (event: React.MouseEvent) => void; +} + +const PlainButton: React.StatelessComponent = ({ children, onClick, type, className }) => ( + +); + +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: 'Roboto'; + 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', +}; + +Button.displayName = 'Button'; + +type CTAType = 'light' | 'dark'; + +export interface CTAProps { + type?: CTAType; + fontSize?: string; + width?: string; +} + +export const CTA: React.StatelessComponent = ({ 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 ( + + ); +}; + +CTA.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 = (props: ContainerProps) => { - const { children, ...style } = props; - return
{children}
; +export const Container: React.StatelessComponent = ({ children, className, isHidden, ...style }) => { + const visibility = isHidden ? 'hidden' : undefined; + return ( +
+ {children} +
+ ); }; Container.displayName = 'Container'; diff --git a/packages/website/ts/components/ui/input.tsx b/packages/website/ts/components/ui/input.tsx new file mode 100644 index 000000000..75a453eae --- /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) => void; +} + +const PlainInput: React.StatelessComponent = ({ value, className, placeholder, onChange }) => ( + +); + +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.placeholder}; + } +`; + +Input.defaultProps = { + width: 'auto', + backgroundColor: colors.white, + fontColor: colors.darkestGrey, + placeholderColor: colors.grey500, + fontSize: '12px', +}; + +Input.displayName = 'Input'; diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx new file mode 100644 index 000000000..259365618 --- /dev/null +++ b/packages/website/ts/components/ui/text.tsx @@ -0,0 +1,56 @@ +import { colors } from '@0xproject/react-shared'; +import * as React from 'react'; +import { styled } from 'ts/style/theme'; +import { Deco, Key } from 'ts/types'; +import { Translate } from 'ts/utils/translate'; + +export type TextTag = 'p' | 'div' | 'span' | 'label'; + +export interface TextProps { + className?: string; + Tag?: TextTag; + fontSize?: string; + fontFamily?: string; + fontColor?: string; + lineHeight?: string; + center?: boolean; + fontWeight?: number; +} + +const PlainText: React.StatelessComponent = ({ children, className, Tag }) => ( + {children} +); + +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}; +`; + +Text.defaultProps = { + fontFamily: 'Roboto', + fontWeight: 400, + fontColor: colors.white, + fontSize: '14px', + Tag: 'div', +}; + +Text.displayName = 'Text'; + +interface TranslatedProps { + children: Key; + translate: Translate; + deco?: Deco; +} + +export type TranslatedTextProps = TextProps & TranslatedProps; + +export const TranslatedText: React.StatelessComponent = ({ + translate, + children, + deco, + ...textProps +}) => {translate.get(children, deco)}; diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index 016c62a30..0911bb2cf 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -1,7 +1,7 @@ import { colors } from '@0xproject/react-shared'; import * as _ from 'lodash'; -import RaisedButton from 'material-ui/RaisedButton'; import * as React from 'react'; +import { CTA } from 'ts/components/ui/button'; import DocumentTitle = require('react-document-title'); import { Link } from 'react-router-dom'; import { Footer } from 'ts/components/footer'; @@ -237,7 +237,7 @@ export class Landing extends React.Component {
{this._renderWhatsNew()} -
+
@@ -272,13 +272,9 @@ export class Landing extends React.Component {
- + + {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)} +
@@ -287,23 +283,17 @@ export class Landing extends React.Component { target="_blank" className="text-decoration-none" > - + + {this.props.translate.get(Key.CommunityCallToAction, Deco.Cap)} +
-
+ ); } @@ -784,15 +774,7 @@ export class Landing extends React.Component {
- + {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
diff --git a/packages/website/ts/utils/backend_client.ts b/packages/website/ts/utils/backend_client.ts index fb7c21c59..6b16aea6b 100644 --- a/packages/website/ts/utils/backend_client.ts +++ b/packages/website/ts/utils/backend_client.ts @@ -34,11 +34,11 @@ export const backendClient = { const result = await fetchUtils.requestAsync(utils.getBackendBaseUrl(), WIKI_ENDPOINT); return result; }, - async subscribeToNewsletterAsync(email: string): Promise { + async subscribeToNewsletterAsync(email: string): Promise { const result = await fetchUtils.postAsync(utils.getBackendBaseUrl(), SUBSCRIBE_SUBSTACK_NEWSLETTER_ENDPOINT, { email, referrer: window.location.href, }); - return result.status === 200; + return result; }, }; -- cgit v1.2.3 From a74597c7cd44d3138de39ec05079e9b9e005d03d Mon Sep 17 00:00:00 2001 From: fragosti Date: Fri, 1 Jun 2018 17:37:32 -0700 Subject: Lint and cleanup --- packages/website/ts/components/forms/subscribe_form.tsx | 8 ++++---- packages/website/ts/components/ui/text.tsx | 2 +- packages/website/ts/pages/landing/landing.tsx | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 99686efce..b83a9c346 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -1,11 +1,11 @@ import { colors } from '@0xproject/react-shared'; import * as React from 'react'; +import { logUtils } from '@0xproject/utils'; 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 { logUtils } from '@0xproject/utils'; -import { Container } from 'ts/components/ui/container'; import { styled } from 'ts/style/theme'; import { backendClient } from 'ts/utils/backend_client'; @@ -47,7 +47,7 @@ export class SubscribeForm extends React.Component @@ -55,7 +55,7 @@ export class SubscribeForm extends React.Component @@ -82,16 +84,19 @@ export class SubscribeForm extends React.Component - {message || 'spacer text'} + {message || 'spacer text (never shown to user)'} ); } - private _handleEmailInputChange(event: React.ChangeEvent): void { this.setState({ emailText: event.target.value }); } @@ -107,15 +112,12 @@ export class SubscribeForm extends React.Component void): void { - this.setState({ status }, then); + private _setStatus(status: SubscribeFormStatus): void { + this.setState({ status }); } } diff --git a/packages/website/ts/components/ui/button.tsx b/packages/website/ts/components/ui/button.tsx index e6e31374f..4c7d59839 100644 --- a/packages/website/ts/components/ui/button.tsx +++ b/packages/website/ts/components/ui/button.tsx @@ -48,15 +48,15 @@ Button.defaultProps = { Button.displayName = 'Button'; -type CTAType = 'light' | 'dark'; +type CallToActionType = 'light' | 'dark'; -export interface CTAProps { - type?: CTAType; +export interface CallToActionProps { + type?: CallToActionType; fontSize?: string; width?: string; } -export const CTA: React.StatelessComponent = ({ children, type, fontSize, width }) => { +export const CallToAction: React.StatelessComponent = ({ children, type, fontSize, width }) => { const isLight = type === 'light'; const backgroundColor = isLight ? colors.white : colors.heroGrey; const fontColor = isLight ? colors.heroGrey : colors.white; @@ -74,6 +74,6 @@ export const CTA: React.StatelessComponent = ({ children, type, fontSi ); }; -CTA.defaultProps = { +CallToAction.defaultProps = { type: 'dark', }; diff --git a/packages/website/ts/components/ui/input.tsx b/packages/website/ts/components/ui/input.tsx index 75a453eae..e01a71a53 100644 --- a/packages/website/ts/components/ui/input.tsx +++ b/packages/website/ts/components/ui/input.tsx @@ -28,7 +28,7 @@ export const Input = styled(PlainInput)` border: none; background-color: ${props => props.backgroundColor}; &::placeholder { - color: ${props => props.placeholder}; + color: ${props => props.placeholderColor}; } `; @@ -36,7 +36,7 @@ Input.defaultProps = { width: 'auto', backgroundColor: colors.white, fontColor: colors.darkestGrey, - placeholderColor: colors.grey500, + placeholderColor: colors.darkGrey, fontSize: '12px', }; diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx index d3e205d12..259365618 100644 --- a/packages/website/ts/components/ui/text.tsx +++ b/packages/website/ts/components/ui/text.tsx @@ -52,5 +52,5 @@ export const TranslatedText: React.StatelessComponent = ({ translate, children, deco, - ...textProps, + ...textProps }) => {translate.get(children, deco)}; diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index 1a1772a23..db3eb83b0 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -6,7 +6,7 @@ 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 { CTA } from 'ts/components/ui/button'; +import { CallToAction } from 'ts/components/ui/button'; import { Dispatcher } from 'ts/redux/dispatcher'; import { Deco, Key, Language, ScreenWidths, WebsitePaths } from 'ts/types'; import { constants } from 'ts/utils/constants'; @@ -272,9 +272,9 @@ export class Landing extends React.Component {
- + {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)} - +
@@ -283,9 +283,9 @@ export class Landing extends React.Component { target="_blank" className="text-decoration-none" > - + {this.props.translate.get(Key.CommunityCallToAction, Deco.Cap)} - +
@@ -774,7 +774,9 @@ export class Landing extends React.Component {
- {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)} + + {this.props.translate.get(Key.BuildCallToAction, Deco.Cap)} +
diff --git a/packages/website/ts/utils/fetch_utils.ts b/packages/website/ts/utils/fetch_utils.ts index e65ac64e1..513f7e479 100644 --- a/packages/website/ts/utils/fetch_utils.ts +++ b/packages/website/ts/utils/fetch_utils.ts @@ -4,23 +4,26 @@ 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 { 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 { const url = `${baseUrl}${path}`; const response = await fetch(url, { @@ -30,6 +33,7 @@ export const fetchUtils = { }, body: JSON.stringify(body), }); + logErrorIfPresent(response, url); return response; }, }; diff --git a/packages/website/ts/utils/utils.ts b/packages/website/ts/utils/utils.ts index 10381845b..b9d962b75 100644 --- a/packages/website/ts/utils/utils.ts +++ b/packages/website/ts/utils/utils.ts @@ -306,8 +306,7 @@ export const utils = { return parsedProviderName; }, getBackendBaseUrl(): string { - return 'http://localhost:3000'; - // return isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; + return isDogfood() ? configs.BACKEND_BASE_STAGING_URL : configs.BACKEND_BASE_PROD_URL; }, isDevelopment(): boolean { return configs.ENVIRONMENT === Environments.DEVELOPMENT; -- cgit v1.2.3 From 3c508c1d271ffba4eead6f0c145d57330804697c Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 4 Jun 2018 17:06:23 -0700 Subject: Do not show subscribe form if language is not english --- packages/website/ts/pages/landing/landing.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index db3eb83b0..aa639c10e 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -293,7 +293,7 @@ export class Landing extends React.Component { - + {this.props.translate.getLanguage() === Language.English && } ); } -- cgit v1.2.3 From ea2d5b9d4a7c3e59645a0b302dc6979e6b9b285f Mon Sep 17 00:00:00 2001 From: fragosti Date: Mon, 4 Jun 2018 17:51:48 -0700 Subject: Make buttons stack on mobile --- packages/website/ts/components/ui/text.tsx | 2 +- packages/website/ts/pages/landing/landing.tsx | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/ui/text.tsx b/packages/website/ts/components/ui/text.tsx index 259365618..d3e205d12 100644 --- a/packages/website/ts/components/ui/text.tsx +++ b/packages/website/ts/components/ui/text.tsx @@ -52,5 +52,5 @@ export const TranslatedText: React.StatelessComponent = ({ translate, children, deco, - ...textProps + ...textProps, }) => {translate.get(children, deco)}; diff --git a/packages/website/ts/pages/landing/landing.tsx b/packages/website/ts/pages/landing/landing.tsx index aa639c10e..f3428d475 100644 --- a/packages/website/ts/pages/landing/landing.tsx +++ b/packages/website/ts/pages/landing/landing.tsx @@ -7,6 +7,7 @@ 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'; @@ -269,15 +270,15 @@ export class Landing extends React.Component { > {this.props.translate.get(Key.TopTagline)} -
-
+ +
{this.props.translate.get(Key.BuildCallToAction, Deco.Cap)}
-
+ -
+
-- cgit v1.2.3 From 8de3f03b4982f14459b10a0ef1d60ab713d5c7be Mon Sep 17 00:00:00 2001 From: fragosti Date: Tue, 5 Jun 2018 12:59:10 -0700 Subject: Use stricter check for subscribe input text --- packages/website/ts/components/forms/subscribe_form.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'packages/website') diff --git a/packages/website/ts/components/forms/subscribe_form.tsx b/packages/website/ts/components/forms/subscribe_form.tsx index 4bef3a7b6..04ef28e70 100644 --- a/packages/website/ts/components/forms/subscribe_form.tsx +++ b/packages/website/ts/components/forms/subscribe_form.tsx @@ -1,4 +1,5 @@ import { colors } from '@0xproject/react-shared'; +import * as _ from 'lodash'; import * as React from 'react'; import { Button } from 'ts/components/ui/button'; @@ -102,7 +103,7 @@ export class SubscribeForm extends React.Component): Promise { event.preventDefault(); - if (!this.state.emailText) { + if (_.isUndefined(this.state.emailText) || _.isEmpty(this.state.emailText)) { return; } this.setState({ -- cgit v1.2.3