diff options
| author | Oskar Nyberg <oskar@mullvad.net> | 2020-05-19 12:07:03 +0200 |
|---|---|---|
| committer | Oskar Nyberg <oskar@mullvad.net> | 2020-05-19 12:07:03 +0200 |
| commit | 17a1b03fb8a21844c815d0b8f4efea3a26526064 (patch) | |
| tree | 6ccbdd334b127e135857b65d8802a0e40d77d690 /gui | |
| parent | 5d3f86a2cfc78c5014dceacba4f0011e7ed7875f (diff) | |
| parent | 2fe210f325d53cc64fd2742976a93aa0816b1ebb (diff) | |
| download | mullvadvpn-17a1b03fb8a21844c815d0b8f4efea3a26526064.tar.xz mullvadvpn-17a1b03fb8a21844c815d0b8f4efea3a26526064.zip | |
Merge branch 'add-voucher-payment-to-account-view'
Diffstat (limited to 'gui')
| -rw-r--r-- | gui/src/renderer/components/Account.tsx | 103 | ||||
| -rw-r--r-- | gui/src/renderer/components/AccountStyles.tsx | 2 | ||||
| -rw-r--r-- | gui/src/renderer/components/ExpiredAccountErrorView.tsx | 39 | ||||
| -rw-r--r-- | gui/src/renderer/components/RedeemVoucher.tsx | 52 | ||||
| -rw-r--r-- | gui/src/renderer/components/RedeemVoucherStyles.tsx | 9 |
5 files changed, 120 insertions, 85 deletions
diff --git a/gui/src/renderer/components/Account.tsx b/gui/src/renderer/components/Account.tsx index 0055a32049..7863040f83 100644 --- a/gui/src/renderer/components/Account.tsx +++ b/gui/src/renderer/components/Account.tsx @@ -13,7 +13,9 @@ import styles, { import AccountTokenLabel from './AccountTokenLabel'; import * as AppButton from './AppButton'; import { Layout } from './Layout'; +import { ModalContainer } from './Modal'; import { BackBarItem, NavigationBar, NavigationItems } from './NavigationBar'; +import { RedeemVoucherButton } from './RedeemVoucher'; import SettingsHeader, { HeaderTitle } from './SettingsHeader'; import { AccountToken } from '../../shared/daemon-rpc-types'; @@ -31,58 +33,63 @@ interface IProps { export default class Account extends React.Component<IProps> { public render() { return ( - <Layout> - <StyledContainer> - <NavigationBar> - <NavigationItems> - <BackBarItem action={this.props.onClose}> - { - // TRANSLATORS: Back button in navigation bar - messages.pgettext('navigation-bar', 'Settings') - } - </BackBarItem> - </NavigationItems> - </NavigationBar> + <ModalContainer> + <Layout> + <StyledContainer> + <NavigationBar> + <NavigationItems> + <BackBarItem action={this.props.onClose}> + { + // TRANSLATORS: Back button in navigation bar + messages.pgettext('navigation-bar', 'Settings') + } + </BackBarItem> + </NavigationItems> + </NavigationBar> - <AccountContainer> - <SettingsHeader> - <HeaderTitle>{messages.pgettext('account-view', 'Account')}</HeaderTitle> - </SettingsHeader> + <AccountContainer> + <SettingsHeader> + <HeaderTitle>{messages.pgettext('account-view', 'Account')}</HeaderTitle> + </SettingsHeader> - <AccountRow> - <AccountRowLabel> - {messages.pgettext('account-view', 'Account number')} - </AccountRowLabel> - <AccountRowValue - as={AccountTokenLabel} - accountToken={this.props.accountToken || ''} - /> - </AccountRow> + <AccountRow> + <AccountRowLabel> + {messages.pgettext('account-view', 'Account number')} + </AccountRowLabel> + <AccountRowValue + as={AccountTokenLabel} + accountToken={this.props.accountToken || ''} + /> + </AccountRow> - <AccountRow> - <AccountRowLabel>{messages.pgettext('account-view', 'Paid until')}</AccountRowLabel> - <FormattedAccountExpiry - expiry={this.props.accountExpiry} - locale={this.props.expiryLocale} - /> - </AccountRow> + <AccountRow> + <AccountRowLabel>{messages.pgettext('account-view', 'Paid until')}</AccountRowLabel> + <FormattedAccountExpiry + expiry={this.props.accountExpiry} + locale={this.props.expiryLocale} + /> + </AccountRow> - <AccountFooter> - <AppButton.BlockingButton - disabled={this.props.isOffline} - onPress={this.props.onBuyMore}> - <AppButton.GreenButton style={styles.account__buy_button}> - <AppButton.Label>{messages.gettext('Buy more credit')}</AppButton.Label> - <AppButton.Icon source="icon-extLink" height={16} width={16} /> - </AppButton.GreenButton> - </AppButton.BlockingButton> - <AppButton.RedButton onPress={this.props.onLogout}> - {messages.pgettext('account-view', 'Log out')} - </AppButton.RedButton> - </AccountFooter> - </AccountContainer> - </StyledContainer> - </Layout> + <AccountFooter> + <AppButton.BlockingButton + disabled={this.props.isOffline} + onPress={this.props.onBuyMore}> + <AppButton.GreenButton style={styles.button}> + <AppButton.Label>{messages.gettext('Buy more credit')}</AppButton.Label> + <AppButton.Icon source="icon-extLink" height={16} width={16} /> + </AppButton.GreenButton> + </AppButton.BlockingButton> + + <RedeemVoucherButton style={styles.button} /> + + <AppButton.RedButton onPress={this.props.onLogout}> + {messages.pgettext('account-view', 'Log out')} + </AppButton.RedButton> + </AccountFooter> + </AccountContainer> + </StyledContainer> + </Layout> + </ModalContainer> ); } } diff --git a/gui/src/renderer/components/AccountStyles.tsx b/gui/src/renderer/components/AccountStyles.tsx index c793b96a1b..970309e4f8 100644 --- a/gui/src/renderer/components/AccountStyles.tsx +++ b/gui/src/renderer/components/AccountStyles.tsx @@ -52,7 +52,7 @@ export const AccountFooter = styled.div({ }); export default { - account__buy_button: Styles.createViewStyle({ + button: Styles.createViewStyle({ marginBottom: 24, }), }; diff --git a/gui/src/renderer/components/ExpiredAccountErrorView.tsx b/gui/src/renderer/components/ExpiredAccountErrorView.tsx index 5703a33947..51c1867cf9 100644 --- a/gui/src/renderer/components/ExpiredAccountErrorView.tsx +++ b/gui/src/renderer/components/ExpiredAccountErrorView.tsx @@ -5,7 +5,6 @@ import { links } from '../../config.json'; import AccountExpiry from '../../shared/account-expiry'; import { AccountToken } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; -import { RedeemVoucherContainer } from '../components/RedeemVoucher'; import { LoginState } from '../redux/account/reducers'; import * as AppButton from './AppButton'; import * as Cell from './Cell'; @@ -13,11 +12,7 @@ import CustomScrollbars from './CustomScrollbars'; import styles, { StyledAccountTokenLabel } from './ExpiredAccountErrorViewStyles'; import ImageView from './ImageView'; import { ModalAlert, ModalAlertType } from './Modal'; -import { - RedeemVoucherInput, - RedeemVoucherResponse, - RedeemVoucherSubmitButton, -} from './RedeemVoucher'; +import { RedeemVoucherContainer, RedeemVoucherAlert } from './RedeemVoucher'; export enum RecoveryAction { openBrowser, @@ -40,7 +35,6 @@ interface IExpiredAccountErrorViewProps { interface IExpiredAccountErrorViewState { showBlockWhenDisconnectedAlert: boolean; showRedeemVoucherAlert: boolean; - redeemingVoucher: boolean; } export default class ExpiredAccountErrorView extends Component< @@ -50,7 +44,6 @@ export default class ExpiredAccountErrorView extends Component< public state: IExpiredAccountErrorViewState = { showBlockWhenDisconnectedAlert: false, showRedeemVoucherAlert: false, - redeemingVoucher: false, }; public componentDidUpdate() { @@ -175,26 +168,8 @@ export default class ExpiredAccountErrorView extends Component< private renderRedeemVoucherAlert() { return ( - <RedeemVoucherContainer - onSubmit={this.onVoucherSubmit} - onSuccess={this.props.hideWelcomeView} - onFailure={this.onVoucherResponse}> - <ModalAlert - buttons={[ - <RedeemVoucherSubmitButton key="submit" />, - <AppButton.BlueButton - key="cancel" - disabled={this.state.redeemingVoucher} - onPress={this.onCloseRedeemVoucherAlert}> - {messages.gettext('Cancel')} - </AppButton.BlueButton>, - ]}> - <Text style={styles.fieldLabel}> - {messages.pgettext('connect-view', 'Enter voucher code')} - </Text> - <RedeemVoucherInput /> - <RedeemVoucherResponse /> - </ModalAlert> + <RedeemVoucherContainer onSuccess={this.props.hideWelcomeView}> + <RedeemVoucherAlert onClose={this.onCloseRedeemVoucherAlert} /> </RedeemVoucherContainer> ); } @@ -269,14 +244,6 @@ export default class ExpiredAccountErrorView extends Component< this.setState({ showRedeemVoucherAlert: false }); }; - private onVoucherSubmit = () => { - this.setState({ redeemingVoucher: true }); - }; - - private onVoucherResponse = () => { - this.setState({ redeemingVoucher: false }); - }; - private onCloseBlockWhenDisconnectedInstructions = () => { this.setState({ showBlockWhenDisconnectedAlert: false }); }; diff --git a/gui/src/renderer/components/RedeemVoucher.tsx b/gui/src/renderer/components/RedeemVoucher.tsx index 39f3e68d3d..ad16523f54 100644 --- a/gui/src/renderer/components/RedeemVoucher.tsx +++ b/gui/src/renderer/components/RedeemVoucher.tsx @@ -1,14 +1,19 @@ import React, { useCallback, useContext, useState } from 'react'; +import { useSelector } from 'react-redux'; +import { Types } from 'reactxp'; import { VoucherResponse } from '../../shared/daemon-rpc-types'; import { messages } from '../../shared/gettext'; import { useAppContext } from '../context'; import useActions from '../lib/actionsHook'; import accountActions from '../redux/account/actions'; +import { IReduxState } from '../redux/store'; import * as AppButton from './AppButton'; +import { ModalAlert } from './Modal'; import { StyledEmptyResponse, StyledErrorResponse, StyledInput, + StyledLabel, StyledSpinner, StyledSuccessResponse, } from './RedeemVoucherStyles'; @@ -171,3 +176,50 @@ export function RedeemVoucherSubmitButton() { </AppButton.GreenButton> ); } + +interface IRedeemVoucherAlertProps { + onClose?: () => void; +} + +export function RedeemVoucherAlert(props: IRedeemVoucherAlertProps) { + const { submitting } = useContext(RedeemVoucherContext); + + return ( + <ModalAlert + buttons={[ + <RedeemVoucherSubmitButton key="submit" />, + <AppButton.BlueButton key="cancel" disabled={submitting} onPress={props.onClose}> + {messages.pgettext('redeem-voucher-alert', 'Cancel')} + </AppButton.BlueButton>, + ]}> + <StyledLabel>{messages.pgettext('redeem-voucher-alert', 'Enter voucher code')}</StyledLabel> + <RedeemVoucherInput /> + <RedeemVoucherResponse /> + </ModalAlert> + ); +} + +interface IRedeemVoucherButtonProps { + style?: Types.StyleRuleSetRecursive<Types.ViewStyleRuleSet>; +} + +export function RedeemVoucherButton(props: IRedeemVoucherButtonProps) { + const isBlocked = useSelector((state: IReduxState) => state.connection.isBlocked); + const [showAlert, setShowAlert] = useState(false); + + const onPress = useCallback(() => setShowAlert(true), []); + const onAlertClose = useCallback(() => setShowAlert(false), []); + + return ( + <> + <AppButton.GreenButton disabled={isBlocked} onPress={onPress} style={props.style}> + {messages.pgettext('redeem-voucher-alert', 'Redeem voucher')} + </AppButton.GreenButton> + {showAlert && ( + <RedeemVoucherContainer onSuccess={onAlertClose}> + <RedeemVoucherAlert onClose={onAlertClose} /> + </RedeemVoucherContainer> + )} + </> + ); +} diff --git a/gui/src/renderer/components/RedeemVoucherStyles.tsx b/gui/src/renderer/components/RedeemVoucherStyles.tsx index 6ce463fab9..cd7d0cc7eb 100644 --- a/gui/src/renderer/components/RedeemVoucherStyles.tsx +++ b/gui/src/renderer/components/RedeemVoucherStyles.tsx @@ -2,6 +2,15 @@ import styled from 'styled-components'; import { colors } from '../../config.json'; import ImageView from './ImageView'; +export const StyledLabel = styled.span({ + fontFamily: 'Open Sans', + fontSize: '13px', + fontWeight: 600, + lineHeight: '20px', + color: colors.white, + marginBottom: '9px', +}); + export const StyledInput = styled.input({ flex: 1, overflow: 'hidden', |
