(Fix) - Remove safe fix (#1744)
* Avoid displaying notification for non updated owner * Remove old selector usage on welcome page * Remove provider props on WelcomeLayout Fix removing safe behaviour * Fix missing undefined property check on cancelThresholdReached * Removes the default safe when removing the safe marked as default * Remove index * Change react import * Fix relative path for relocate url * Adds removeLocalSafe action Uses removeLocalSafe on onRemoveSafeHandler also removes default safe * Refactor SafeListSidebar uses redux-hooks approach * Disabled save button when the owner name input is pristine
This commit is contained in:
parent
09b470187f
commit
f1ffb5d147
|
@ -11,7 +11,7 @@ import ErrorIcon from 'src/assets/icons/error.svg'
|
||||||
import InfoIcon from 'src/assets/icons/info.svg'
|
import InfoIcon from 'src/assets/icons/info.svg'
|
||||||
|
|
||||||
import AppLayout from 'src/components/AppLayout'
|
import AppLayout from 'src/components/AppLayout'
|
||||||
import SafeListSidebarProvider, { SafeListSidebarContext } from 'src/components/SafeListSidebar'
|
import { SafeListSidebar, SafeListSidebarContext } from 'src/components/SafeListSidebar'
|
||||||
import CookiesBanner from 'src/components/CookiesBanner'
|
import CookiesBanner from 'src/components/CookiesBanner'
|
||||||
import Notifier from 'src/components/Notifier'
|
import Notifier from 'src/components/Notifier'
|
||||||
import Backdrop from 'src/components/layout/Backdrop'
|
import Backdrop from 'src/components/layout/Backdrop'
|
||||||
|
@ -159,9 +159,9 @@ const App: React.FC = ({ children }) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const WrapperAppWithSidebar: React.FC = ({ children }) => (
|
const WrapperAppWithSidebar: React.FC = ({ children }) => (
|
||||||
<SafeListSidebarProvider>
|
<SafeListSidebar>
|
||||||
<App>{children}</App>
|
<App>{children}</App>
|
||||||
</SafeListSidebarProvider>
|
</SafeListSidebar>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default WrapperAppWithSidebar
|
export default WrapperAppWithSidebar
|
||||||
|
|
|
@ -6,9 +6,10 @@ import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
import DefaultBadge from './DefaultBadge'
|
import DefaultBadge from './DefaultBadge'
|
||||||
import { SafeRecordProps } from 'src/logic/safe/store/models/safe'
|
import { SafeRecordProps } from 'src/logic/safe/store/models/safe'
|
||||||
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
|
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
|
||||||
import { SetDefaultSafe } from 'src/logic/safe/store/actions/setDefaultSafe'
|
import setDefaultSafe from 'src/logic/safe/store/actions/setDefaultSafe'
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import { getNetworkInfo } from 'src/config'
|
import { getNetworkInfo } from 'src/config'
|
||||||
|
import { useDispatch } from 'react-redux'
|
||||||
|
|
||||||
const StyledButtonLink = styled(ButtonLink)`
|
const StyledButtonLink = styled(ButtonLink)`
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
|
@ -46,14 +47,18 @@ const useStyles = makeStyles({
|
||||||
type Props = {
|
type Props = {
|
||||||
safe: SafeRecordProps
|
safe: SafeRecordProps
|
||||||
defaultSafe: DefaultSafe
|
defaultSafe: DefaultSafe
|
||||||
setDefaultSafe: SetDefaultSafe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const { nativeCoin } = getNetworkInfo()
|
const { nativeCoin } = getNetworkInfo()
|
||||||
|
|
||||||
export const AddressWrapper = (props: Props): React.ReactElement => {
|
export const AddressWrapper = (props: Props): React.ReactElement => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const { safe, defaultSafe, setDefaultSafe } = props
|
const { safe, defaultSafe } = props
|
||||||
|
const dispatch = useDispatch()
|
||||||
|
|
||||||
|
const setDefaultSafeAction = (safeAddress: string) => {
|
||||||
|
dispatch(setDefaultSafe(safeAddress))
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={classes.wrapper}>
|
<div className={classes.wrapper}>
|
||||||
|
@ -68,7 +73,7 @@ export const AddressWrapper = (props: Props): React.ReactElement => {
|
||||||
className="safeListMakeDefaultButton"
|
className="safeListMakeDefaultButton"
|
||||||
textSize="sm"
|
textSize="sm"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setDefaultSafe(safe.address)
|
setDefaultSafeAction(safe.address)
|
||||||
}}
|
}}
|
||||||
color="primary"
|
color="primary"
|
||||||
>
|
>
|
|
@ -6,12 +6,11 @@ import * as React from 'react'
|
||||||
import styled from 'styled-components'
|
import styled from 'styled-components'
|
||||||
import { SafeRecord } from 'src/logic/safe/store/models/safe'
|
import { SafeRecord } from 'src/logic/safe/store/models/safe'
|
||||||
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
|
import { DefaultSafe } from 'src/routes/safe/store/reducer/types/safe'
|
||||||
import { SetDefaultSafe } from 'src/logic/safe/store/actions/setDefaultSafe'
|
|
||||||
import Hairline from 'src/components/layout/Hairline'
|
import Hairline from 'src/components/layout/Hairline'
|
||||||
import Link from 'src/components/layout/Link'
|
import Link from 'src/components/layout/Link'
|
||||||
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
import { SAFELIST_ADDRESS } from 'src/routes/routes'
|
import { SAFELIST_ADDRESS } from 'src/routes/routes'
|
||||||
import { AddressWrapper } from './AddresWrapper'
|
import { AddressWrapper } from 'src/components/SafeListSidebar/SafeList/AddressWrapper'
|
||||||
export const SIDEBAR_SAFELIST_ROW_TESTID = 'SIDEBAR_SAFELIST_ROW_TESTID'
|
export const SIDEBAR_SAFELIST_ROW_TESTID = 'SIDEBAR_SAFELIST_ROW_TESTID'
|
||||||
|
|
||||||
const StyledIcon = styled(Icon)`
|
const StyledIcon = styled(Icon)`
|
||||||
|
@ -46,10 +45,9 @@ type Props = {
|
||||||
defaultSafe: DefaultSafe
|
defaultSafe: DefaultSafe
|
||||||
safes: SafeRecord[]
|
safes: SafeRecord[]
|
||||||
onSafeClick: () => void
|
onSafeClick: () => void
|
||||||
setDefaultSafe: SetDefaultSafe
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe }: Props): React.ReactElement => {
|
export const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes }: Props): React.ReactElement => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -67,7 +65,7 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe
|
||||||
) : (
|
) : (
|
||||||
<div className={classes.noIcon}>placeholder</div>
|
<div className={classes.noIcon}>placeholder</div>
|
||||||
)}
|
)}
|
||||||
<AddressWrapper safe={safe} defaultSafe={defaultSafe} setDefaultSafe={setDefaultSafe} />
|
<AddressWrapper safe={safe} defaultSafe={defaultSafe} />
|
||||||
</ListItem>
|
</ListItem>
|
||||||
</Link>
|
</Link>
|
||||||
<Hairline />
|
<Hairline />
|
||||||
|
@ -76,5 +74,3 @@ const SafeList = ({ currentSafe, defaultSafe, onSafeClick, safes, setDefaultSafe
|
||||||
</MuiList>
|
</MuiList>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default SafeList
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import React, { useEffect, useMemo, useState } from 'react'
|
import React, { useEffect, useMemo, useState, ReactElement } from 'react'
|
||||||
import Drawer from '@material-ui/core/Drawer'
|
import Drawer from '@material-ui/core/Drawer'
|
||||||
import SearchIcon from '@material-ui/icons/Search'
|
import SearchIcon from '@material-ui/icons/Search'
|
||||||
import SearchBar from 'material-ui-search-bar'
|
import SearchBar from 'material-ui-search-bar'
|
||||||
import { connect } from 'react-redux'
|
import { useSelector } from 'react-redux'
|
||||||
|
|
||||||
import SafeList from './SafeList'
|
import { SafeList } from './SafeList'
|
||||||
import { sortedSafeListSelector } from './selectors'
|
import { sortedSafeListSelector } from './selectors'
|
||||||
import useSidebarStyles from './style'
|
import useSidebarStyles from './style'
|
||||||
|
|
||||||
|
@ -15,11 +15,9 @@ import Hairline from 'src/components/layout/Hairline'
|
||||||
import Link from 'src/components/layout/Link'
|
import Link from 'src/components/layout/Link'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
import { WELCOME_ADDRESS } from 'src/routes/routes'
|
import { WELCOME_ADDRESS } from 'src/routes/routes'
|
||||||
import setDefaultSafe from 'src/logic/safe/store/actions/setDefaultSafe'
|
|
||||||
import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics'
|
import { useAnalytics, SAFE_NAVIGATION_EVENT } from 'src/utils/googleAnalytics'
|
||||||
|
|
||||||
import { defaultSafeSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
|
import { defaultSafeSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
|
||||||
import { AppReduxState } from 'src/store'
|
|
||||||
|
|
||||||
export const SafeListSidebarContext = React.createContext({
|
export const SafeListSidebarContext = React.createContext({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
|
@ -34,9 +32,17 @@ const filterBy = (filter, safes) =>
|
||||||
safe.name.toLowerCase().includes(filter.toLowerCase()),
|
safe.name.toLowerCase().includes(filter.toLowerCase()),
|
||||||
)
|
)
|
||||||
|
|
||||||
const SafeListSidebar = ({ children, currentSafe, defaultSafe, safes, setDefaultSafeAction }) => {
|
type Props = {
|
||||||
|
children: ReactElement
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SafeListSidebar = ({ children }: Props): ReactElement => {
|
||||||
const [isOpen, setIsOpen] = useState(false)
|
const [isOpen, setIsOpen] = useState(false)
|
||||||
const [filter, setFilter] = useState('')
|
const [filter, setFilter] = useState('')
|
||||||
|
const safes = useSelector(sortedSafeListSelector)
|
||||||
|
const defaultSafe = useSelector(defaultSafeSelector)
|
||||||
|
const currentSafe = useSelector(safeParamAddressFromStateSelector)
|
||||||
|
|
||||||
const classes = useSidebarStyles()
|
const classes = useSidebarStyles()
|
||||||
const { trackEvent } = useAnalytics()
|
const { trackEvent } = useAnalytics()
|
||||||
|
|
||||||
|
@ -118,19 +124,9 @@ const SafeListSidebar = ({ children, currentSafe, defaultSafe, safes, setDefault
|
||||||
defaultSafe={defaultSafe}
|
defaultSafe={defaultSafe}
|
||||||
onSafeClick={toggleSidebar}
|
onSafeClick={toggleSidebar}
|
||||||
safes={filteredSafes}
|
safes={filteredSafes}
|
||||||
setDefaultSafe={setDefaultSafeAction}
|
|
||||||
/>
|
/>
|
||||||
</Drawer>
|
</Drawer>
|
||||||
{children}
|
{children}
|
||||||
</SafeListSidebarContext.Provider>
|
</SafeListSidebarContext.Provider>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default connect(
|
|
||||||
(state: AppReduxState) => ({
|
|
||||||
safes: sortedSafeListSelector(state),
|
|
||||||
defaultSafe: defaultSafeSelector(state),
|
|
||||||
currentSafe: safeParamAddressFromStateSelector(state),
|
|
||||||
}),
|
|
||||||
{ setDefaultSafeAction: setDefaultSafe },
|
|
||||||
)(SafeListSidebar)
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Action, Dispatch } from 'redux'
|
||||||
|
import { loadStoredSafes } from 'src/logic/safe/utils'
|
||||||
|
import removeSafe from 'src/logic/safe/store/actions/removeSafe'
|
||||||
|
|
||||||
|
export const removeLocalSafe = (safeAddress: string) => async (dispatch: Dispatch): Promise<Action | void> => {
|
||||||
|
const storedSafes = await loadStoredSafes()
|
||||||
|
if (storedSafes) {
|
||||||
|
delete storedSafes[safeAddress]
|
||||||
|
}
|
||||||
|
dispatch(removeSafe(safeAddress))
|
||||||
|
}
|
|
@ -126,7 +126,14 @@ export default handleActions(
|
||||||
[REMOVE_SAFE]: (state: SafeReducerMap, action) => {
|
[REMOVE_SAFE]: (state: SafeReducerMap, action) => {
|
||||||
const safeAddress = action.payload
|
const safeAddress = action.payload
|
||||||
|
|
||||||
return state.deleteIn(['safes', safeAddress])
|
const currentDefaultSafe = state.get('defaultSafe')
|
||||||
|
|
||||||
|
let newState = state.deleteIn(['safes', safeAddress])
|
||||||
|
if (sameAddress(safeAddress, currentDefaultSafe)) {
|
||||||
|
newState = newState.set('defaultSafe', DEFAULT_SAFE_INITIAL_STATE)
|
||||||
|
}
|
||||||
|
|
||||||
|
return newState
|
||||||
},
|
},
|
||||||
[ADD_SAFE_OWNER]: (state: SafeReducerMap, action) => {
|
[ADD_SAFE_OWNER]: (state: SafeReducerMap, action) => {
|
||||||
const { ownerAddress, ownerName, safeAddress } = action.payload
|
const { ownerAddress, ownerName, safeAddress } = action.payload
|
||||||
|
|
|
@ -17,7 +17,7 @@ import {
|
||||||
getOwnerAddressBy,
|
getOwnerAddressBy,
|
||||||
getOwnerNameBy,
|
getOwnerNameBy,
|
||||||
} from 'src/routes/open/components/fields'
|
} from 'src/routes/open/components/fields'
|
||||||
import Welcome from 'src/routes/welcome/components/Layout'
|
import { WelcomeLayout } from 'src/routes/welcome/components/index'
|
||||||
import { history } from 'src/store'
|
import { history } from 'src/store'
|
||||||
import { secondary, sm } from 'src/theme/variables'
|
import { secondary, sm } from 'src/theme/variables'
|
||||||
import { networkSelector, providerNameSelector, userAccountSelector } from 'src/logic/wallets/store/selectors'
|
import { networkSelector, providerNameSelector, userAccountSelector } from 'src/logic/wallets/store/selectors'
|
||||||
|
@ -138,7 +138,7 @@ export const Layout = (props: LayoutProps): React.ReactElement => {
|
||||||
</Stepper>
|
</Stepper>
|
||||||
</Block>
|
</Block>
|
||||||
) : (
|
) : (
|
||||||
<Welcome isOldMultisigMigration provider={provider} />
|
<WelcomeLayout isOldMultisigMigration />
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
|
|
|
@ -40,17 +40,18 @@ type OwnProps = {
|
||||||
selectedOwnerName: string
|
selectedOwnerName: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const EditOwnerComponent = ({ isOpen, onClose, ownerAddress, selectedOwnerName }: OwnProps): React.ReactElement => {
|
export const EditOwnerModal = ({ isOpen, onClose, ownerAddress, selectedOwnerName }: OwnProps): React.ReactElement => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const safeAddress = useSelector(safeParamAddressFromStateSelector) as string
|
const safeAddress = useSelector(safeParamAddressFromStateSelector)
|
||||||
const handleSubmit = (values) => {
|
|
||||||
const { ownerName } = values
|
|
||||||
|
|
||||||
dispatch(editSafeOwner({ safeAddress, ownerAddress, ownerName }))
|
|
||||||
dispatch(addOrUpdateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName })))
|
|
||||||
dispatch(enqueueSnackbar(NOTIFICATIONS.OWNER_NAME_CHANGE_EXECUTED_MSG))
|
|
||||||
|
|
||||||
|
const handleSubmit = ({ ownerName }: { ownerName: string }): void => {
|
||||||
|
// Update the value only if the ownerName really changed
|
||||||
|
if (ownerName !== selectedOwnerName) {
|
||||||
|
dispatch(editSafeOwner({ safeAddress, ownerAddress, ownerName }))
|
||||||
|
dispatch(addOrUpdateAddressBookEntry(makeAddressBookEntry({ address: ownerAddress, name: ownerName })))
|
||||||
|
dispatch(enqueueSnackbar(NOTIFICATIONS.OWNER_NAME_CHANGE_EXECUTED_MSG))
|
||||||
|
}
|
||||||
onClose()
|
onClose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,54 +72,56 @@ const EditOwnerComponent = ({ isOpen, onClose, ownerAddress, selectedOwnerName }
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</Row>
|
</Row>
|
||||||
<Hairline />
|
<Hairline />
|
||||||
<GnoForm onSubmit={handleSubmit}>
|
<GnoForm onSubmit={handleSubmit} subscription={{ pristine: true }}>
|
||||||
{() => (
|
{(...args) => {
|
||||||
<>
|
const pristine = args[2].pristine
|
||||||
<Block className={classes.container}>
|
return (
|
||||||
<Row margin="md">
|
<>
|
||||||
<Field
|
<Block className={classes.container}>
|
||||||
component={TextField}
|
<Row margin="md">
|
||||||
initialValue={selectedOwnerName}
|
<Field
|
||||||
name="ownerName"
|
component={TextField}
|
||||||
placeholder="Owner name*"
|
initialValue={selectedOwnerName}
|
||||||
testId={RENAME_OWNER_INPUT_TEST_ID}
|
name="ownerName"
|
||||||
text="Owner name*"
|
placeholder="Owner name*"
|
||||||
type="text"
|
testId={RENAME_OWNER_INPUT_TEST_ID}
|
||||||
validate={composeValidators(required, minMaxLength(1, 50))}
|
text="Owner name*"
|
||||||
/>
|
type="text"
|
||||||
|
validate={composeValidators(required, minMaxLength(1, 50))}
|
||||||
|
/>
|
||||||
|
</Row>
|
||||||
|
<Row>
|
||||||
|
<Block justify="center">
|
||||||
|
<Identicon address={ownerAddress} diameter={32} />
|
||||||
|
<Paragraph color="disabled" noMargin size="md" style={{ marginLeft: sm, marginRight: sm }}>
|
||||||
|
{ownerAddress}
|
||||||
|
</Paragraph>
|
||||||
|
<CopyBtn content={ownerAddress} />
|
||||||
|
<ExplorerButton explorerUrl={getExplorerInfo(ownerAddress)} />
|
||||||
|
</Block>
|
||||||
|
</Row>
|
||||||
|
</Block>
|
||||||
|
<Hairline />
|
||||||
|
<Row align="center" className={classes.buttonRow}>
|
||||||
|
<Button minHeight={42} minWidth={140} onClick={onClose}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
minHeight={42}
|
||||||
|
minWidth={140}
|
||||||
|
testId={SAVE_OWNER_CHANGES_BTN_TEST_ID}
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
disabled={pristine}
|
||||||
|
>
|
||||||
|
Save
|
||||||
|
</Button>
|
||||||
</Row>
|
</Row>
|
||||||
<Row>
|
</>
|
||||||
<Block justify="center">
|
)
|
||||||
<Identicon address={ownerAddress} diameter={32} />
|
}}
|
||||||
<Paragraph color="disabled" noMargin size="md" style={{ marginLeft: sm, marginRight: sm }}>
|
|
||||||
{ownerAddress}
|
|
||||||
</Paragraph>
|
|
||||||
<CopyBtn content={ownerAddress} />
|
|
||||||
<ExplorerButton explorerUrl={getExplorerInfo(ownerAddress)} />
|
|
||||||
</Block>
|
|
||||||
</Row>
|
|
||||||
</Block>
|
|
||||||
<Hairline />
|
|
||||||
<Row align="center" className={classes.buttonRow}>
|
|
||||||
<Button minHeight={42} minWidth={140} onClick={onClose}>
|
|
||||||
Cancel
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
color="primary"
|
|
||||||
minHeight={42}
|
|
||||||
minWidth={140}
|
|
||||||
testId={SAVE_OWNER_CHANGES_BTN_TEST_ID}
|
|
||||||
type="submit"
|
|
||||||
variant="contained"
|
|
||||||
>
|
|
||||||
Save
|
|
||||||
</Button>
|
|
||||||
</Row>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</GnoForm>
|
</GnoForm>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default EditOwnerComponent
|
|
||||||
|
|
|
@ -9,7 +9,7 @@ import { List } from 'immutable'
|
||||||
import RemoveOwnerIcon from '../assets/icons/bin.svg'
|
import RemoveOwnerIcon from '../assets/icons/bin.svg'
|
||||||
|
|
||||||
import AddOwnerModal from './AddOwnerModal'
|
import AddOwnerModal from './AddOwnerModal'
|
||||||
import EditOwnerModal from './EditOwnerModal'
|
import { EditOwnerModal } from './EditOwnerModal'
|
||||||
import OwnerAddressTableCell from './OwnerAddressTableCell'
|
import OwnerAddressTableCell from './OwnerAddressTableCell'
|
||||||
import RemoveOwnerModal from './RemoveOwnerModal'
|
import RemoveOwnerModal from './RemoveOwnerModal'
|
||||||
import ReplaceOwnerModal from './ReplaceOwnerModal'
|
import ReplaceOwnerModal from './ReplaceOwnerModal'
|
||||||
|
|
|
@ -18,9 +18,16 @@ import Hairline from 'src/components/layout/Hairline'
|
||||||
import Link from 'src/components/layout/Link'
|
import Link from 'src/components/layout/Link'
|
||||||
import Paragraph from 'src/components/layout/Paragraph'
|
import Paragraph from 'src/components/layout/Paragraph'
|
||||||
import Row from 'src/components/layout/Row'
|
import Row from 'src/components/layout/Row'
|
||||||
import removeSafe from 'src/logic/safe/store/actions/removeSafe'
|
import {
|
||||||
import { safeNameSelector, safeParamAddressFromStateSelector } from 'src/logic/safe/store/selectors'
|
defaultSafeSelector,
|
||||||
|
safeNameSelector,
|
||||||
|
safeParamAddressFromStateSelector,
|
||||||
|
} from 'src/logic/safe/store/selectors'
|
||||||
import { md, secondary } from 'src/theme/variables'
|
import { md, secondary } from 'src/theme/variables'
|
||||||
|
import { WELCOME_ADDRESS } from 'src/routes/routes'
|
||||||
|
import { removeLocalSafe } from 'src/logic/safe/store/actions/removeLocalSafe'
|
||||||
|
import { sameAddress } from 'src/logic/wallets/ethAddresses'
|
||||||
|
import { saveDefaultSafe } from 'src/logic/safe/utils'
|
||||||
|
|
||||||
const openIconStyle = {
|
const openIconStyle = {
|
||||||
height: md,
|
height: md,
|
||||||
|
@ -29,14 +36,33 @@ const openIconStyle = {
|
||||||
|
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
|
|
||||||
const RemoveSafeComponent = ({ isOpen, onClose }) => {
|
type RemoveSafeModalProps = {
|
||||||
|
isOpen: boolean
|
||||||
|
onClose: () => void
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RemoveSafeModal = ({ isOpen, onClose }: RemoveSafeModalProps): React.ReactElement => {
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
const safeAddress = useSelector(safeParamAddressFromStateSelector) as string
|
const safeAddress = useSelector(safeParamAddressFromStateSelector)
|
||||||
const safeName = useSelector(safeNameSelector)
|
const safeName = useSelector(safeNameSelector)
|
||||||
|
const defaultSafe = useSelector(defaultSafeSelector)
|
||||||
const dispatch = useDispatch()
|
const dispatch = useDispatch()
|
||||||
const explorerInfo = getExplorerInfo(safeAddress)
|
const explorerInfo = getExplorerInfo(safeAddress)
|
||||||
const { url } = explorerInfo()
|
const { url } = explorerInfo()
|
||||||
|
|
||||||
|
const onRemoveSafeHandler = async () => {
|
||||||
|
await dispatch(removeLocalSafe(safeAddress))
|
||||||
|
if (sameAddress(safeAddress, defaultSafe)) {
|
||||||
|
await saveDefaultSafe('')
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose()
|
||||||
|
// using native redirect in order to avoid problems in several components
|
||||||
|
// trying to access references of the removed safe.
|
||||||
|
const relativePath = window.location.href.split('/#/')[0]
|
||||||
|
window.location.href = `${relativePath}/#/${WELCOME_ADDRESS}`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Modal
|
<Modal
|
||||||
description="Remove the selected Safe"
|
description="Remove the selected Safe"
|
||||||
|
@ -91,13 +117,7 @@ const RemoveSafeComponent = ({ isOpen, onClose }) => {
|
||||||
<Button
|
<Button
|
||||||
className={classes.buttonRemove}
|
className={classes.buttonRemove}
|
||||||
minWidth={140}
|
minWidth={140}
|
||||||
onClick={() => {
|
onClick={onRemoveSafeHandler}
|
||||||
dispatch(removeSafe(safeAddress))
|
|
||||||
onClose()
|
|
||||||
// using native redirect in order to avoid problems in several components
|
|
||||||
// trying to access references of the removed safe.
|
|
||||||
window.location.href = '/app/'
|
|
||||||
}}
|
|
||||||
type="submit"
|
type="submit"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
>
|
>
|
||||||
|
@ -107,5 +127,3 @@ const RemoveSafeComponent = ({ isOpen, onClose }) => {
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export const RemoveSafeModal = RemoveSafeComponent
|
|
||||||
|
|
|
@ -105,7 +105,7 @@ const ExpandedSafeTx = ({ cancelTx, tx }: ExpandedSafeTxProps): ReactElement =>
|
||||||
|
|
||||||
const thresholdReached = !isIncomingTx && threshold <= tx.confirmations.size
|
const thresholdReached = !isIncomingTx && threshold <= tx.confirmations.size
|
||||||
const canExecute = !isIncomingTx && nonce === tx.nonce
|
const canExecute = !isIncomingTx && nonce === tx.nonce
|
||||||
const cancelThresholdReached = !!cancelTx && threshold <= cancelTx.confirmations.size
|
const cancelThresholdReached = !!cancelTx && threshold <= cancelTx.confirmations?.size
|
||||||
const canExecuteCancel = nonce === tx.nonce
|
const canExecuteCancel = nonce === tx.nonce
|
||||||
|
|
||||||
const openRejectModal = () => {
|
const openRejectModal = () => {
|
||||||
|
|
|
@ -16,6 +16,8 @@ import Link from 'src/components/layout/Link'
|
||||||
import Block from 'src/components/layout/Block'
|
import Block from 'src/components/layout/Block'
|
||||||
import { LOAD_ADDRESS, OPEN_ADDRESS } from 'src/routes/routes'
|
import { LOAD_ADDRESS, OPEN_ADDRESS } from 'src/routes/routes'
|
||||||
import { onConnectButtonClick } from 'src/components/ConnectButton'
|
import { onConnectButtonClick } from 'src/components/ConnectButton'
|
||||||
|
import { useSelector } from 'react-redux'
|
||||||
|
import { providerNameSelector } from 'src/logic/wallets/store/selectors'
|
||||||
|
|
||||||
const Wrapper = styled.div`
|
const Wrapper = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -67,10 +69,10 @@ const StyledButtonLink = styled(ButtonLink)`
|
||||||
|
|
||||||
type Props = {
|
type Props = {
|
||||||
isOldMultisigMigration?: boolean
|
isOldMultisigMigration?: boolean
|
||||||
provider: any
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Welcome = ({ isOldMultisigMigration, provider }: Props): React.ReactElement => {
|
export const WelcomeLayout = ({ isOldMultisigMigration }: Props): React.ReactElement => {
|
||||||
|
const provider = useSelector(providerNameSelector)
|
||||||
return (
|
return (
|
||||||
<Block>
|
<Block>
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
|
@ -125,7 +127,7 @@ const Welcome = ({ isOldMultisigMigration, provider }: Props): React.ReactElemen
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="contained"
|
variant="contained"
|
||||||
onClick={onConnectButtonClick}
|
onClick={onConnectButtonClick}
|
||||||
disabled={provider}
|
disabled={!!provider}
|
||||||
data-testid="connect-btn"
|
data-testid="connect-btn"
|
||||||
>
|
>
|
||||||
<Text size="xl" color="white">
|
<Text size="xl" color="white">
|
||||||
|
@ -187,5 +189,3 @@ const Welcome = ({ isOldMultisigMigration, provider }: Props): React.ReactElemen
|
||||||
</Block>
|
</Block>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default Welcome
|
|
|
@ -1,16 +1,12 @@
|
||||||
import * as React from 'react'
|
import React, { ReactElement } from 'react'
|
||||||
import { connect } from 'react-redux'
|
import { WelcomeLayout } from 'src/routes/welcome/components'
|
||||||
|
|
||||||
import Layout from '../components/Layout'
|
|
||||||
|
|
||||||
import selector from './selector'
|
|
||||||
|
|
||||||
import Page from 'src/components/layout/Page'
|
import Page from 'src/components/layout/Page'
|
||||||
|
|
||||||
const Welcome = ({ provider }) => (
|
const Welcome = (): ReactElement => (
|
||||||
<Page align="center">
|
<Page align="center">
|
||||||
<Layout provider={provider} />
|
<WelcomeLayout />
|
||||||
</Page>
|
</Page>
|
||||||
)
|
)
|
||||||
|
|
||||||
export default connect(selector)(Welcome)
|
export default Welcome
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
import { createStructuredSelector } from 'reselect'
|
|
||||||
|
|
||||||
import { providerNameSelector } from 'src/logic/wallets/store/selectors'
|
|
||||||
|
|
||||||
export default createStructuredSelector({
|
|
||||||
provider: providerNameSelector,
|
|
||||||
})
|
|
Loading…
Reference in New Issue