From 4d323c9f4ec80503af023d80bcd03ac8e61670c6 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 5 Aug 2021 18:13:57 -0600 Subject: [PATCH 001/101] Add default/delete popover and supporting methods --- .../settings/Payments/PaymentMethodList.js | 4 +- src/pages/settings/Payments/PaymentsPage.js | 103 +++++++++++++++++- src/styles/styles.js | 4 + src/styles/utilities/spacing.js | 4 + 4 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index 5d1b3bd3ceef..a7611556b11d 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -95,7 +95,7 @@ class PaymentMethodList extends Component { // eslint-disable-next-line description: formattedBankAccountNumber, icon: Bank, - onPress: e => this.props.onPress(e, bankAccount.bankAccountID), + onPress: e => this.props.onPress(e, 'bankAccount', bankAccount.bankAccountID), key: `bankAccount-${bankAccount.bankAccountID}`, }); } @@ -114,7 +114,7 @@ class PaymentMethodList extends Component { // eslint-disable-next-line description: formattedCardNumber, icon: CreditCard, - onPress: e => this.props.onPress(e, card.cardID), + onPress: e => this.props.onPress(e, 'card', card.cardID), key: `card-${card.cardID}`, }); } diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 70296695c111..2de18912e9de 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -1,5 +1,5 @@ import React from 'react'; -import {View} from 'react-native'; +import {View, TouchableOpacity} from 'react-native'; import PaymentMethodList from './PaymentMethodList'; import ROUTES from '../../../ROUTES'; import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; @@ -12,14 +12,18 @@ import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index import Text from '../../../components/Text'; import getPaymentMethods from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; -import {PayPal} from '../../../components/Icon/Expensicons'; +import {PayPal, Bank} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; import getClickedElementLocation from '../../../libs/getClickedElementLocation'; +import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; +import NameValuePair from '../../../libs/actions/NameValuePair'; +import CONST from '../../../CONST'; import CurrentWalletBalance from '../../../components/CurrentWalletBalance'; const PAYPAL = 'payPalMe'; const propTypes = { + ...windowDimensionsPropTypes, ...withLocalizePropTypes, }; @@ -33,6 +37,9 @@ class PaymentsPage extends React.Component { this.state = { shouldShowAddPaymentMenu: false, + shouldShowDefaultDeleteMenu: false, + selectedPaymentMethod: {}, + formattedSelectedPaymentMethod: {}, anchorPositionTop: 0, anchorPositionLeft: 0, isLoadingPaymentMethods: true, @@ -41,6 +48,9 @@ class PaymentsPage extends React.Component { this.paymentMethodPressed = this.paymentMethodPressed.bind(this); this.addPaymentMethodTypePressed = this.addPaymentMethodTypePressed.bind(this); this.hideAddPaymentMenu = this.hideAddPaymentMenu.bind(this); + this.hideDefaultDeleteMenu = this.hideDefaultDeleteMenu.bind(this); + this.makeDefaultPaymentMethod = this.makeDefaultPaymentMethod.bind(this); + this.deletePaymentMethod = this.deletePaymentMethod.bind(this); } componentDidMount() { @@ -53,9 +63,10 @@ class PaymentsPage extends React.Component { * Display the delete/default menu, or the add payment method menu * * @param {Object} nativeEvent + * @param {String} accountType * @param {String} account */ - paymentMethodPressed(nativeEvent, account) { + paymentMethodPressed(nativeEvent, accountType, account) { if (account) { if (account === PAYPAL) { Navigation.navigate(ROUTES.SETTINGS_ADD_PAYPAL_ME); @@ -70,6 +81,37 @@ class PaymentsPage extends React.Component { anchorPositionLeft: position.left + 20, }); } + + const position = getClickedElementLocation(nativeEvent); + if (accountType) { + let formattedSelectedPaymentMethod; + if (accountType === PAYPAL) { + formattedSelectedPaymentMethod = { + title: 'PayPal.me', + icon: Bank, + }; + } else if (accountType === 'bankAccount') { + formattedSelectedPaymentMethod = { + title: account.addressName, + icon: Bank, + }; + } else { + formattedSelectedPaymentMethod = { + title: account.cardName, + icon: Bank, + }; + } + this.setState({ + shouldShowDefaultDeleteMenu: true, + selectedPaymentMethod: account, + selectedPaymentMethodType: accountType, + anchorPositionTop: position.bottom, + + // We want the position to be 20px to the right of the left border + anchorPositionLeft: position.left + 20, + formattedSelectedPaymentMethod, + }); + } } /** @@ -92,6 +134,21 @@ class PaymentsPage extends React.Component { this.setState({shouldShowAddPaymentMenu: false}); } + /** + * Hide the default / delete modal + */ + hideDefaultDeleteMenu() { + this.setState({shouldShowDefaultDeleteMenu: false}); + } + + makeDefaultPaymentMethod() { + + } + + deletePaymentMethod() { + + } + render() { return ( @@ -129,6 +186,45 @@ class PaymentsPage extends React.Component { onPress={() => this.addPaymentMethodTypePressed(PAYPAL)} /> + + {this.props.isSmallScreenWidth && ( + {}} + /> + )} + + + Make Default Payment Method + + + + + {this.props.translate('common.delete')} + + + ); @@ -140,5 +236,6 @@ PaymentsPage.defaultProps = defaultProps; PaymentsPage.displayName = 'PaymentsPage'; export default compose( + withWindowDimensions, withLocalize, )(PaymentsPage); diff --git a/src/styles/styles.js b/src/styles/styles.js index b1ade504e459..10914cfc0907 100644 --- a/src/styles/styles.js +++ b/src/styles/styles.js @@ -1855,6 +1855,10 @@ const styles = { ...whiteSpace.noWrap, }, + defaultOrDeleteButton: { + width: variables.sideBarWidth - 70, + }, + shortTermsRow: { flexDirection: 'row', padding: 12, diff --git a/src/styles/utilities/spacing.js b/src/styles/utilities/spacing.js index 2ddb61032358..b0dedd2a2482 100644 --- a/src/styles/utilities/spacing.js +++ b/src/styles/utilities/spacing.js @@ -25,6 +25,10 @@ export default { marginHorizontal: 4, }, + mh2: { + marginHorizontal: 8, + }, + mh5: { marginHorizontal: 20, }, From 8e2ae55ee80ae739cf1a512b546e582e621f115b Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Mon, 9 Aug 2021 12:07:01 -0600 Subject: [PATCH 002/101] Add popover and merge master --- src/pages/settings/Payments/PaymentsPage.js | 66 +++++++++++++++------ 1 file changed, 48 insertions(+), 18 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 2de18912e9de..0b831bf4c474 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -7,12 +7,14 @@ import ScreenWrapper from '../../../components/ScreenWrapper'; import Navigation from '../../../libs/Navigation/Navigation'; import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; +import TextInputFocusable from '../../../components/TextInputFocusable'; import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; import Text from '../../../components/Text'; +import {deleteBankAccount} from '../../../libs/actions/BankAccounts'; import getPaymentMethods from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; -import {PayPal, Bank} from '../../../components/Icon/Expensicons'; +import {PayPal, Bank, CreditCard} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; import getClickedElementLocation from '../../../libs/getClickedElementLocation'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; @@ -67,28 +69,13 @@ class PaymentsPage extends React.Component { * @param {String} account */ paymentMethodPressed(nativeEvent, accountType, account) { - if (account) { - if (account === PAYPAL) { - Navigation.navigate(ROUTES.SETTINGS_ADD_PAYPAL_ME); - } - } else { - const position = getClickedElementLocation(nativeEvent); - this.setState({ - shouldShowAddPaymentMenu: true, - anchorPositionTop: position.bottom, - - // We want the position to be 20px to the right of the left border - anchorPositionLeft: position.left + 20, - }); - } - const position = getClickedElementLocation(nativeEvent); if (accountType) { let formattedSelectedPaymentMethod; if (accountType === PAYPAL) { formattedSelectedPaymentMethod = { title: 'PayPal.me', - icon: Bank, + icon: PayPal, }; } else if (accountType === 'bankAccount') { formattedSelectedPaymentMethod = { @@ -98,7 +85,7 @@ class PaymentsPage extends React.Component { } else { formattedSelectedPaymentMethod = { title: account.cardName, - icon: Bank, + icon: CreditCard, }; } this.setState({ @@ -111,6 +98,14 @@ class PaymentsPage extends React.Component { anchorPositionLeft: position.left + 20, formattedSelectedPaymentMethod, }); + } else { + this.setState({ + shouldShowAddPaymentMenu: true, + anchorPositionTop: position.bottom, + + // We want the position to be 20px to the right of the left border + anchorPositionLeft: position.left + 20, + }); } } @@ -225,6 +220,41 @@ class PaymentsPage extends React.Component { + + + Please enter your password + + this.setState(password)} + /> + deleteBankAccount(this.state.selectedPaymentMethod, this.state.password)} + style={[ + styles.button, + styles.buttonDanger, + styles.mh2, + styles.mv2, + styles.defaultOrDeleteButton, + ]} + > + + {this.props.translate('common.delete')} + + + ); From 3600ee6117ccec2ef7e16e7ebe26ce4dd2e131d6 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Mon, 9 Aug 2021 12:07:47 -0600 Subject: [PATCH 003/101] Add ability to delete account and add scaffold for default --- src/libs/API.js | 9 ++++++++ src/libs/actions/BankAccounts.js | 9 ++++++++ src/pages/settings/Payments/PaymentsPage.js | 23 +++++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/libs/API.js b/src/libs/API.js index 8a3c56b505e3..abb9a0eddf1f 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -973,6 +973,14 @@ function BankAccount_SetupWithdrawal(parameters) { ); } +function DeleteBankAccount(parameters) { + const commandName = 'DeleteBankAccount'; + requireParameters(['bankAccountID', 'password'], parameters, commandName); + return Network.post( + commandName, {bankAccountID: parameters.bankAccountID, password: parameters.password}, + ); +} + /** * @param {Object} parameters * @param {String[]} data @@ -1135,4 +1143,5 @@ export { Policy_Create, Policy_Employees_Remove, PreferredLocale_Update, + DeleteBankAccount, }; diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index b3f016ac3ab4..485790008577 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -10,6 +10,7 @@ import BankAccount from '../models/BankAccount'; import promiseAllSettled from '../promiseAllSettled'; import Growl from '../Growl'; import {translateLocal} from '../translate'; +import {DeleteBankAccount} from '../API'; /** * List of bank accounts. This data should not be stored in Onyx since it contains unmasked PANs. @@ -739,6 +740,13 @@ function hideExistingOwnersError() { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {error: '', existingOwnersList: ''}); } +function deleteBankAccount(bankAccountID, password) { + API.DeleteBankAccount({bankAccountID, password}) + .then((response) => { + console.log(response); + }); +} + export { activateWallet, addPersonalBankAccount, @@ -752,4 +760,5 @@ export { setupWithdrawalAccount, validateBankAccount, hideExistingOwnersError, + deleteBankAccount, }; diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 0b831bf4c474..a970ce4bc671 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -40,6 +40,7 @@ class PaymentsPage extends React.Component { this.state = { shouldShowAddPaymentMenu: false, shouldShowDefaultDeleteMenu: false, + shouldShowPasswordPrompt: false, selectedPaymentMethod: {}, formattedSelectedPaymentMethod: {}, anchorPositionTop: 0, @@ -53,6 +54,7 @@ class PaymentsPage extends React.Component { this.hideDefaultDeleteMenu = this.hideDefaultDeleteMenu.bind(this); this.makeDefaultPaymentMethod = this.makeDefaultPaymentMethod.bind(this); this.deletePaymentMethod = this.deletePaymentMethod.bind(this); + this.hidePasswordPrompt = this.hidePasswordPrompt.bind(this); } componentDidMount() { @@ -136,12 +138,33 @@ class PaymentsPage extends React.Component { this.setState({shouldShowDefaultDeleteMenu: false}); } + hidePasswordPrompt() { + this.setState({shouldShowPasswordPrompt: false}); + } + makeDefaultPaymentMethod() { + if (this.state.selectedPaymentMethodType === 'PayPal.me') { + + } else if (this.state.selectedPaymentMethodType === 'bankAccount') { + + } else if (this.state.selectedPaymentMethodType === 'card') { + } } deletePaymentMethod() { + if (this.state.selectedPaymentMethodType === 'PayPal.me') { + NameValuePair.set(CONST.NVP.PAYPAL_ME_ADDRESS, null); + } else if (this.state.selectedPaymentMethodType === 'bankAccount') { + this.setState({shouldShowDefaultDeleteMenu: false, shouldShowPasswordPrompt: true}); + } else if (this.state.selectedPaymentMethodType === 'card') { + + } + } + deleteBankAccount(password) { + debugger; + deleteBankAccount(this.state.selectedPaymentMethod, password); } render() { From b41716b9762e6a1c074d51735c39c802d9ece68d Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Mon, 9 Aug 2021 17:56:46 -0600 Subject: [PATCH 004/101] Correctly set password --- src/pages/settings/Payments/PaymentsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index a970ce4bc671..f2d34fb2344e 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -261,7 +261,7 @@ class PaymentsPage extends React.Component { this.setState(password)} + onChangeText={password => this.setState({password})} /> deleteBankAccount(this.state.selectedPaymentMethod, this.state.password)} From 182a825b489b56b75f0fb1ce2d044426cb1eb123 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 12 Aug 2021 11:31:21 -0600 Subject: [PATCH 005/101] Move everything into a view to style easier --- src/pages/settings/Payments/PaymentsPage.js | 60 +++++++++++---------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index f2d34fb2344e..c271c80de5db 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -162,11 +162,6 @@ class PaymentsPage extends React.Component { } } - deleteBankAccount(password) { - debugger; - deleteBankAccount(this.state.selectedPaymentMethod, password); - } - render() { return ( @@ -251,32 +246,39 @@ class PaymentsPage extends React.Component { left: this.state.anchorPositionLeft, }} > - - Please enter your password - - this.setState({password})} - /> - deleteBankAccount(this.state.selectedPaymentMethod, this.state.password)} - style={[ - styles.button, - styles.buttonDanger, - styles.mh2, - styles.mv2, - styles.defaultOrDeleteButton, - ]} + - - {this.props.translate('common.delete')} + + Please enter your password - + this.setState({password})} + /> + deleteBankAccount(this.state.selectedPaymentMethod, this.state.password)} + style={[ + styles.button, + styles.buttonDanger, + styles.mv2, + styles.defaultOrDeleteButton, + ]} + > + + {this.props.translate('common.delete')} + + + From 6fbaf8d1a28e1a938ed699ba3f3ba32c1104681d Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 18:37:33 -0600 Subject: [PATCH 006/101] Add new method for setting default wallet --- src/libs/API.js | 14 ++++++++++++++ src/libs/actions/PaymentMethods.js | 13 ++++++++++++- src/pages/settings/Payments/AddPayPalMePage.js | 2 +- src/pages/settings/Payments/PaymentsPage.js | 2 +- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libs/API.js b/src/libs/API.js index 627b05f28ab1..b4f8f8c061d5 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -721,6 +721,19 @@ function SetPassword(parameters) { return Network.post(commandName, parameters); } +/** + * @param {Object} parameters + * @param {String} parameters.password + * @param {String|null} parameters.bankAccountID + * @param {String|null} parameters.fundID + * @returns {Promise} + */ +function SetWalletLinkedAccount(parameters) { + const commandName = 'SetWalletLinkedAccount'; + requireParameters(['password'], parameters, SetWalletLinkedAccount); + return Network.post(commandName, parameters); +} + /** * @param {Object} parameters * @param {String} parameters.subscribed @@ -1121,6 +1134,7 @@ export { ResetPassword, SetNameValuePair, SetPassword, + SetWalletLinkedAccount, UpdateAccount, UpdatePolicy, User_SignUp, diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 4647a4bc9998..adfa1b0f3f04 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -28,4 +28,15 @@ function getPaymentMethods() { }); } -export default getPaymentMethods; +function setWalletLinkedAccount(password, bankAccountID, fundID) { + return API.SetWalletLinkedAccount({ + password, + bankAccountID, + fundID, + }); +} + +export { + getPaymentMethods, + setWalletLinkedAccount, +}; diff --git a/src/pages/settings/Payments/AddPayPalMePage.js b/src/pages/settings/Payments/AddPayPalMePage.js index 65cd22071df2..58905d2d6e8d 100644 --- a/src/pages/settings/Payments/AddPayPalMePage.js +++ b/src/pages/settings/Payments/AddPayPalMePage.js @@ -9,7 +9,7 @@ import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; import Text from '../../../components/Text'; import ScreenWrapper from '../../../components/ScreenWrapper'; import NameValuePair from '../../../libs/actions/NameValuePair'; -import getPaymentMethods from '../../../libs/actions/PaymentMethods'; +import {getPaymentMethods} from '../../../libs/actions/PaymentMethods'; import Navigation from '../../../libs/Navigation/Navigation'; import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index c5601d47af8f..5711d71b2dcd 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -14,7 +14,7 @@ import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; import Text from '../../../components/Text'; import {deleteBankAccount} from '../../../libs/actions/BankAccounts'; -import getPaymentMethods from '../../../libs/actions/PaymentMethods'; +import {getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; import {PayPal, Bank, CreditCard} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; From 101d7650c76809cbd117ae71e0edc962b1cf933c Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 18:37:56 -0600 Subject: [PATCH 007/101] Send the whole payment method rather than just the id --- src/pages/settings/Payments/PaymentMethodList.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index 8d8fae891882..43bcfc0babb4 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -96,7 +96,7 @@ class PaymentMethodList extends Component { description: formattedBankAccountNumber, icon, iconSize, - onPress: e => this.props.onPress(e, 'bankAccount', bankAccount.bankAccountID), + onPress: e => this.props.onPress(e, 'bankAccount', bankAccount), key: `bankAccount-${bankAccount.bankAccountID}`, }); } @@ -116,7 +116,7 @@ class PaymentMethodList extends Component { description: formattedCardNumber, icon, iconSize, - onPress: e => this.props.onPress(e, 'card', card.cardID), + onPress: e => this.props.onPress(e, 'card', card), key: `card-${card.cardID}`, }); } From a2331bfc48b6e642c15ee722063ba324914cdb6b Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 18:38:36 -0600 Subject: [PATCH 008/101] Update password component to call either default or delete --- src/pages/settings/Payments/PaymentsPage.js | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 5711d71b2dcd..ebdc34c18733 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -150,12 +150,10 @@ class PaymentsPage extends React.Component { } makeDefaultPaymentMethod() { - if (this.state.selectedPaymentMethodType === 'PayPal.me') { - - } else if (this.state.selectedPaymentMethodType === 'bankAccount') { - + if (this.state.selectedPaymentMethodType === 'bankAccount') { + setWalletLinkedAccount(this.state.password, this.state.selectedPaymentMethod.bankAccountID, null); } else if (this.state.selectedPaymentMethodType === 'card') { - + setWalletLinkedAccount(this.state.password, null, this.state.selectedPaymentMethod.managedBy); } } @@ -225,7 +223,13 @@ class PaymentsPage extends React.Component { /> )} { + this.setState({ + shouldShowPasswordPrompt: true, + shouldShowDefaultDeleteMenu: false, + passwordFormCallback: this.makeDefaultPaymentMethod, + }); + }} style={[styles.button, styles.mh2, styles.mt2, styles.defaultOrDeleteButton]} > @@ -275,7 +279,10 @@ class PaymentsPage extends React.Component { onChangeText={password => this.setState({password})} /> deleteBankAccount(this.state.selectedPaymentMethod, this.state.password)} + onPress={() => { + this.hidePasswordPrompt(); + this.state.passwordFormCallback(); + }} style={[ styles.button, styles.buttonDanger, From 6bc3cf331ef32dcbf8b65dc4ed99ab93f4bea4e0 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 18:39:44 -0600 Subject: [PATCH 009/101] Add ability to delete bank accounts --- src/pages/settings/Payments/PaymentsPage.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index ebdc34c18733..95d6ba6b52ec 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -161,7 +161,7 @@ class PaymentsPage extends React.Component { if (this.state.selectedPaymentMethodType === 'PayPal.me') { NameValuePair.set(CONST.NVP.PAYPAL_ME_ADDRESS, null); } else if (this.state.selectedPaymentMethodType === 'bankAccount') { - this.setState({shouldShowDefaultDeleteMenu: false, shouldShowPasswordPrompt: true}); + deleteBankAccount(this.state.password, this.state.selectedPaymentMethod.bankAccountID); } else if (this.state.selectedPaymentMethodType === 'card') { } @@ -237,7 +237,13 @@ class PaymentsPage extends React.Component { { + this.setState({ + shouldShowPasswordPrompt: true, + shouldShowDefaultDeleteMenu: false, + passwordFormCallback: this.deletePaymentMethod, + }); + }} style={[ styles.button, styles.buttonDanger, From a09a55aad126acff4af11794602fb764eeb9327b Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 19:01:30 -0600 Subject: [PATCH 010/101] Add ability to delete cards --- src/libs/API.js | 13 +++++++++++++ src/libs/actions/PaymentMethods.js | 5 +++++ src/pages/settings/Payments/PaymentsPage.js | 4 ++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/src/libs/API.js b/src/libs/API.js index b4f8f8c061d5..069eca0032f8 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -394,6 +394,18 @@ function CreateLogin(parameters) { return Network.post(commandName, parameters); } +/** + * @param {Object} parameters + * @param {Number} parameters.cardID + * @returns {Promise} + * @constructor + */ +function DeleteCard(parameters) { + const commandName = 'DeleteCard'; + requireParameters(['cardID'], parameters, commandName); + return Network.post(commandName, parameters); +} + /** * @param {Object} parameters * @param {String} parameters.partnerUserID @@ -1104,6 +1116,7 @@ export { ChangePassword, CreateChatReport, CreateLogin, + DeleteCard, DeleteLogin, Get, GetAccountStatus, diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index adfa1b0f3f04..674fc6909d06 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -4,6 +4,10 @@ import ONYXKEYS from '../../ONYXKEYS'; import * as API from '../API'; import CONST from '../../CONST'; +function deleteCard(cardID) { + return API.DeleteCard(cardID); +} + /** * Calls the API to get the user's bankAccountList, cardList, wallet, and payPalMe * @@ -37,6 +41,7 @@ function setWalletLinkedAccount(password, bankAccountID, fundID) { } export { + deleteCard, getPaymentMethods, setWalletLinkedAccount, }; diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 95d6ba6b52ec..3c46df20442e 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -14,7 +14,7 @@ import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; import Text from '../../../components/Text'; import {deleteBankAccount} from '../../../libs/actions/BankAccounts'; -import {getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; +import {deleteCard, getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; import {PayPal, Bank, CreditCard} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; @@ -163,7 +163,7 @@ class PaymentsPage extends React.Component { } else if (this.state.selectedPaymentMethodType === 'bankAccount') { deleteBankAccount(this.state.password, this.state.selectedPaymentMethod.bankAccountID); } else if (this.state.selectedPaymentMethodType === 'card') { - + deleteCard(this.state.selectedPaymentMethod.cardID); } } From ca180ae907b37876d62c22aa9392f4333784a997 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 19:27:28 -0600 Subject: [PATCH 011/101] Add autofocus and hide input since it's a password --- src/pages/settings/Payments/PaymentsPage.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 3c46df20442e..ad3ccd8f4394 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -283,6 +283,8 @@ class PaymentsPage extends React.Component { styles.w100, ]} onChangeText={password => this.setState({password})} + autoFocus + secureTextEntry /> { From 386a97cffd9cbe072e15cadc1193c01cb5c8622e Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 20:57:07 -0600 Subject: [PATCH 012/101] Move password popover to its own component --- src/components/PasswordPopover.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 src/components/PasswordPopover.js diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js new file mode 100644 index 000000000000..e69de29bb2d1 From 43b5d124d679985edba5fe1c185c271d0b4a95b2 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 21:10:58 -0600 Subject: [PATCH 013/101] Move password popover to its own component --- src/components/PasswordPopover.js | 96 +++++++++++++++++++++ src/pages/settings/Payments/PaymentsPage.js | 48 ++--------- 2 files changed, 102 insertions(+), 42 deletions(-) diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js index e69de29bb2d1..24a05801a9a9 100644 --- a/src/components/PasswordPopover.js +++ b/src/components/PasswordPopover.js @@ -0,0 +1,96 @@ +import {TouchableOpacity, View} from 'react-native'; +import React, {Component} from 'react'; +import PropTypes from 'prop-types'; +import styles from '../styles/styles'; +import Text from './Text'; +import TextInputFocusable from './TextInputFocusable'; +import Popover from './Popover'; + +const propTypes = { + /** Is the popover currently showing? */ + isVisible: PropTypes.bool.isRequired, + + /** Function that gets called when the user closes the modal */ + onClose: PropTypes.func.isRequired, + + /** Where the popover should be placed */ + anchorPosition: PropTypes.shape({ + top: PropTypes.number, + left: PropTypes.number, + }).isRequired, + + /** Function that gets called when the user clicks the delete / make default button */ + onSubmit: PropTypes.func, + + /** The text that should be displayed in the submit button */ + submitButtonText: PropTypes.string, + + /** Is the reason for the password dangerous. This will change the button style to red */ + isDangerousAction: PropTypes.bool, +}; + +const defaultProps = { + onSubmit: () => {}, + submitButtonText: '', + isDangerousAction: false, +}; + +class PasswordPopover extends Component { + constructor(props) { + super(props); + + this.state = { + password: '', + }; + } + + render() { + return ( + + + + Please enter your password + + this.setState({password})} + autoFocus + secureTextEntry + /> + this.props.onSubmit(this.state.password)} + style={[ + styles.button, + styles.mv2, + styles.defaultOrDeleteButton, + this.props.isDangerousAction && styles.buttonDanger, + ]} + > + + {this.props.submitButtonText} + + + + + ); + } +} + +PasswordPopover.propTypes = propTypes; +PasswordPopover.defaultProps = defaultProps; +export default PasswordPopover; diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index ad3ccd8f4394..54555fd99dfd 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -5,11 +5,11 @@ import PropTypes from 'prop-types'; import PaymentMethodList from './PaymentMethodList'; import ROUTES from '../../../ROUTES'; import HeaderWithCloseButton from '../../../components/HeaderWithCloseButton'; +import PasswordPopover from '../../../components/PasswordPopover'; import ScreenWrapper from '../../../components/ScreenWrapper'; import Navigation from '../../../libs/Navigation/Navigation'; import styles from '../../../styles/styles'; import withLocalize, {withLocalizePropTypes} from '../../../components/withLocalize'; -import TextInputFocusable from '../../../components/TextInputFocusable'; import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; import Text from '../../../components/Text'; @@ -257,53 +257,17 @@ class PaymentsPage extends React.Component { - - - - Please enter your password - - this.setState({password})} - autoFocus - secureTextEntry - /> - { - this.hidePasswordPrompt(); - this.state.passwordFormCallback(); - }} - style={[ - styles.button, - styles.buttonDanger, - styles.mv2, - styles.defaultOrDeleteButton, - ]} - > - - {this.props.translate('common.delete')} - - - - + onSubmit={this.callPasswordCallbackAndHidePopover} + submitButtonText={this.state.passwordButtonText} + isDangerousAction={this.state.isDangerousAction} + /> ); From 5bd68557e928f7a31e455409af8613031326f103 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 21:11:44 -0600 Subject: [PATCH 014/101] Convert the rest of the file to work with the new password popover --- src/pages/settings/Payments/PaymentsPage.js | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 54555fd99dfd..13e5f61e9de3 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -62,6 +62,7 @@ class PaymentsPage extends React.Component { this.makeDefaultPaymentMethod = this.makeDefaultPaymentMethod.bind(this); this.deletePaymentMethod = this.deletePaymentMethod.bind(this); this.hidePasswordPrompt = this.hidePasswordPrompt.bind(this); + this.callPasswordCallbackAndHidePopover = this.callPasswordCallbackAndHidePopover.bind(this); } componentDidMount() { @@ -149,19 +150,24 @@ class PaymentsPage extends React.Component { this.setState({shouldShowPasswordPrompt: false}); } - makeDefaultPaymentMethod() { + callPasswordCallbackAndHidePopover(password) { + this.hidePasswordPrompt(); + this.state.passwordFormCallback(password); + } + + makeDefaultPaymentMethod(password) { if (this.state.selectedPaymentMethodType === 'bankAccount') { - setWalletLinkedAccount(this.state.password, this.state.selectedPaymentMethod.bankAccountID, null); + setWalletLinkedAccount(password, this.state.selectedPaymentMethod.bankAccountID, null); } else if (this.state.selectedPaymentMethodType === 'card') { - setWalletLinkedAccount(this.state.password, null, this.state.selectedPaymentMethod.managedBy); + setWalletLinkedAccount(password, null, this.state.selectedPaymentMethod.managedBy); } } - deletePaymentMethod() { + deletePaymentMethod(password) { if (this.state.selectedPaymentMethodType === 'PayPal.me') { NameValuePair.set(CONST.NVP.PAYPAL_ME_ADDRESS, null); } else if (this.state.selectedPaymentMethodType === 'bankAccount') { - deleteBankAccount(this.state.password, this.state.selectedPaymentMethod.bankAccountID); + deleteBankAccount(password, this.state.selectedPaymentMethod.bankAccountID); } else if (this.state.selectedPaymentMethodType === 'card') { deleteCard(this.state.selectedPaymentMethod.cardID); } @@ -227,6 +233,8 @@ class PaymentsPage extends React.Component { this.setState({ shouldShowPasswordPrompt: true, shouldShowDefaultDeleteMenu: false, + passwordButtonText: 'Make Default Payment Method', + isDangerousAction: false, passwordFormCallback: this.makeDefaultPaymentMethod, }); }} @@ -241,6 +249,8 @@ class PaymentsPage extends React.Component { this.setState({ shouldShowPasswordPrompt: true, shouldShowDefaultDeleteMenu: false, + passwordButtonText: this.props.translate('common.delete'), + isDangerousAction: true, passwordFormCallback: this.deletePaymentMethod, }); }} From d1769160a2756899ead6f974afec933ec8c4df0c Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 9 Sep 2021 21:48:53 -0600 Subject: [PATCH 015/101] Translate enter password text --- src/components/PasswordPopover.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js index 24a05801a9a9..e95a37d01373 100644 --- a/src/components/PasswordPopover.js +++ b/src/components/PasswordPopover.js @@ -5,6 +5,7 @@ import styles from '../styles/styles'; import Text from './Text'; import TextInputFocusable from './TextInputFocusable'; import Popover from './Popover'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; const propTypes = { /** Is the popover currently showing? */ @@ -27,6 +28,8 @@ const propTypes = { /** Is the reason for the password dangerous. This will change the button style to red */ isDangerousAction: PropTypes.bool, + + ...withLocalizePropTypes, }; const defaultProps = { @@ -60,7 +63,7 @@ class PasswordPopover extends Component { styles.mv2, ]} > - Please enter your password + {this.props.translate('passwordForm.pleaseFillPassword')} Date: Thu, 9 Sep 2021 21:49:10 -0600 Subject: [PATCH 016/101] Make enter work when entering password --- src/components/PasswordPopover.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js index e95a37d01373..e071222c02e9 100644 --- a/src/components/PasswordPopover.js +++ b/src/components/PasswordPopover.js @@ -72,6 +72,7 @@ class PasswordPopover extends Component { styles.w100, ]} onChangeText={password => this.setState({password})} + onSubmitEditing={this.props.onSubmit(this.state.password)} autoFocus secureTextEntry /> From bef952cc7d11e21c56b9890e06cdf639995cba41 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 10 Sep 2021 12:22:34 -0600 Subject: [PATCH 017/101] fix onSubmit call --- src/components/PasswordPopover.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js index e071222c02e9..bd025235068b 100644 --- a/src/components/PasswordPopover.js +++ b/src/components/PasswordPopover.js @@ -72,7 +72,7 @@ class PasswordPopover extends Component { styles.w100, ]} onChangeText={password => this.setState({password})} - onSubmitEditing={this.props.onSubmit(this.state.password)} + onSubmitEditing={() => this.props.onSubmit(this.state.password)} autoFocus secureTextEntry /> From cb1c713ea1129ba4304fe648c5c7beb5977ed73e Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 18:21:10 -0600 Subject: [PATCH 018/101] Style --- src/libs/actions/BankAccounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index ff8d3378071a..110fde38e44e 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -789,7 +789,7 @@ function setWorkspaceIDForReimbursementAccount(workspaceID) { function deleteBankAccount(bankAccountID, password) { API.DeleteBankAccount({ bankAccountID, - password + password, }) .then((response) => { console.log(response); From 150770dc2913fad504f5d36008697ef65a242a77 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 18:48:47 -0600 Subject: [PATCH 019/101] Add default badge --- src/pages/settings/Payments/PaymentMethodList.js | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index 59bd7b948075..c62a83a4afca 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -54,6 +54,14 @@ const propTypes = { cardID: PropTypes.number, })), + userWallet: PropTypes.arrayOf(PropTypes.shape({ + /** The ID of the linked account */ + walletLinkedAccountID: PropTypes.number, + + /** The type of the linked account (debitCard or bankAccount) */ + walletLinkedAccountType: PropTypes.string, + })), + ...withLocalizePropTypes, }; @@ -87,6 +95,7 @@ class PaymentMethodList extends Component { bankAccount.accountNumber.slice(-4) }` : null; + const isDefault = this.props.userWallet.walletLinkedAccountType === 'bankAccount' && this.props.userWallet.walletLinkedAccountID === bankAccount.bankAccountID; const {icon, iconSize} = getBankIcon(bankAccount.additionalData.bankName); combinedPaymentMethods.push({ type: MENU_ITEM, @@ -98,6 +107,7 @@ class PaymentMethodList extends Component { iconSize, onPress: e => this.props.onPress(e, 'bankAccount', bankAccount), key: `bankAccount-${bankAccount.bankAccountID}`, + isDefault }); } }); @@ -106,6 +116,7 @@ class PaymentMethodList extends Component { const formattedCardNumber = card.cardNumber ? `${this.props.translate('paymentMethodList.cardLastFour')} ${card.cardNumber.slice(-4)}` : null; + const isDefault = this.props.userWallet.walletLinkedAccountType === 'debitCard' && this.props.userWallet.walletLinkedAccountID === card.fundID; const {icon, iconSize} = getBankIcon(card.bank, true); combinedPaymentMethods.push({ type: MENU_ITEM, @@ -116,6 +127,7 @@ class PaymentMethodList extends Component { iconSize, onPress: e => this.props.onPress(e, 'card', card), key: `card-${card.cardNumber}`, + isDefault }); }); @@ -169,6 +181,7 @@ class PaymentMethodList extends Component { disabled={item.disabled} iconHeight={item.iconSize} iconWidth={item.iconSize} + badgeText={item.isDefault ? 'Default' : null} /> ); } @@ -207,5 +220,8 @@ export default compose( payPalMeUsername: { key: ONYXKEYS.NVP_PAYPAL_ME_ADDRESS, }, + userWallet: { + key: ONYXKEYS.USER_WALLET, + }, }), )(PaymentMethodList); From ac8f1eb94ea847ea20880a19d7d7c95f8be82443 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 18:50:25 -0600 Subject: [PATCH 020/101] Style and defaults --- src/pages/settings/Payments/PaymentMethodList.js | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index c62a83a4afca..b0e5e2fcc698 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -54,13 +54,13 @@ const propTypes = { cardID: PropTypes.number, })), - userWallet: PropTypes.arrayOf(PropTypes.shape({ + userWallet: PropTypes.shape({ /** The ID of the linked account */ walletLinkedAccountID: PropTypes.number, /** The type of the linked account (debitCard or bankAccount) */ walletLinkedAccountType: PropTypes.string, - })), + }), ...withLocalizePropTypes, }; @@ -69,6 +69,10 @@ const defaultProps = { payPalMeUsername: '', bankAccountList: [], cardList: [], + userWallet: { + walletLinkedAccountID: 0, + walletLinkedAccountType: '', + }, isLoadingPayments: false, }; @@ -107,7 +111,7 @@ class PaymentMethodList extends Component { iconSize, onPress: e => this.props.onPress(e, 'bankAccount', bankAccount), key: `bankAccount-${bankAccount.bankAccountID}`, - isDefault + isDefault, }); } }); @@ -127,7 +131,7 @@ class PaymentMethodList extends Component { iconSize, onPress: e => this.props.onPress(e, 'card', card), key: `card-${card.cardNumber}`, - isDefault + isDefault, }); }); From 11f927874b3244873f3c17ea1c4584e10f3ff5b5 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 19:11:01 -0600 Subject: [PATCH 021/101] Fix the card key --- src/pages/settings/Payments/PaymentsPage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index c0433606d653..6cb15e107ed0 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -164,7 +164,7 @@ class PaymentsPage extends React.Component { if (this.state.selectedPaymentMethodType === 'bankAccount') { setWalletLinkedAccount(password, this.state.selectedPaymentMethod.bankAccountID, null); } else if (this.state.selectedPaymentMethodType === 'card') { - setWalletLinkedAccount(password, null, this.state.selectedPaymentMethod.managedBy); + setWalletLinkedAccount(password, null, this.state.selectedPaymentMethod.fundID); } } From 0c0185493b8703dedaf632dde5c65be5644776c4 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 19:38:38 -0600 Subject: [PATCH 022/101] Update onyx when we finish setting the default --- src/libs/actions/PaymentMethods.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index f8d9bbda2bd3..2ec319ddb335 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -42,7 +42,10 @@ function setWalletLinkedAccount(password, bankAccountID, fundID) { password, bankAccountID, fundID, - }); + }) + .then(() => { + Onyx.merge(ONYXKEYS.USER_WALLET, {walletLinkedAccountID: bankAccountID ? bankAccountID : fundID, walletLinkedAccountType: bankAccountID ? 'bankAccount' : 'debitCard'}); + }); } /** From aa0c6e92573ce18027e4bde5ae730758626c63d2 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 19:38:49 -0600 Subject: [PATCH 023/101] Add growl --- src/libs/actions/PaymentMethods.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 2ec319ddb335..4fd0eafd2741 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -45,6 +45,7 @@ function setWalletLinkedAccount(password, bankAccountID, fundID) { }) .then(() => { Onyx.merge(ONYXKEYS.USER_WALLET, {walletLinkedAccountID: bankAccountID ? bankAccountID : fundID, walletLinkedAccountType: bankAccountID ? 'bankAccount' : 'debitCard'}); + Growl.show('Default set!', CONST.GROWL.SUCCESS, 5000); }); } From 55ff7fd9524e67657b9f001fdcaffd0f1efb13d0 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Fri, 1 Oct 2021 19:44:51 -0600 Subject: [PATCH 024/101] Check jsonCode and add failure growl --- src/languages/en.js | 2 ++ src/languages/es.js | 2 ++ src/libs/actions/PaymentMethods.js | 10 +++++++--- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/languages/en.js b/src/languages/en.js index 15dec0b3fc90..4ad1592467e3 100755 --- a/src/languages/en.js +++ b/src/languages/en.js @@ -307,6 +307,8 @@ export default { }, paymentsPage: { paymentMethodsTitle: 'Payment methods', + setDefaultSuccess: 'Default payment method set!', + setDefaultFailure: 'Failed to set default payment method. Please try again later.', }, paymentMethodList: { addPaymentMethod: 'Add payment method', diff --git a/src/languages/es.js b/src/languages/es.js index baf80af46805..0a8182f27741 100644 --- a/src/languages/es.js +++ b/src/languages/es.js @@ -307,6 +307,8 @@ export default { }, paymentsPage: { paymentMethodsTitle: 'Métodos de pago', + setDefaultSuccess: 'TODO', + setDefaultFailure: 'TODO', }, paymentMethodList: { addPaymentMethod: 'Agrega método de pago', diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 4fd0eafd2741..1d82852dde0d 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -43,9 +43,13 @@ function setWalletLinkedAccount(password, bankAccountID, fundID) { bankAccountID, fundID, }) - .then(() => { - Onyx.merge(ONYXKEYS.USER_WALLET, {walletLinkedAccountID: bankAccountID ? bankAccountID : fundID, walletLinkedAccountType: bankAccountID ? 'bankAccount' : 'debitCard'}); - Growl.show('Default set!', CONST.GROWL.SUCCESS, 5000); + .then((response) => { + if (response.jsonCode === 200) { + Onyx.merge(ONYXKEYS.USER_WALLET, {walletLinkedAccountID: bankAccountID ? bankAccountID : fundID, walletLinkedAccountType: bankAccountID ? 'bankAccount' : 'debitCard'}); + Growl.show(translateLocal('paymentsPage.setDefaultSuccess'), CONST.GROWL.SUCCESS, 5000); + } else { + Growl.show(translateLocal('paymentsPage.setDefaultFailure'), CONST.GROWL.ERROR, 5000); + } }); } From d27815a1445242fe53c717a90d1c76b0d24c0463 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 21 Oct 2021 15:05:56 -0600 Subject: [PATCH 025/101] Remove password requirement for deleting payments --- src/pages/settings/Payments/PaymentsPage.js | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 969fbd7b13cb..10f20add7470 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -169,11 +169,11 @@ class PaymentsPage extends React.Component { } } - deletePaymentMethod(password) { + deletePaymentMethod() { if (this.state.selectedPaymentMethodType === 'PayPal.me') { NameValuePair.set(CONST.NVP.PAYPAL_ME_ADDRESS, null); } else if (this.state.selectedPaymentMethodType === 'bankAccount') { - deleteBankAccount(password, this.state.selectedPaymentMethod.bankAccountID); + deleteBankAccount(this.state.selectedPaymentMethod.bankAccountID); } else if (this.state.selectedPaymentMethodType === 'card') { deleteCard(this.state.selectedPaymentMethod.cardID); } @@ -258,12 +258,9 @@ class PaymentsPage extends React.Component { { this.setState({ - shouldShowPasswordPrompt: true, shouldShowDefaultDeleteMenu: false, - passwordButtonText: this.props.translate('common.delete'), - isDangerousAction: true, - passwordFormCallback: this.deletePaymentMethod, }); + this.deletePaymentMethod(); }} style={[ styles.button, From 4d1c7035d6fd7ceb9a1bfe5f79eba4c1a4a15062 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 21 Oct 2021 15:06:48 -0600 Subject: [PATCH 026/101] Remove password rewquirement from deleteBankAccount --- src/libs/API.js | 4 ++-- src/libs/actions/BankAccounts.js | 3 +-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/libs/API.js b/src/libs/API.js index 2de283d9937d..e0d57fb5a996 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -1019,9 +1019,9 @@ function BankAccount_SetupWithdrawal(parameters) { function DeleteBankAccount(parameters) { const commandName = 'DeleteBankAccount'; - requireParameters(['bankAccountID', 'password'], parameters, commandName); + requireParameters(['bankAccountID'], parameters, commandName); return Network.post( - commandName, {bankAccountID: parameters.bankAccountID, password: parameters.password}, + commandName, {bankAccountID: parameters.bankAccountID}, ); } diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 1344a423042e..b8c3c4357256 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -813,10 +813,9 @@ function setWorkspaceIDForReimbursementAccount(workspaceID) { Onyx.merge(ONYXKEYS.REIMBURSEMENT_ACCOUNT_WORKSPACE_ID, workspaceID); } -function deleteBankAccount(bankAccountID, password) { +function deleteBankAccount(bankAccountID) { API.DeleteBankAccount({ bankAccountID, - password, }) .then((response) => { console.log(response); From 712a49ef5f7a4186e22457e2348deeea36f01d3a Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 21 Oct 2021 16:33:04 -0600 Subject: [PATCH 027/101] Fix credit card import --- src/components/Icon/BankIcons.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Icon/BankIcons.js b/src/components/Icon/BankIcons.js index 048de6e7550c..df16ff8672b3 100644 --- a/src/components/Icon/BankIcons.js +++ b/src/components/Icon/BankIcons.js @@ -1,4 +1,4 @@ -import CreditCard from './Expensicons'; +import {CreditCard} from './Expensicons'; import AmericanExpress from '../../../assets/images/bankicons/american-express.svg'; import BankOfAmerica from '../../../assets/images/bankicons/bank-of-america.svg'; import BB_T from '../../../assets/images/bankicons/bb-t.svg'; From a31a10f26ea2f366b0c8dad10fcd4e12bd9cd294 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 21 Oct 2021 17:35:11 -0600 Subject: [PATCH 028/101] Fix password form styles --- src/components/PasswordPopover.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js index bd025235068b..e5d706c81e3c 100644 --- a/src/components/PasswordPopover.js +++ b/src/components/PasswordPopover.js @@ -61,13 +61,14 @@ class PasswordPopover extends Component { style={[ styles.h1, styles.mv2, + styles.alignSelfCenter, ]} > {this.props.translate('passwordForm.pleaseFillPassword')} Date: Thu, 21 Oct 2021 17:47:53 -0600 Subject: [PATCH 029/101] Style --- src/libs/actions/PaymentMethods.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 95cf234ea146..ac5bd25917f5 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -47,7 +47,7 @@ function setWalletLinkedAccount(password, bankAccountID, fundID) { }) .then((response) => { if (response.jsonCode === 200) { - Onyx.merge(ONYXKEYS.USER_WALLET, {walletLinkedAccountID: bankAccountID ? bankAccountID : fundID, walletLinkedAccountType: bankAccountID ? 'bankAccount' : 'debitCard'}); + Onyx.merge(ONYXKEYS.USER_WALLET, {walletLinkedAccountID: bankAccountID || fundID, walletLinkedAccountType: bankAccountID ? 'bankAccount' : 'debitCard'}); Growl.show(translateLocal('paymentsPage.setDefaultSuccess'), CONST.GROWL.SUCCESS, 5000); } else { Growl.show(translateLocal('paymentsPage.setDefaultFailure'), CONST.GROWL.ERROR, 5000); From 3c45efe3ca7fc1c403aab4e331e9e04a3d1d92ec Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 21 Oct 2021 17:49:13 -0600 Subject: [PATCH 030/101] Remove test log --- src/libs/actions/BankAccounts.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index b8c3c4357256..bf439e55ad29 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -816,10 +816,7 @@ function setWorkspaceIDForReimbursementAccount(workspaceID) { function deleteBankAccount(bankAccountID) { API.DeleteBankAccount({ bankAccountID, - }) - .then((response) => { - console.log(response); - }); + }); } /** From c7ace3b272f7034410640d6d03699d28e0a141bc Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 14:33:57 -0600 Subject: [PATCH 031/101] Call correct API method and rename action function --- src/libs/API.js | 10 +++++----- src/libs/actions/PaymentMethods.js | 6 +++--- src/pages/settings/Payments/PaymentsPage.js | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/libs/API.js b/src/libs/API.js index e0d57fb5a996..4f0adb229217 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -417,13 +417,13 @@ function CreateLogin(parameters) { /** * @param {Object} parameters - * @param {Number} parameters.cardID + * @param {Number} parameters.fundID * @returns {Promise} * @constructor */ -function DeleteCard(parameters) { - const commandName = 'DeleteCard'; - requireParameters(['cardID'], parameters, commandName); +function DeleteFund(parameters) { + const commandName = 'DeleteFund'; + requireParameters(['fundID'], parameters, commandName); return Network.post(commandName, parameters); } @@ -1138,7 +1138,7 @@ export { ChangePassword, CreateChatReport, CreateLogin, - DeleteCard, + DeleteFund, DeleteLogin, Get, GetAccountStatus, diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index ac5bd25917f5..c22d5815e690 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -9,8 +9,8 @@ import {translateLocal} from '../translate'; import Navigation from '../Navigation/Navigation'; import {maskCardNumber} from '../cardUtils'; -function deleteCard(cardID) { - return API.DeleteCard(cardID); +function deleteDebitCard(fundID) { + return API.DeleteFund({fundID}); } /** @@ -99,7 +99,7 @@ function addBillingCard(params) { } export { - deleteCard, + deleteDebitCard, getPaymentMethods, setWalletLinkedAccount, addBillingCard, diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 10f20add7470..0d00f43824a8 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -14,7 +14,7 @@ import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; import Text from '../../../components/Text'; import {deleteBankAccount} from '../../../libs/actions/BankAccounts'; -import {deleteCard, getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; +import {deleteDebitCard, getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; import {PayPal, Bank, CreditCard} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; @@ -175,7 +175,7 @@ class PaymentsPage extends React.Component { } else if (this.state.selectedPaymentMethodType === 'bankAccount') { deleteBankAccount(this.state.selectedPaymentMethod.bankAccountID); } else if (this.state.selectedPaymentMethodType === 'card') { - deleteCard(this.state.selectedPaymentMethod.cardID); + deleteDebitCard(this.state.selectedPaymentMethod.fundID); } } From 296d6cb662c9a45f0801fed183eb44c92540d897 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 15:08:57 -0600 Subject: [PATCH 032/101] Remove duplicate deleteBankAccount --- src/libs/API.js | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/libs/API.js b/src/libs/API.js index 07273d058566..a743b894fbb3 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -1016,14 +1016,6 @@ function BankAccount_SetupWithdrawal(parameters) { ); } -function DeleteBankAccount(parameters) { - const commandName = 'DeleteBankAccount'; - requireParameters(['bankAccountID'], parameters, commandName); - return Network.post( - commandName, {bankAccountID: parameters.bankAccountID}, - ); -} - /** * @param {Object} parameters * @param {Number} parameters.bankAccountID From 4921fa60200c13fa8583bae52549588bde7d92a3 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 15:39:59 -0600 Subject: [PATCH 033/101] Remove duplicate export --- src/libs/API.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libs/API.js b/src/libs/API.js index a743b894fbb3..9f72246fc725 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -1194,5 +1194,4 @@ export { Policy_Create, Policy_Employees_Remove, PreferredLocale_Update, - DeleteBankAccount, }; From 5362000e4884058afb4cc53010961c9a7c5fa4bc Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 17:27:31 -0600 Subject: [PATCH 034/101] Get cards/banks as an object so that we can delete them easily --- src/libs/actions/PaymentMethods.js | 8 ++++++-- src/pages/settings/Payments/PaymentMethodList.js | 4 ++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 9c2ca8337b00..2978ca24d0f1 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -1,3 +1,4 @@ +import _ from 'underscore'; import lodashGet from 'lodash/get'; import Onyx from 'react-native-onyx'; import ONYXKEYS from '../../ONYXKEYS'; @@ -28,11 +29,14 @@ function getPaymentMethods() { excludeNotActivated: true, }) .then((response) => { + // Convert bank accounts/cards from an array of objects, to a map with the bankAccountID as the key + const bankAccounts = _.object(_.map(lodashGet(response, 'bankAccountList', []), bankAccount => [bankAccount.bankAccountID, bankAccount])); + const debitCards = _.object(_.map(lodashGet(response, 'fundList', []), fund => [fund.fundID, fund])); Onyx.multiSet({ [ONYXKEYS.IS_LOADING_PAYMENT_METHODS]: false, [ONYXKEYS.USER_WALLET]: lodashGet(response, 'userWallet', {}), - [ONYXKEYS.BANK_ACCOUNT_LIST]: lodashGet(response, 'bankAccountList', []), - [ONYXKEYS.CARD_LIST]: lodashGet(response, 'fundList', []), + [ONYXKEYS.BANK_ACCOUNT_LIST]: bankAccounts, + [ONYXKEYS.CARD_LIST]: debitCards, [ONYXKEYS.NVP_PAYPAL_ME_ADDRESS]: lodashGet(response, ['nameValuePairs', CONST.NVP.PAYPAL_ME_ADDRESS], ''), }); diff --git a/src/pages/settings/Payments/PaymentMethodList.js b/src/pages/settings/Payments/PaymentMethodList.js index bc9494c98cbe..d6c8593aac37 100644 --- a/src/pages/settings/Payments/PaymentMethodList.js +++ b/src/pages/settings/Payments/PaymentMethodList.js @@ -33,10 +33,10 @@ const propTypes = { payPalMeUsername: PropTypes.string, /** Array of bank account objects */ - bankAccountList: PropTypes.arrayOf(bankAccountPropTypes), + bankAccountList: PropTypes.objectOf(bankAccountPropTypes), /** Array of card objects */ - cardList: PropTypes.arrayOf(PropTypes.shape({ + cardList: PropTypes.objectOf(PropTypes.shape({ /** The name of the institution (bank of america, etc */ cardName: PropTypes.string, From eddab69b07746b86739b9699af9761c200056c04 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 17:54:51 -0600 Subject: [PATCH 035/101] keep types consistent --- src/libs/actions/BankAccounts.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 8bb320279fc5..4e61cbf98f41 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -876,7 +876,7 @@ function resetFreePlanBankAccount() { // Clear reimbursement account, draft user input, and the bank account list Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT, {}); Onyx.set(ONYXKEYS.REIMBURSEMENT_ACCOUNT_DRAFT, null); - Onyx.set(ONYXKEYS.BANK_ACCOUNT_LIST, []); + Onyx.set(ONYXKEYS.BANK_ACCOUNT_LIST, {}); // Clear the NVP for the bank account so the user can add a new one API.SetNameValuePair({name: CONST.NVP.FREE_PLAN_BANK_ACCOUNT_ID, value: ''}); From d5da408abb922af1bfd4da35a103cdf0743c26b8 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 18:48:59 -0600 Subject: [PATCH 036/101] Remove fund from onyx when we delete it --- src/libs/actions/PaymentMethods.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 2978ca24d0f1..c662fcf0d0b4 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -11,7 +11,9 @@ import Navigation from '../Navigation/Navigation'; import {maskCardNumber, getMonthFromExpirationDateString, getYearFromExpirationDateString} from '../CardUtils'; function deleteDebitCard(fundID) { - return API.DeleteFund({fundID}); + return API.DeleteFund({fundID}).then(() => { + Onyx.merge(ONYXKEYS.CARD_LIST, {[fundID]: null}); + }); } /** From db4036fee8f4723e71e67518086f92ae316f5071 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 18:52:43 -0600 Subject: [PATCH 037/101] Delete bank account from onyx after we delete it --- src/libs/actions/BankAccounts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 4e61cbf98f41..02efeeb3c8a7 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -824,6 +824,8 @@ function setWorkspaceIDForReimbursementAccount(workspaceID) { function deleteBankAccount(bankAccountID) { API.DeleteBankAccount({ bankAccountID, + }).then(() => { + Onyx.merge(ONYXKEYS.BANK_ACCOUNT_LIST, {[bankAccountID]: null}); }); } From 12cc3f373cbbfcfc3bcd30566edf457825d07421 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 19:12:14 -0600 Subject: [PATCH 038/101] Don't require ownerEmail, it's an optional param --- src/libs/API.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libs/API.js b/src/libs/API.js index 9f72246fc725..5f79082e58be 100644 --- a/src/libs/API.js +++ b/src/libs/API.js @@ -1024,7 +1024,7 @@ function BankAccount_SetupWithdrawal(parameters) { */ function DeleteBankAccount(parameters) { const commandName = 'DeleteBankAccount'; - requireParameters(['bankAccountID', 'ownerEmail'], parameters, commandName); + requireParameters(['bankAccountID'], parameters, commandName); return Network.post(commandName, parameters); } From fc013a4afce8ba9642e8c8c34faf735370beccb1 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 28 Oct 2021 19:20:06 -0600 Subject: [PATCH 039/101] Only delete from onyx if the call was successful --- src/libs/actions/BankAccounts.js | 6 ++++-- src/libs/actions/PaymentMethods.js | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 02efeeb3c8a7..9f582e93bb67 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -824,8 +824,10 @@ function setWorkspaceIDForReimbursementAccount(workspaceID) { function deleteBankAccount(bankAccountID) { API.DeleteBankAccount({ bankAccountID, - }).then(() => { - Onyx.merge(ONYXKEYS.BANK_ACCOUNT_LIST, {[bankAccountID]: null}); + }).then((response) => { + if (response.jsonCode === 200) { + Onyx.merge(ONYXKEYS.BANK_ACCOUNT_LIST, {[bankAccountID]: null}); + } }); } diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index c662fcf0d0b4..251754b62f91 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -11,8 +11,10 @@ import Navigation from '../Navigation/Navigation'; import {maskCardNumber, getMonthFromExpirationDateString, getYearFromExpirationDateString} from '../CardUtils'; function deleteDebitCard(fundID) { - return API.DeleteFund({fundID}).then(() => { - Onyx.merge(ONYXKEYS.CARD_LIST, {[fundID]: null}); + return API.DeleteFund({fundID}).then((response) => { + if (response.jsonCode === 200) { + Onyx.merge(ONYXKEYS.CARD_LIST, {[fundID]: null}); + } }); } From e85eaf29a12c9373699579ce51c21b0738b8a04f Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Tue, 16 Nov 2021 18:50:22 -0700 Subject: [PATCH 040/101] Fix deleting paypal.me by creating a new method --- src/libs/actions/PaymentMethods.js | 7 +++++++ src/pages/settings/Payments/PaymentsPage.js | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 251754b62f91..43a73cf7ac78 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -9,6 +9,7 @@ import Growl from '../Growl'; import {translateLocal} from '../translate'; import Navigation from '../Navigation/Navigation'; import {maskCardNumber, getMonthFromExpirationDateString, getYearFromExpirationDateString} from '../CardUtils'; +import NameValuePair from './NameValuePair'; function deleteDebitCard(fundID) { return API.DeleteFund({fundID}).then((response) => { @@ -18,6 +19,11 @@ function deleteDebitCard(fundID) { }); } +function deletePayPalMe() { + NameValuePair.set(CONST.NVP.PAYPAL_ME_ADDRESS, ''); + Onyx.merge(ONYXKEYS.NVP_PAYPAL_ME_ADDRESS, null); +} + /** * Calls the API to get the user's bankAccountList, cardList, wallet, and payPalMe * @@ -125,6 +131,7 @@ function clearDebitCardFormErrorAndSubmit() { export { deleteDebitCard, + deletePayPalMe, getPaymentMethods, setWalletLinkedAccount, addBillingCard, diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 91ac761d8b82..9fe39257cb31 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -14,7 +14,7 @@ import compose from '../../../libs/compose'; import KeyboardAvoidingView from '../../../components/KeyboardAvoidingView/index'; import Text from '../../../components/Text'; import {deleteBankAccount} from '../../../libs/actions/BankAccounts'; -import {deleteDebitCard, getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; +import {deleteDebitCard, deletePayPalMe, getPaymentMethods, setWalletLinkedAccount} from '../../../libs/actions/PaymentMethods'; import Popover from '../../../components/Popover'; import {PayPal, Bank, CreditCard} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; @@ -174,8 +174,8 @@ class PaymentsPage extends React.Component { } deletePaymentMethod() { - if (this.state.selectedPaymentMethodType === 'PayPal.me') { - NameValuePair.set(CONST.NVP.PAYPAL_ME_ADDRESS, null); + if (this.state.selectedPaymentMethodType === 'payPalMe') { + deletePayPalMe(); } else if (this.state.selectedPaymentMethodType === 'bankAccount') { deleteBankAccount(this.state.selectedPaymentMethod.bankAccountID); } else if (this.state.selectedPaymentMethodType === 'card') { From 2fad483f9a0aa517b784ac986ec7f105d1597d60 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Tue, 16 Nov 2021 18:50:38 -0700 Subject: [PATCH 041/101] Remove unused imports --- src/pages/settings/Payments/PaymentsPage.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/pages/settings/Payments/PaymentsPage.js b/src/pages/settings/Payments/PaymentsPage.js index 9fe39257cb31..3fbd874e9529 100644 --- a/src/pages/settings/Payments/PaymentsPage.js +++ b/src/pages/settings/Payments/PaymentsPage.js @@ -20,8 +20,6 @@ import {PayPal, Bank, CreditCard} from '../../../components/Icon/Expensicons'; import MenuItem from '../../../components/MenuItem'; import getClickedElementLocation from '../../../libs/getClickedElementLocation'; import withWindowDimensions, {windowDimensionsPropTypes} from '../../../components/withWindowDimensions'; -import NameValuePair from '../../../libs/actions/NameValuePair'; -import CONST from '../../../CONST'; import CurrentWalletBalance from '../../../components/CurrentWalletBalance'; import ONYXKEYS from '../../../ONYXKEYS'; import Permissions from '../../../libs/Permissions'; From e3c7a9e4941606a703e9a8efdbf5e9be610e81b8 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 18 Nov 2021 15:28:39 -0700 Subject: [PATCH 042/101] Add error message for set default failure --- src/libs/actions/PaymentMethods.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index 43a73cf7ac78..d1f895cb7e11 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -66,6 +66,9 @@ function setWalletLinkedAccount(password, bankAccountID, fundID) { } else { Growl.show(translateLocal('paymentsPage.setDefaultFailure'), CONST.GROWL.ERROR, 5000); } + }) + .catch(() => { + Growl.show(translateLocal('paymentsPage.setDefaultFailure'), CONST.GROWL.ERROR, 5000); }); } From dfdf73e95b8af4de4bb1986a0f33f178eb3a9d5c Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 18 Nov 2021 15:34:54 -0700 Subject: [PATCH 043/101] Add error case for deleting a debit card --- src/libs/actions/PaymentMethods.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libs/actions/PaymentMethods.js b/src/libs/actions/PaymentMethods.js index d1f895cb7e11..bbcaf0dec17b 100644 --- a/src/libs/actions/PaymentMethods.js +++ b/src/libs/actions/PaymentMethods.js @@ -12,11 +12,15 @@ import {maskCardNumber, getMonthFromExpirationDateString, getYearFromExpirationD import NameValuePair from './NameValuePair'; function deleteDebitCard(fundID) { - return API.DeleteFund({fundID}).then((response) => { - if (response.jsonCode === 200) { - Onyx.merge(ONYXKEYS.CARD_LIST, {[fundID]: null}); - } - }); + return API.DeleteFund({fundID}) + .then((response) => { + if (response.jsonCode === 200) { + Onyx.merge(ONYXKEYS.CARD_LIST, {[fundID]: null}); + } + }) + .catch(() => { + Growl.show(translateLocal('common.genericErrorMessage'), CONST.GROWL.ERROR, 3000); + }); } function deletePayPalMe() { From 4fba80c4720f6db12aeeaf6d1eafed21c2eb9df8 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 18 Nov 2021 15:43:04 -0700 Subject: [PATCH 044/101] Catch failure to delete bank account --- src/libs/actions/BankAccounts.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libs/actions/BankAccounts.js b/src/libs/actions/BankAccounts.js index 9f582e93bb67..a4069095ccaa 100644 --- a/src/libs/actions/BankAccounts.js +++ b/src/libs/actions/BankAccounts.js @@ -828,6 +828,8 @@ function deleteBankAccount(bankAccountID) { if (response.jsonCode === 200) { Onyx.merge(ONYXKEYS.BANK_ACCOUNT_LIST, {[bankAccountID]: null}); } + }).catch(() => { + Growl.show(translateLocal('common.genericErrorMessage'), CONST.GROWL.ERROR, 3000); }); } From 5fbefc7633dc6ea3bd22468623645c913943a64b Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 18 Nov 2021 16:10:38 -0700 Subject: [PATCH 045/101] Auto focus password input --- src/components/PasswordPopover.js | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/components/PasswordPopover.js b/src/components/PasswordPopover.js index e5d706c81e3c..95b2162c0e9c 100644 --- a/src/components/PasswordPopover.js +++ b/src/components/PasswordPopover.js @@ -42,17 +42,31 @@ class PasswordPopover extends Component { constructor(props) { super(props); + this.passwordInput = undefined; + + this.focusInput = this.focusInput.bind(this); + this.state = { password: '', }; } + /** + * Focus the password input + */ + focusInput() { + if (this.passwordInput) { + this.passwordInput.focus(); + } + } + render() { return ( this.setState({password})} + ref={el => this.passwordInput = el} onSubmitEditing={() => this.props.onSubmit(this.state.password)} autoFocus secureTextEntry From 9c3dffcd08f490ebb1cd9dcf723ecc76ec228372 Mon Sep 17 00:00:00 2001 From: Brandon Stites Date: Thu, 18 Nov 2021 17:57:11 -0700 Subject: [PATCH 046/101] Create new confirm popover component --- src/components/ConfirmPopover.js | 115 +++++++++++++++++++++++++++++++ 1 file changed, 115 insertions(+) create mode 100644 src/components/ConfirmPopover.js diff --git a/src/components/ConfirmPopover.js b/src/components/ConfirmPopover.js new file mode 100644 index 000000000000..2dc59223f242 --- /dev/null +++ b/src/components/ConfirmPopover.js @@ -0,0 +1,115 @@ +import React from 'react'; +import {View} from 'react-native'; +import _ from 'underscore'; +import PropTypes from 'prop-types'; +import Header from './Header'; +import styles from '../styles/styles'; +import Popover from './Popover'; +import CONST from '../CONST'; +import withWindowDimensions, {windowDimensionsPropTypes} from './withWindowDimensions'; +import withLocalize, {withLocalizePropTypes} from './withLocalize'; +import compose from '../libs/compose'; +import Button from './Button'; +import Text from './Text'; + +const propTypes = { + /** Title of the modal */ + title: PropTypes.string.isRequired, + + /** A callback to call when the form has been submitted */ + onConfirm: PropTypes.func.isRequired, + + /** A callback to call when the form has been closed */ + onCancel: PropTypes.func, + + /** Modal visibility */ + isVisible: PropTypes.bool.isRequired, + + /** Confirm button text */ + confirmText: PropTypes.string, + + /** Cancel button text */ + cancelText: PropTypes.string, + + /** Is the action destructive */ + danger: PropTypes.bool, + + /** Whether we should show the cancel button */ + shouldShowCancelButton: PropTypes.bool, + + /** Where the popover should be positioned */ + anchorPosition: PropTypes.shape({ + top: PropTypes.number, + left: PropTypes.number, + }).isRequired, + + ...withLocalizePropTypes, + + ...windowDimensionsPropTypes, +}; + +const defaultProps = { + confirmText: '', + cancelText: '', + danger: false, + onCancel: () => {}, + shouldShowCancelButton: true, +}; + +const ConfirmPopover = props => ( + + + + {props.title} + +