Consolidate connected account alerts (#8802)
* update connected accounts appearance * consolidate account alerts * UnconnectedAccountAlert: use ConnectedAccountsList * move switch account action out of menu in all views Co-authored-by: Mark Stacey <markjstacey@gmail.com>feature/default_network_editable
parent
3f8fa161ca
commit
4dfe4e7463
@ -1 +0,0 @@ |
||||
export { default } from './switch-to-connected-alert' |
@ -1,121 +0,0 @@ |
||||
import React, { useState } from 'react' |
||||
import { useDispatch, useSelector } from 'react-redux' |
||||
|
||||
import { |
||||
ALERT_STATE, |
||||
switchToAccount, |
||||
dismissAlert, |
||||
dismissAndDisableAlert, |
||||
getAlertState, |
||||
} from '../../../../ducks/alerts/switch-to-connected' |
||||
import { getPermittedIdentitiesForCurrentTab } from '../../../../selectors' |
||||
import Popover from '../../../ui/popover' |
||||
import Button from '../../../ui/button' |
||||
import Dropdown from '../../../ui/dropdown' |
||||
import Checkbox from '../../../ui/check-box' |
||||
import Tooltip from '../../../ui/tooltip-v2' |
||||
import { useI18nContext } from '../../../../hooks/useI18nContext' |
||||
|
||||
const { |
||||
ERROR, |
||||
LOADING, |
||||
} = ALERT_STATE |
||||
|
||||
const SwitchToUnconnectedAccountAlert = () => { |
||||
const t = useI18nContext() |
||||
const dispatch = useDispatch() |
||||
const alertState = useSelector(getAlertState) |
||||
const connectedAccounts = useSelector(getPermittedIdentitiesForCurrentTab) |
||||
const [accountToSwitchTo, setAccountToSwitchTo] = useState(connectedAccounts[0].address) |
||||
const [dontShowThisAgain, setDontShowThisAgain] = useState(false) |
||||
|
||||
const onClose = async () => { |
||||
return dontShowThisAgain |
||||
? await dispatch(dismissAndDisableAlert()) |
||||
: dispatch(dismissAlert()) |
||||
} |
||||
|
||||
const options = connectedAccounts.map((account) => { |
||||
return { name: account.name, value: account.address } |
||||
}) |
||||
|
||||
return ( |
||||
<Popover |
||||
contentClassName="switch-to-connected-alert__content" |
||||
footer={( |
||||
<> |
||||
{ |
||||
alertState === ERROR |
||||
? ( |
||||
<div className="switch-to-connected-alert__error"> |
||||
{ t('failureMessage') } |
||||
</div> |
||||
) |
||||
: null |
||||
} |
||||
<div className="switch-to-connected-alert__footer-buttons"> |
||||
<Button |
||||
disabled={alertState === LOADING} |
||||
onClick={onClose} |
||||
type="secondary" |
||||
> |
||||
{ t('dismiss') } |
||||
</Button> |
||||
<Button |
||||
disabled={alertState === LOADING || alertState === ERROR || dontShowThisAgain} |
||||
onClick={() => dispatch(switchToAccount(accountToSwitchTo))} |
||||
type="primary" |
||||
> |
||||
{ t('switchAccounts') } |
||||
</Button> |
||||
</div> |
||||
</> |
||||
)} |
||||
footerClassName="switch-to-connected-alert__footer" |
||||
onClose={onClose} |
||||
subtitle={ |
||||
connectedAccounts.length > 1 |
||||
? t('switchToConnectedAlertMultipleAccountsDescription') |
||||
: t('switchToConnectedAlertSingleAccountDescription', [connectedAccounts[0].name]) |
||||
} |
||||
title={t('notConnected')} |
||||
> |
||||
{ |
||||
connectedAccounts.length > 1 |
||||
? ( |
||||
<Dropdown |
||||
className="switch-to-connected-alert__dropdown" |
||||
title="Switch to account" |
||||
onChange={(address) => setAccountToSwitchTo(address)} |
||||
options={options} |
||||
selectedOption={accountToSwitchTo} |
||||
/> |
||||
) |
||||
: null |
||||
} |
||||
<div className="switch-to-connected-alert__checkbox-wrapper"> |
||||
<Checkbox |
||||
id="switchToConnected_dontShowThisAgain" |
||||
checked={dontShowThisAgain} |
||||
className="switch-to-connected-alert__checkbox" |
||||
onClick={() => setDontShowThisAgain((checked) => !checked)} |
||||
/> |
||||
<label |
||||
className="switch-to-connected-alert__checkbox-label" |
||||
htmlFor="switchToConnected_dontShowThisAgain" |
||||
> |
||||
{ t('dontShowThisAgain') } |
||||
<Tooltip |
||||
position="top" |
||||
title={t('unconnectedAccountAlertDisableTooltip')} |
||||
wrapperClassName="switch-to-connected-alert__checkbox-label-tooltip" |
||||
> |
||||
<i className="fa fa-info-circle" /> |
||||
</Tooltip> |
||||
</label> |
||||
</div> |
||||
</Popover> |
||||
) |
||||
} |
||||
|
||||
export default SwitchToUnconnectedAccountAlert |
@ -1,66 +0,0 @@ |
||||
.switch-to-connected-alert { |
||||
&__footer { |
||||
flex-direction: column; |
||||
|
||||
:only-child { |
||||
margin: 0; |
||||
} |
||||
} |
||||
|
||||
&__footer-buttons { |
||||
display: flex; |
||||
flex-direction: row; |
||||
|
||||
button:first-child { |
||||
margin-right: 24px; |
||||
} |
||||
|
||||
button { |
||||
font-size: 14px; |
||||
line-height: 20px; |
||||
padding: 8px; |
||||
} |
||||
} |
||||
|
||||
&__error { |
||||
margin-bottom: 16px; |
||||
padding: 16px; |
||||
font-size: 14px; |
||||
border: 1px solid #D73A49; |
||||
background: #F8EAE8; |
||||
border-radius: 3px; |
||||
} |
||||
|
||||
&__content { |
||||
align-items: center; |
||||
padding: 0 24px 24px 24px; |
||||
} |
||||
|
||||
&__dropdown { |
||||
background-color: white; |
||||
width: 100%; |
||||
margin-bottom: 24px; |
||||
} |
||||
|
||||
&__checkbox-wrapper { |
||||
display: flex; |
||||
flex-direction: row; |
||||
width: 100%; |
||||
} |
||||
|
||||
&__checkbox { |
||||
margin-right: 8px; |
||||
} |
||||
|
||||
&__checkbox-label { |
||||
font-size: 14px; |
||||
margin-top: auto; |
||||
margin-bottom: auto; |
||||
color: $Grey-500; |
||||
display: flex; |
||||
} |
||||
|
||||
&__checkbox-label-tooltip { |
||||
margin-left: 8px; |
||||
} |
||||
} |
@ -1 +0,0 @@ |
||||
export { default } from './connected-accounts-list-permissions.component' |
@ -0,0 +1 @@ |
||||
export { default } from './connected-accounts-permissions.component' |
@ -0,0 +1,64 @@ |
||||
.connected-accounts-permissions { |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
font-size: 12px; |
||||
line-height: 17px; |
||||
color: $Grey-500; |
||||
|
||||
strong { |
||||
font-weight: bold; |
||||
} |
||||
|
||||
p + p { |
||||
padding-top: 8px; |
||||
} |
||||
|
||||
&__header { |
||||
display: flex; |
||||
flex-direction: row; |
||||
justify-content: space-between; |
||||
align-items: center; |
||||
cursor: pointer; |
||||
|
||||
font-size: 14px; |
||||
line-height: 20px; |
||||
color: #24292E; |
||||
|
||||
button { |
||||
font-size: 16px; |
||||
line-height: 24px; |
||||
|
||||
background: none; |
||||
padding: 0; |
||||
margin-left: 8px; |
||||
} |
||||
} |
||||
|
||||
&__list { |
||||
padding-top: 8px; |
||||
} |
||||
|
||||
&__list-item { |
||||
display: flex; |
||||
|
||||
i { |
||||
display: block; |
||||
padding-right: 8px; |
||||
font-size: 18px; |
||||
color: $Grey-800; |
||||
} |
||||
} |
||||
|
||||
&__list-container { |
||||
max-height: 0px; |
||||
overflow: hidden; |
||||
height: auto; |
||||
transition: max-height 0.8s cubic-bezier(0.4, 0.0, 0.2, 1); |
||||
|
||||
&--expanded { |
||||
// arbitrarily set hard coded value for effect to work |
||||
max-height: 100px; |
||||
} |
||||
} |
||||
} |
@ -1,2 +1 @@ |
||||
export { default as switchToConnected } from './switch-to-connected' |
||||
export { default as unconnectedAccount } from './unconnected-account' |
||||
|
@ -1,111 +0,0 @@ |
||||
import { createSlice } from '@reduxjs/toolkit' |
||||
import { captureException } from '@sentry/browser' |
||||
|
||||
import { ALERT_TYPES } from '../../../../app/scripts/controllers/alert' |
||||
import * as actionConstants from '../../store/actionConstants' |
||||
import { setAlertEnabledness, setSelectedAddress } from '../../store/actions' |
||||
|
||||
// Constants
|
||||
|
||||
export const ALERT_STATE = { |
||||
CLOSED: 'CLOSED', |
||||
ERROR: 'ERROR', |
||||
LOADING: 'LOADING', |
||||
OPEN: 'OPEN', |
||||
} |
||||
|
||||
const name = ALERT_TYPES.switchToConnected |
||||
|
||||
const initialState = { |
||||
state: ALERT_STATE.CLOSED, |
||||
} |
||||
|
||||
// Slice (reducer plus auto-generated actions and action creators)
|
||||
|
||||
const slice = createSlice({ |
||||
name, |
||||
initialState, |
||||
reducers: { |
||||
disableAlertFailed: (state) => { |
||||
state.state = ALERT_STATE.ERROR |
||||
}, |
||||
disableAlertRequested: (state) => { |
||||
state.state = ALERT_STATE.LOADING |
||||
}, |
||||
disableAlertSucceeded: (state) => { |
||||
state.state = ALERT_STATE.CLOSED |
||||
}, |
||||
dismissAlert: (state) => { |
||||
state.state = ALERT_STATE.CLOSED |
||||
}, |
||||
switchAccountFailed: (state) => { |
||||
state.state = ALERT_STATE.ERROR |
||||
}, |
||||
switchAccountRequested: (state) => { |
||||
state.state = ALERT_STATE.LOADING |
||||
}, |
||||
switchAccountSucceeded: (state) => { |
||||
state.state = ALERT_STATE.CLOSED |
||||
}, |
||||
}, |
||||
extraReducers: { |
||||
[actionConstants.SELECTED_ADDRESS_CHANGED]: (state) => { |
||||
// close the alert if the account is switched while it's open
|
||||
if (state.state === ALERT_STATE.OPEN) { |
||||
state.state = ALERT_STATE.CLOSED |
||||
} |
||||
}, |
||||
}, |
||||
}) |
||||
|
||||
const { actions, reducer } = slice |
||||
|
||||
export default reducer |
||||
|
||||
// Selectors
|
||||
|
||||
export const getAlertState = (state) => state[name].state |
||||
|
||||
export const alertIsOpen = (state) => state[name].state !== ALERT_STATE.CLOSED |
||||
|
||||
// Actions / action-creators
|
||||
|
||||
const { |
||||
disableAlertFailed, |
||||
disableAlertRequested, |
||||
disableAlertSucceeded, |
||||
dismissAlert, |
||||
switchAccountFailed, |
||||
switchAccountRequested, |
||||
switchAccountSucceeded, |
||||
} = actions |
||||
|
||||
export { dismissAlert } |
||||
|
||||
export const dismissAndDisableAlert = () => { |
||||
return async (dispatch) => { |
||||
try { |
||||
await dispatch(disableAlertRequested()) |
||||
await dispatch(setAlertEnabledness(name, false)) |
||||
await dispatch(disableAlertSucceeded()) |
||||
} catch (error) { |
||||
console.error(error) |
||||
captureException(error) |
||||
await dispatch(disableAlertFailed()) |
||||
} |
||||
} |
||||
} |
||||
|
||||
export const switchToAccount = (address) => { |
||||
return async (dispatch) => { |
||||
try { |
||||
await dispatch(switchAccountRequested()) |
||||
await dispatch(setSelectedAddress(address)) |
||||
await dispatch(switchAccountSucceeded()) |
||||
} catch (error) { |
||||
console.error(error) |
||||
captureException(error) |
||||
await dispatch(switchAccountFailed()) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue