diff --git a/app/_locales/en/messages.json b/app/_locales/en/messages.json index cc087867a..625aaef66 100644 --- a/app/_locales/en/messages.json +++ b/app/_locales/en/messages.json @@ -1208,6 +1208,12 @@ "resetAccountDescription": { "message": "Resetting your account will clear your transaction history." }, + "deleteNetwork": { + "message": "Delete Network?" + }, + "deleteNetworkDescription": { + "message": "Are you sure you want to delete this network?" + }, "restoreFromSeed": { "message": "Restore account?" }, diff --git a/test/e2e/beta/metamask-beta-ui.spec.js b/test/e2e/beta/metamask-beta-ui.spec.js index 7aa386637..e61277c18 100644 --- a/test/e2e/beta/metamask-beta-ui.spec.js +++ b/test/e2e/beta/metamask-beta-ui.spec.js @@ -1522,6 +1522,15 @@ describe('MetaMask', function () { const deleteButton = await findElement(driver, By.css('.btn-danger')) await deleteButton.click() await delay(regularDelayMs) + + const confirmDeleteNetworkModal = await findElement(driver, By.css('span .modal')) + + const byConfirmDeleteNetworkButton = By.css('.button.btn-danger.modal-container__footer-button') + const confirmDeleteNetworkButton = await driver.wait(until.elementLocated(byConfirmDeleteNetworkButton)) + await confirmDeleteNetworkButton.click() + + await driver.wait(until.stalenessOf(confirmDeleteNetworkModal)) + const newNetworkListItems = await findElements(driver, By.css('.networks-tab__networks-list-name')) assert.equal(networkListItems.length - 1, newNetworkListItems.length) diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js new file mode 100644 index 000000000..ea92e340c --- /dev/null +++ b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.component.js @@ -0,0 +1,43 @@ +import React, { PureComponent } from 'react' +import PropTypes from 'prop-types' +import Modal, { ModalContent } from '../../modal' + +export default class ConfirmDeleteNetwork extends PureComponent { + static propTypes = { + hideModal: PropTypes.func.isRequired, + delRpcTarget: PropTypes.func.isRequired, + onConfirm: PropTypes.func.isRequired, + target: PropTypes.string.isRequired, + } + + static contextTypes = { + t: PropTypes.func, + } + + handleDelete = () => { + this.props.delRpcTarget(this.props.target) + .then(() => { + this.props.onConfirm() + this.props.hideModal() + }) + } + + render () { + const { t } = this.context + + return ( + this.props.hideModal()} + submitText={t('delete')} + cancelText={t('cancel')} + submitType="danger" + > + + + ) + } +} diff --git a/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js new file mode 100644 index 000000000..4c9bb279f --- /dev/null +++ b/ui/app/components/app/modals/confirm-delete-network/confirm-delete-network.container.js @@ -0,0 +1,16 @@ +import { connect } from 'react-redux' +import { compose } from 'recompose' +import withModalProps from '../../../../helpers/higher-order-components/with-modal-props' +import ConfirmDeleteNetwork from './confirm-delete-network.component' +import { delRpcTarget } from '../../../../store/actions' + +const mapDispatchToProps = dispatch => { + return { + delRpcTarget: (target) => dispatch(delRpcTarget(target)), + } +} + +export default compose( + withModalProps, + connect(null, mapDispatchToProps) +)(ConfirmDeleteNetwork) diff --git a/ui/app/components/app/modals/confirm-delete-network/index.js b/ui/app/components/app/modals/confirm-delete-network/index.js new file mode 100644 index 000000000..de9543eea --- /dev/null +++ b/ui/app/components/app/modals/confirm-delete-network/index.js @@ -0,0 +1 @@ +export { default } from './confirm-delete-network.container' diff --git a/ui/app/components/app/modals/modal.js b/ui/app/components/app/modals/modal.js index 394367c46..cd8ec0c7d 100644 --- a/ui/app/components/app/modals/modal.js +++ b/ui/app/components/app/modals/modal.js @@ -29,6 +29,7 @@ import MetaMetricsOptInModal from './metametrics-opt-in-modal' import RejectTransactions from './reject-transactions' import ClearApprovedOrigins from './clear-approved-origins' import ConfirmCustomizeGasModal from '../gas-customization/gas-modal-page-container' +import ConfirmDeleteNetwork from './confirm-delete-network' const modalContainerBaseStyle = { transform: 'translate3d(-50%, 0, 0px)', @@ -301,6 +302,19 @@ const MODALS = { }, }, + CONFIRM_DELETE_NETWORK: { + contents: h(ConfirmDeleteNetwork), + mobileModalStyle: { + ...modalContainerMobileStyle, + }, + laptopModalStyle: { + ...modalContainerLaptopStyle, + }, + contentStyle: { + borderRadius: '8px', + }, + }, + NEW_ACCOUNT: { contents: [ h(NewAccountModal, {}, []), diff --git a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js index 388e2665f..0349aa14f 100644 --- a/ui/app/pages/settings/networks-tab/network-form/network-form.component.js +++ b/ui/app/pages/settings/networks-tab/network-form/network-form.component.js @@ -12,7 +12,7 @@ export default class NetworkForm extends PureComponent { static propTypes = { editRpc: PropTypes.func.isRequired, - delRpcTarget: PropTypes.func.isRequired, + showConfirmDeleteNetworkModal: PropTypes.func.isRequired, rpcUrl: PropTypes.string, chainId: PropTypes.string, ticker: PropTypes.string, @@ -131,10 +131,14 @@ export default class NetworkForm extends PureComponent { } onDelete = () => { - const { delRpcTarget, rpcUrl, onClear } = this.props - delRpcTarget(rpcUrl) - this.resetForm() - onClear() + const { showConfirmDeleteNetworkModal, rpcUrl, onClear } = this.props + showConfirmDeleteNetworkModal({ + target: rpcUrl, + onConfirm: () => { + this.resetForm() + onClear() + }, + }) } stateIsUnchanged () { diff --git a/ui/app/pages/settings/networks-tab/networks-tab.component.js b/ui/app/pages/settings/networks-tab/networks-tab.component.js index f6c8443cf..cf634058f 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.component.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.component.js @@ -25,7 +25,7 @@ export default class NetworksTab extends PureComponent { setNetworksTabAddMode: PropTypes.func.isRequired, setRpcTarget: PropTypes.func.isRequired, setSelectedSettingsRpcUrl: PropTypes.func.isRequired, - delRpcTarget: PropTypes.func.isRequired, + showConfirmDeleteNetworkModal: PropTypes.func.isRequired, providerUrl: PropTypes.string, providerType: PropTypes.string, networkDefaultedToProvider: PropTypes.bool, @@ -160,7 +160,7 @@ export default class NetworksTab extends PureComponent { const { t } = this.context const { setRpcTarget, - delRpcTarget, + showConfirmDeleteNetworkModal, setSelectedSettingsRpcUrl, setNetworksTabAddMode, selectedNetwork: { @@ -199,7 +199,7 @@ export default class NetworksTab extends PureComponent { setNetworksTabAddMode(false) setSelectedSettingsRpcUrl(null) }} - delRpcTarget={delRpcTarget} + showConfirmDeleteNetworkModal={showConfirmDeleteNetworkModal} viewOnly={viewOnly} isCurrentRpcTarget={providerUrl === rpcUrl} networksTabIsInAddMode={networksTabIsInAddMode} diff --git a/ui/app/pages/settings/networks-tab/networks-tab.container.js b/ui/app/pages/settings/networks-tab/networks-tab.container.js index 9e1098922..8cc18a4bd 100644 --- a/ui/app/pages/settings/networks-tab/networks-tab.container.js +++ b/ui/app/pages/settings/networks-tab/networks-tab.container.js @@ -8,7 +8,7 @@ import { displayWarning, setNetworksTabAddMode, editRpc, - delRpcTarget, + showModal, } from '../../../store/actions' import { defaultNetworksData } from './networks-tab.constants' const defaultNetworks = defaultNetworksData.map(network => ({ ...network, viewOnly: true })) @@ -64,8 +64,8 @@ const mapDispatchToProps = dispatch => { setRpcTarget: (newRpc, chainId, ticker, nickname, rpcPrefs) => { dispatch(updateAndSetCustomRpc(newRpc, chainId, ticker, nickname, rpcPrefs)) }, - delRpcTarget: (target) => { - dispatch(delRpcTarget(target)) + showConfirmDeleteNetworkModal: ({ target, onConfirm }) => { + return dispatch(showModal({ name: 'CONFIRM_DELETE_NETWORK', target, onConfirm })) }, displayWarning: warning => dispatch(displayWarning(warning)), setNetworksTabAddMode: isInAddMode => dispatch(setNetworksTabAddMode(isInAddMode)), diff --git a/ui/app/store/actions.js b/ui/app/store/actions.js index 3ed82044d..476a77b42 100644 --- a/ui/app/store/actions.js +++ b/ui/app/store/actions.js @@ -2037,12 +2037,16 @@ function setRpcTarget (newRpc, chainId, ticker = 'ETH', nickname) { function delRpcTarget (oldRpc) { return (dispatch) => { log.debug(`background.delRpcTarget: ${oldRpc}`) - background.delCustomRpc(oldRpc, (err) => { - if (err) { - log.error(err) - return dispatch(self.displayWarning('Had a problem removing network!')) - } - dispatch(actions.setSelectedToken()) + return new Promise((resolve, reject) => { + background.delCustomRpc(oldRpc, (err) => { + if (err) { + log.error(err) + dispatch(self.displayWarning('Had a problem removing network!')) + return reject(err) + } + dispatch(actions.setSelectedToken()) + resolve() + }) }) } }