mirror of
https://github.com/kremalicious/metamask-extension.git
synced 2024-11-22 09:57:02 +01:00
[MMI] Review interactive replacement token flow (#19974)
* Sending showCustodyConfirmLink as a prop and fixing other issues * Upgraded MMI extension monrepo and trying to fix the issue * prevents deeplink from closing * Fixed styles of Custody view and changed the place of it * Fixed CI issues * fixing eslint issues * Update LavaMoat policies * fixing tests * Fixed test * updated snapshots * Improving IRT flow * Fixing everything * Finish fixing all issues * Fixed institutional entity done page styles * Fixing boxes * Fixed issue with checkbox * Fixed tests and styles * Removed duplicated lodash * updated snapshot * Fixing tests * Removed unused test * Fixed snapshot * Fixed snapshot --------- Co-authored-by: Antonio Regadas <antonio.regadas@consensys.net> Co-authored-by: MetaMask Bot <metamaskbot@users.noreply.github.com>
This commit is contained in:
parent
16481268cc
commit
47fe542273
@ -2499,6 +2499,10 @@ export default class MetamaskController extends EventEmitter {
|
||||
this.institutionalFeaturesController.removeAddTokenConnectRequest.bind(
|
||||
this.institutionalFeaturesController,
|
||||
),
|
||||
showInteractiveReplacementTokenBanner:
|
||||
appStateController.showInteractiveReplacementTokenBanner.bind(
|
||||
appStateController,
|
||||
),
|
||||
///: END:ONLY_INCLUDE_IN
|
||||
|
||||
///: BEGIN:ONLY_INCLUDE_IN(snaps)
|
||||
|
@ -44,21 +44,24 @@ exports[`Confirm Remove JWT should render correctly 1`] = `
|
||||
class="box confirm-action-jwt__accounts-list box--flex-direction-row"
|
||||
>
|
||||
<div
|
||||
class="box box--padding-top-4 box--padding-right-7 box--padding-bottom-7 box--padding-left-7 box--flex-direction-row"
|
||||
class="mm-box page-container"
|
||||
>
|
||||
<div
|
||||
class="box custody-account-list box--display-flex box--flex-direction-column box--width-full"
|
||||
class="mm-box page-container__content mm-box--padding-4"
|
||||
>
|
||||
<div
|
||||
class="mm-box custody-account-list mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
|
||||
data-testid="custody-account-list"
|
||||
>
|
||||
<div
|
||||
class="box custody-account-list__item box--display-flex box--flex-direction-row"
|
||||
class="mm-box custody-account-list__item mm-box--display-flex"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--align-items-flex-start"
|
||||
class="mm-box mm-box--display-flex mm-box--align-items-flex-start"
|
||||
data-testid="custody-account-list-item-radio-button"
|
||||
/>
|
||||
<div
|
||||
class="box box--margin-left-2 box--display-flex box--flex-direction-column box--width-full"
|
||||
class="mm-box mm-box--margin-left-2 mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
|
||||
>
|
||||
<label
|
||||
class="box mm-text mm-label mm-label--html-for custody-account-list__item__title mm-text--body-md mm-text--font-weight-medium box--margin-top-2 box--margin-left-2 box--display-flex box--flex-direction-row box--align-items-center box--color-text-default"
|
||||
@ -115,7 +118,7 @@ exports[`Confirm Remove JWT should render correctly 1`] = `
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--justify-content-space-between"
|
||||
class="mm-box mm-box--display-flex mm-box--justify-content-space-between"
|
||||
>
|
||||
<label
|
||||
class="box mm-text mm-label mm-label--html-for mm-text--body-md mm-text--font-weight-medium box--display-flex box--flex-direction-row box--align-items-center box--color-text-default"
|
||||
@ -128,6 +131,7 @@ exports[`Confirm Remove JWT should render correctly 1`] = `
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="modal-container__footer"
|
||||
>
|
||||
|
@ -7,7 +7,7 @@ exports[`CustodyLabels Component should render correctly 1`] = `
|
||||
for="address-index"
|
||||
>
|
||||
<p
|
||||
class="box mm-text custody-label mm-text--h9 mm-text--font-weight-normal mm-text--text-transform-uppercase box--margin-top-1 box--margin-right-1 box--margin-bottom-2 box--padding-top-1 box--padding-right-2 box--padding-bottom-1 box--padding-left-2 box--flex-direction-row box--color-text-muted box--background-color-background-alternative box--rounded-sm"
|
||||
class="box mm-text custody-label mm-text--body-xs mm-text--font-weight-normal mm-text--text-transform-capitalize box--margin-top-1 box--margin-right-1 box--margin-bottom-2 box--padding-top-1 box--padding-right-2 box--padding-bottom-1 box--padding-left-2 box--flex-direction-row box--color-text-default box--background-color-background-alternative box--rounded-sm"
|
||||
>
|
||||
value
|
||||
</p>
|
||||
|
@ -7,7 +7,7 @@ import {
|
||||
TextColor,
|
||||
FontWeight,
|
||||
BorderRadius,
|
||||
TypographyVariant,
|
||||
TextVariant,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
|
||||
const CustodyLabels = (props) => {
|
||||
@ -25,7 +25,7 @@ const CustodyLabels = (props) => {
|
||||
{filteredLabels.map((item) => (
|
||||
<Text
|
||||
key={item.key}
|
||||
textTransform={TextTransform.Uppercase}
|
||||
textTransform={TextTransform.Capitalize}
|
||||
className="custody-label"
|
||||
style={background ? { background } : {}}
|
||||
marginTop={1}
|
||||
@ -36,10 +36,10 @@ const CustodyLabels = (props) => {
|
||||
paddingLeft={2}
|
||||
paddingRight={2}
|
||||
backgroundColor={BackgroundColor.backgroundAlternative}
|
||||
color={TextColor.textMuted}
|
||||
color={TextColor.textDefault}
|
||||
fontWeight={FontWeight.Normal}
|
||||
borderRadius={BorderRadius.SM}
|
||||
variant={TypographyVariant.H9}
|
||||
variant={TextVariant.bodyXs}
|
||||
>
|
||||
{item.value}
|
||||
</Text>
|
||||
|
@ -2,7 +2,7 @@
|
||||
z-index: 1;
|
||||
letter-spacing: 0.5px;
|
||||
white-space: nowrap;
|
||||
max-width: 80px;
|
||||
max-width: 150px;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
display: block;
|
||||
|
@ -1,19 +1,26 @@
|
||||
import React, { useContext } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import Modal from '../../app/modal';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { MetaMetricsContext } from '../../../contexts/metametrics';
|
||||
import { hideModal } from '../../../store/actions';
|
||||
import { getSelectedAddress } from '../../../selectors/selectors';
|
||||
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
|
||||
import { Text } from '../../component-library';
|
||||
import Box from '../../ui/box';
|
||||
import {
|
||||
BLOCK_SIZES,
|
||||
Box,
|
||||
Button,
|
||||
Modal,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalOverlay,
|
||||
Text,
|
||||
} from '../../component-library';
|
||||
|
||||
import {
|
||||
BlockSize,
|
||||
BackgroundColor,
|
||||
DISPLAY,
|
||||
FLEX_WRAP,
|
||||
FLEX_DIRECTION,
|
||||
Display,
|
||||
FlexWrap,
|
||||
FlexDirection,
|
||||
BorderRadius,
|
||||
FontWeight,
|
||||
TextAlign,
|
||||
@ -42,18 +49,36 @@ const InteractiveReplacementTokenModal = () => {
|
||||
const custodian =
|
||||
custodians.find((item) => item.name === custodianName) || {};
|
||||
|
||||
const renderCustodyInfo = () => {
|
||||
let img;
|
||||
const handleSubmit = () => {
|
||||
global.platform.openTab({
|
||||
url,
|
||||
});
|
||||
|
||||
if (custodian.iconUrl) {
|
||||
img = (
|
||||
trackEvent({
|
||||
category: 'MMI',
|
||||
event: 'User clicked refresh token link',
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
dispatch(hideModal());
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal isOpen onClose={handleClose}>
|
||||
<ModalOverlay />
|
||||
<ModalContent>
|
||||
<ModalHeader onClose={handleClose}>
|
||||
{t('custodyRefreshTokenModalTitle')}
|
||||
</ModalHeader>
|
||||
{custodian.iconUrl ? (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
alignItems={AlignItems.center}
|
||||
paddingTop={5}
|
||||
>
|
||||
<Box display={DISPLAY.BLOCK} textAlign={TextAlign.Center}>
|
||||
<Box display={Display.Block} textAlign={TextAlign.Center}>
|
||||
<img
|
||||
src={custodian.iconUrl}
|
||||
width={45}
|
||||
@ -61,26 +86,20 @@ const InteractiveReplacementTokenModal = () => {
|
||||
/>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
} else {
|
||||
img = (
|
||||
<Box display={DISPLAY.BLOCK} textAlign={TextAlign.Center}>
|
||||
) : (
|
||||
<Box display={Display.Block} textAlign={TextAlign.Center}>
|
||||
<Text>{custodian.displayName}</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{img}
|
||||
<Text
|
||||
as="h4"
|
||||
paddingTop={4}
|
||||
textAlign={TextAlign.Center}
|
||||
fontWeight={FontWeight.Bold}
|
||||
)}
|
||||
<Box
|
||||
width={BlockSize.Full}
|
||||
backgroundColor={BackgroundColor.backgroundDefault}
|
||||
display={Display.Flex}
|
||||
flexWrap={FlexWrap.Wrap}
|
||||
flexDirection={FlexDirection.Column}
|
||||
borderRadius={BorderRadius.SM}
|
||||
data-testid="interactive-replacement-token-modal"
|
||||
>
|
||||
{t('custodyRefreshTokenModalTitle')}
|
||||
</Text>
|
||||
<Text
|
||||
as="p"
|
||||
paddingTop={4}
|
||||
@ -100,53 +119,14 @@ const InteractiveReplacementTokenModal = () => {
|
||||
>
|
||||
{t('custodyRefreshTokenModalDescription1')}
|
||||
</Text>
|
||||
<Text
|
||||
as="p"
|
||||
marginTop={4}
|
||||
paddingTop={4}
|
||||
paddingBottom={6}
|
||||
textAlign={TextAlign.Left}
|
||||
>
|
||||
<Text as="p" paddingBottom={6} textAlign={TextAlign.Left}>
|
||||
{t('custodyRefreshTokenModalDescription2')}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const handleSubmit = () => {
|
||||
global.platform.openTab({
|
||||
url,
|
||||
});
|
||||
|
||||
trackEvent({
|
||||
category: 'MMI',
|
||||
event: 'User clicked refresh token link',
|
||||
});
|
||||
};
|
||||
|
||||
const handleClose = () => {
|
||||
dispatch(hideModal());
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
onCancel={handleClose}
|
||||
onClose={handleClose}
|
||||
onSubmit={handleSubmit}
|
||||
submitText={custodian.displayName || 'Custodian'}
|
||||
cancelText={t('cancel')}
|
||||
>
|
||||
<Box
|
||||
width={BLOCK_SIZES.FULL}
|
||||
backgroundColor={BackgroundColor.backgroundDefault}
|
||||
display={DISPLAY.FLEX}
|
||||
flexWrap={FLEX_WRAP.WRAP}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
borderRadius={BorderRadius.SM}
|
||||
data-testid="interactive-replacement-token-modal"
|
||||
>
|
||||
{renderCustodyInfo(custodian)}
|
||||
<Button onClick={handleSubmit}>
|
||||
{custodian.displayName || 'Custodian'}
|
||||
</Button>
|
||||
</Box>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
@ -1,7 +1,5 @@
|
||||
import React from 'react';
|
||||
import sinon from 'sinon';
|
||||
import configureMockStore from 'redux-mock-store';
|
||||
import { fireEvent, waitFor } from '@testing-library/react';
|
||||
import { renderWithProvider } from '../../../../test/lib/render-helpers';
|
||||
import testData from '../../../../.storybook/test-data';
|
||||
import InteractiveReplacementTokenModal from '.';
|
||||
@ -71,21 +69,4 @@ describe('Interactive Replacement Token Modal', function () {
|
||||
expect(getByTestId('interactive-replacement-token-modal')).toBeVisible();
|
||||
expect(getByText('Your custodian session has expired')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('opens new tab on Open Codefi Compliance click', async () => {
|
||||
global.platform = { openTab: sinon.spy() };
|
||||
|
||||
const { container } = renderWithProvider(
|
||||
<InteractiveReplacementTokenModal />,
|
||||
store,
|
||||
);
|
||||
|
||||
const button = container.getElementsByClassName('btn-primary')[0];
|
||||
|
||||
fireEvent.click(button);
|
||||
|
||||
await waitFor(() => {
|
||||
expect(global.platform.openTab.calledOnce).toStrictEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -6,13 +6,14 @@ import { getInteractiveReplacementToken } from '../../../selectors/institutional
|
||||
import { getIsUnlocked } from '../../../ducks/metamask/metamask';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { mmiActionsFactory } from '../../../store/institutional/institution-background';
|
||||
import { showInteractiveReplacementTokenModal } from '../../../store/institutional/institution-actions';
|
||||
import { sha256 } from '../../../../shared/modules/hash.utils';
|
||||
import {
|
||||
Size,
|
||||
IconColor,
|
||||
AlignItems,
|
||||
DISPLAY,
|
||||
BLOCK_SIZES,
|
||||
Display,
|
||||
BlockSize,
|
||||
JustifyContent,
|
||||
TextColor,
|
||||
TextVariant,
|
||||
@ -24,10 +25,9 @@ import {
|
||||
IconSize,
|
||||
ButtonLink,
|
||||
Text,
|
||||
Box,
|
||||
} from '../../component-library';
|
||||
|
||||
import Box from '../../ui/box';
|
||||
|
||||
const InteractiveReplacementTokenNotification = ({ isVisible }) => {
|
||||
const t = useI18nContext();
|
||||
const dispatch = useDispatch();
|
||||
@ -48,10 +48,7 @@ const InteractiveReplacementTokenNotification = ({ isVisible }) => {
|
||||
interactiveReplacementToken &&
|
||||
Boolean(Object.keys(interactiveReplacementToken).length);
|
||||
|
||||
if (!/^Custody/u.test(keyring.type)) {
|
||||
setShowNotification(false);
|
||||
return;
|
||||
} else if (!hasInteractiveReplacementToken) {
|
||||
if (!/^Custody/u.test(keyring.type) || !hasInteractiveReplacementToken) {
|
||||
setShowNotification(false);
|
||||
return;
|
||||
}
|
||||
@ -98,34 +95,35 @@ const InteractiveReplacementTokenNotification = ({ isVisible }) => {
|
||||
|
||||
return showNotification ? (
|
||||
<Box
|
||||
width={BLOCK_SIZES.FULL}
|
||||
display={DISPLAY.FLEX}
|
||||
width={BlockSize.Full}
|
||||
display={Display.Flex}
|
||||
justifyContent={JustifyContent.center}
|
||||
alignItems={AlignItems.center}
|
||||
padding={[1, 2]}
|
||||
backgroundColor={BackgroundColor.backgroundAlternative}
|
||||
marginBottom={1}
|
||||
className="interactive-replacement-token-notification"
|
||||
data-testid="interactive-replacement-token-notification"
|
||||
>
|
||||
<Icon
|
||||
name={IconName.Danger}
|
||||
color={IconColor.errorDefault}
|
||||
size={IconSize.Xl}
|
||||
size={IconSize.Md}
|
||||
/>
|
||||
<Text variant={TextVariant.bodyXs} gap={2} color={TextColor.errorDefault}>
|
||||
<Text variant={TextVariant.bodySm} gap={2} color={TextColor.errorDefault}>
|
||||
{t('custodySessionExpired')}
|
||||
</Text>
|
||||
<Text variant={TextVariant.bodySm}>
|
||||
<ButtonLink
|
||||
data-testid="show-modal"
|
||||
size={Size.auto}
|
||||
size={Size.inherit}
|
||||
marginLeft={1}
|
||||
onClick={() => {
|
||||
dispatch(mmiActions.showInteractiveReplacementTokenModal());
|
||||
dispatch(showInteractiveReplacementTokenModal());
|
||||
}}
|
||||
>
|
||||
{t('learnMore')}
|
||||
{t('learnMoreUpperCase')}
|
||||
</ButtonLink>
|
||||
</Text>
|
||||
</Box>
|
||||
) : null;
|
||||
};
|
||||
|
@ -10,10 +10,6 @@ import InteractiveReplacementTokenNotification from './interactive-replacement-t
|
||||
|
||||
jest.mock('../../../../shared/modules/hash.utils');
|
||||
|
||||
const mockedShowInteractiveReplacementTokenModal = jest
|
||||
.fn()
|
||||
.mockReturnValue({ type: 'TYPE' });
|
||||
|
||||
const mockedGetCustodianToken = jest
|
||||
.fn()
|
||||
.mockReturnValue({ type: 'Custody', payload: 'token' });
|
||||
@ -32,11 +28,15 @@ jest.mock('../../../store/institutional/institution-background', () => ({
|
||||
mmiActionsFactory: () => ({
|
||||
getCustodianToken: mockedGetCustodianToken,
|
||||
getAllCustodianAccountsWithToken: mockedGetAllCustodianAccountsWithToken,
|
||||
showInteractiveReplacementTokenModal:
|
||||
mockedShowInteractiveReplacementTokenModal,
|
||||
}),
|
||||
}));
|
||||
|
||||
jest.mock('../../../store/institutional/institution-actions', () => ({
|
||||
showInteractiveReplacementTokenModal: jest
|
||||
.fn()
|
||||
.mockReturnValue({ type: 'TYPE' }),
|
||||
}));
|
||||
|
||||
describe('Interactive Replacement Token Notification', () => {
|
||||
const selectedAddress = '0xca8f1F0245530118D0cf14a06b01Daf8f76Cf281';
|
||||
|
||||
@ -112,8 +112,6 @@ describe('Interactive Replacement Token Notification', () => {
|
||||
await act(async () => {
|
||||
fireEvent.click(screen.getByTestId('show-modal'));
|
||||
});
|
||||
|
||||
expect(mockedShowInteractiveReplacementTokenModal).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should render and call showNotification when component starts', async () => {
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React, { useContext, useState } from 'react';
|
||||
import React, { useContext, useEffect, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { isEqual } from 'lodash';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import isEqual from 'lodash/isEqual';
|
||||
import PulseLoader from '../../../components/ui/pulse-loader';
|
||||
import { CUSTODY_ACCOUNT_ROUTE } from '../../../helpers/constants/routes';
|
||||
import {
|
||||
@ -47,8 +47,14 @@ const ConfirmAddCustodianToken = () => {
|
||||
|
||||
const connectRequest = connectRequests ? connectRequests[0] : undefined;
|
||||
|
||||
useEffect(() => {
|
||||
if (!connectRequest) {
|
||||
history.push(mostRecentOverviewPage);
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [connectRequest, history, mostRecentOverviewPage]);
|
||||
|
||||
if (!connectRequest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -3,28 +3,30 @@
|
||||
exports[`CustodyAccountList renders accounts 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="box box--padding-top-4 box--padding-right-7 box--padding-bottom-7 box--padding-left-7 box--flex-direction-row"
|
||||
class="mm-box page-container"
|
||||
>
|
||||
<div
|
||||
class="box custody-account-list box--display-flex box--flex-direction-column box--width-full"
|
||||
class="mm-box page-container__content mm-box--padding-4"
|
||||
>
|
||||
<div
|
||||
class="mm-box custody-account-list mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
|
||||
data-testid="custody-account-list"
|
||||
>
|
||||
<div
|
||||
class="box custody-account-list__item box--display-flex box--flex-direction-row"
|
||||
class="mm-box custody-account-list__item mm-box--display-flex"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--align-items-flex-start"
|
||||
class="mm-box mm-box--display-flex mm-box--align-items-flex-start"
|
||||
data-testid="custody-account-list-item-radio-button"
|
||||
>
|
||||
<input
|
||||
id="address-0"
|
||||
name="selectedAccount"
|
||||
type="checkbox"
|
||||
value="0x1234567890123456789012345678901234567890"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-left-2 box--display-flex box--flex-direction-column box--width-full"
|
||||
class="mm-box mm-box--margin-left-2 mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
|
||||
>
|
||||
<label
|
||||
class="box mm-text mm-label mm-label--html-for custody-account-list__item__title mm-text--body-md mm-text--font-weight-medium box--margin-top-2 box--margin-left-2 box--display-flex box--flex-direction-row box--align-items-center box--color-text-default"
|
||||
@ -81,26 +83,25 @@ exports[`CustodyAccountList renders accounts 1`] = `
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--justify-content-space-between"
|
||||
class="mm-box mm-box--display-flex mm-box--justify-content-space-between"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box custody-account-list__item box--display-flex box--flex-direction-row"
|
||||
class="mm-box custody-account-list__item mm-box--display-flex"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--align-items-flex-start"
|
||||
class="mm-box mm-box--display-flex mm-box--align-items-flex-start"
|
||||
data-testid="custody-account-list-item-radio-button"
|
||||
>
|
||||
<input
|
||||
id="address-1"
|
||||
name="selectedAccount"
|
||||
type="checkbox"
|
||||
value="0x0987654321098765432109876543210987654321"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
class="box box--margin-left-2 box--display-flex box--flex-direction-column box--width-full"
|
||||
class="mm-box mm-box--margin-left-2 mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
|
||||
>
|
||||
<label
|
||||
class="box mm-text mm-label mm-label--html-for custody-account-list__item__title mm-text--body-md mm-text--font-weight-medium box--margin-top-2 box--margin-left-2 box--display-flex box--flex-direction-row box--align-items-center box--color-text-default"
|
||||
@ -157,32 +158,33 @@ exports[`CustodyAccountList renders accounts 1`] = `
|
||||
</span>
|
||||
</label>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-row box--justify-content-space-between"
|
||||
class="mm-box mm-box--display-flex mm-box--justify-content-space-between"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<footer
|
||||
class="mm-box page-container__footer mm-box--padding-4"
|
||||
>
|
||||
<div
|
||||
class="box custody-account-list__buttons box--padding-top-5 box--padding-right-7 box--padding-bottom-7 box--padding-left-7 box--display-flex box--flex-direction-row box--justify-content-space-between box--width-full"
|
||||
class="mm-box mm-box--display-flex mm-box--gap-4"
|
||||
>
|
||||
<button
|
||||
class="button btn--rounded btn-default btn--large custody-account-list__button"
|
||||
class="box mm-text mm-button-base mm-button-base--size-lg mm-button-base--block custody-account-list__button mm-button-secondary mm-text--body-md-medium box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent box--rounded-pill box--border-color-primary-default box--border-style-solid box--border-width-1"
|
||||
data-testid="custody-account-cancel-button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
[cancel]
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary btn--large custody-account-list__button"
|
||||
class="box mm-text mm-button-base mm-button-base--size-lg mm-button-base--disabled mm-button-base--block custody-account-list__button mm-button-primary mm-button-primary--disabled mm-text--body-md-medium box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-inverse box--background-color-primary-default box--rounded-pill"
|
||||
data-testid="custody-account-connect-button"
|
||||
disabled=""
|
||||
role="button"
|
||||
tabindex="0"
|
||||
>
|
||||
[connect]
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -1,6 +1,5 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import Button from '../../../components/ui/button';
|
||||
import CustodyLabels from '../../../components/institutional/custody-labels';
|
||||
import { SWAPS_CHAINID_DEFAULT_BLOCK_EXPLORER_URL_MAP } from '../../../../shared/constants/swaps';
|
||||
import { CHAIN_IDS } from '../../../../shared/constants/network';
|
||||
@ -9,19 +8,24 @@ import Tooltip from '../../../components/ui/tooltip';
|
||||
import {
|
||||
TextVariant,
|
||||
JustifyContent,
|
||||
BLOCK_SIZES,
|
||||
DISPLAY,
|
||||
BlockSize,
|
||||
Display,
|
||||
IconColor,
|
||||
FlexDirection,
|
||||
AlignItems,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import Box from '../../../components/ui/box';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
Text,
|
||||
Label,
|
||||
Icon,
|
||||
IconName,
|
||||
IconSize,
|
||||
ButtonLink,
|
||||
BUTTON_VARIANT,
|
||||
BUTTON_SIZES,
|
||||
} from '../../../components/component-library';
|
||||
import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard';
|
||||
|
||||
@ -34,7 +38,7 @@ export default function CustodyAccountList({
|
||||
rawList,
|
||||
accounts,
|
||||
onAccountChange,
|
||||
selectedAccounts = {},
|
||||
selectedAccounts,
|
||||
onCancel,
|
||||
onAddAccounts,
|
||||
custody,
|
||||
@ -42,27 +46,28 @@ export default function CustodyAccountList({
|
||||
const t = useI18nContext();
|
||||
const [copied, handleCopy] = useCopyToClipboard();
|
||||
const tooltipText = copied ? t('copiedExclamation') : t('copyToClipboard');
|
||||
const disabled = Object.keys(selectedAccounts).length === 0;
|
||||
const disabled =
|
||||
!selectedAccounts || Object.keys(selectedAccounts).length === 0;
|
||||
|
||||
return (
|
||||
<>
|
||||
<Box paddingTop={4} paddingRight={7} paddingBottom={7} paddingLeft={7}>
|
||||
<Box className="page-container">
|
||||
<Box padding={4} className="page-container__content">
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={['column']}
|
||||
width={BLOCK_SIZES.FULL}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
width={BlockSize.Full}
|
||||
className="custody-account-list"
|
||||
data-testid="custody-account-list"
|
||||
>
|
||||
{accounts.map((account, idx) => (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
className="custody-account-list__item"
|
||||
key={account.address}
|
||||
>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
alignItems={['flex-start']}
|
||||
display={Display.Flex}
|
||||
alignItems={AlignItems.flexStart}
|
||||
data-testid="custody-account-list-item-radio-button"
|
||||
>
|
||||
{!rawList && (
|
||||
@ -70,30 +75,27 @@ export default function CustodyAccountList({
|
||||
type="checkbox"
|
||||
name="selectedAccount"
|
||||
id={`address-${idx}`}
|
||||
value={account.address}
|
||||
onChange={(e) =>
|
||||
onChange={() =>
|
||||
onAccountChange({
|
||||
name: account.name,
|
||||
address: e.target.value,
|
||||
address: account.address,
|
||||
custodianDetails: account.custodianDetails,
|
||||
labels: account.labels,
|
||||
chainId: account.chainId,
|
||||
})
|
||||
}
|
||||
checked={
|
||||
selectedAccounts && selectedAccounts[account.address]
|
||||
}
|
||||
checked={selectedAccounts[account.address] || false}
|
||||
/>
|
||||
)}
|
||||
</Box>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={['column']}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
marginLeft={2}
|
||||
width={BLOCK_SIZES.FULL}
|
||||
width={BlockSize.Full}
|
||||
>
|
||||
<Label
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
marginTop={2}
|
||||
marginLeft={2}
|
||||
htmlFor={`address-${idx}`}
|
||||
@ -110,7 +112,7 @@ export default function CustodyAccountList({
|
||||
</Text>
|
||||
</Label>
|
||||
<Label
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
size={TextVariant.bodySm}
|
||||
marginTop={2}
|
||||
marginLeft={2}
|
||||
@ -120,7 +122,7 @@ export default function CustodyAccountList({
|
||||
<Text
|
||||
as="span"
|
||||
variant={TextVariant.bodyMd}
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
className="custody-account-list__item"
|
||||
>
|
||||
<ButtonLink
|
||||
@ -155,7 +157,7 @@ export default function CustodyAccountList({
|
||||
</Text>
|
||||
</Label>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
>
|
||||
{account.labels && (
|
||||
@ -172,20 +174,13 @@ export default function CustodyAccountList({
|
||||
</Box>
|
||||
</Box>
|
||||
{!rawList && (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
width={BLOCK_SIZES.FULL}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
paddingTop={5}
|
||||
paddingRight={7}
|
||||
paddingBottom={7}
|
||||
paddingLeft={7}
|
||||
className="custody-account-list__buttons"
|
||||
>
|
||||
<Box as="footer" className="page-container__footer" padding={4}>
|
||||
<Box display={Display.Flex} gap={4}>
|
||||
<Button
|
||||
data-testid="custody-account-cancel-button"
|
||||
type="default"
|
||||
large
|
||||
block
|
||||
variant={BUTTON_VARIANT.SECONDARY}
|
||||
size={BUTTON_SIZES.LG}
|
||||
className="custody-account-list__button"
|
||||
onClick={onCancel}
|
||||
>
|
||||
@ -193,8 +188,9 @@ export default function CustodyAccountList({
|
||||
</Button>
|
||||
<Button
|
||||
data-testid="custody-account-connect-button"
|
||||
type="primary"
|
||||
large
|
||||
block
|
||||
variant={BUTTON_VARIANT.PRIMARY}
|
||||
size={BUTTON_SIZES.LG}
|
||||
className="custody-account-list__button"
|
||||
disabled={disabled}
|
||||
onClick={() => onAddAccounts(custody)}
|
||||
@ -202,8 +198,9 @@ export default function CustodyAccountList({
|
||||
{t('connect')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
)}
|
||||
</>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -485,13 +485,9 @@ const CustodyPage = () => {
|
||||
)}
|
||||
{accounts && accounts.length > 0 && (
|
||||
<>
|
||||
<Box
|
||||
borderColor={BorderColor.borderDefault}
|
||||
padding={[5, 7, 2]}
|
||||
width={BlockSize.Full}
|
||||
>
|
||||
<Box padding={[5, 7, 2]} width={BlockSize.Full}>
|
||||
<Text as="h4">{t('selectAnAccount')}</Text>
|
||||
<Text marginTop={2} marginBottom={5}>
|
||||
<Text marginTop={2} marginBottom={2}>
|
||||
{t('selectAnAccountHelp')}
|
||||
</Text>
|
||||
</Box>
|
||||
@ -518,10 +514,13 @@ const CustodyPage = () => {
|
||||
custody={selectedCustodianName}
|
||||
accounts={accounts}
|
||||
onAccountChange={(account) => {
|
||||
if (selectedAccounts[account.address]) {
|
||||
delete selectedAccounts[account.address];
|
||||
setSelectedAccounts((prevSelectedAccounts) => {
|
||||
const updatedSelectedAccounts = { ...prevSelectedAccounts };
|
||||
|
||||
if (updatedSelectedAccounts[account.address]) {
|
||||
delete updatedSelectedAccounts[account.address];
|
||||
} else {
|
||||
selectedAccounts[account.address] = {
|
||||
updatedSelectedAccounts[account.address] = {
|
||||
name: account.name,
|
||||
custodianDetails: account.custodianDetails,
|
||||
labels: account.labels,
|
||||
@ -533,7 +532,8 @@ const CustodyPage = () => {
|
||||
};
|
||||
}
|
||||
|
||||
setSelectedAccounts(selectedAccounts);
|
||||
return updatedSelectedAccounts;
|
||||
});
|
||||
}}
|
||||
selectedAccounts={selectedAccounts}
|
||||
onAddAccounts={async () => {
|
||||
@ -599,10 +599,11 @@ const CustodyPage = () => {
|
||||
</>
|
||||
)}
|
||||
{accounts && accounts.length === 0 && (
|
||||
<>
|
||||
<Box
|
||||
data-testid="custody-accounts-empty"
|
||||
padding={[6, 7, 2]}
|
||||
className="custody-accounts-empty"
|
||||
className="page-container__content"
|
||||
>
|
||||
<Text
|
||||
marginBottom={2}
|
||||
@ -615,12 +616,8 @@ const CustodyPage = () => {
|
||||
<Text variant={TextVariant.bodyMd}>
|
||||
{t('allCustodianAccountsConnectedSubtitle')}
|
||||
</Text>
|
||||
|
||||
<Box
|
||||
padding={[5, 7]}
|
||||
width={BlockSize.Full}
|
||||
className="custody-accounts-empty__footer"
|
||||
>
|
||||
</Box>
|
||||
<Box as="footer" className="page-container__footer" padding={4}>
|
||||
<Button
|
||||
block
|
||||
size={BUTTON_SIZES.LG}
|
||||
@ -630,7 +627,7 @@ const CustodyPage = () => {
|
||||
{t('close')}
|
||||
</Button>
|
||||
</Box>
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
|
@ -1,10 +0,0 @@
|
||||
.custody-accounts-empty {
|
||||
min-height: 300px;
|
||||
|
||||
&__footer {
|
||||
border-top: 1px solid var(--color-border-muted);
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
}
|
||||
}
|
@ -1,16 +1,22 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { useSelector } from 'react-redux';
|
||||
import Button from '../../../components/ui/button';
|
||||
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
||||
import { useI18nContext } from '../../../hooks/useI18nContext';
|
||||
import { Text } from '../../../components/component-library';
|
||||
import {
|
||||
Text,
|
||||
Box,
|
||||
Button,
|
||||
BUTTON_VARIANT,
|
||||
} from '../../../components/component-library';
|
||||
import {
|
||||
TextColor,
|
||||
BorderRadius,
|
||||
TypographyVariant,
|
||||
Display,
|
||||
FlexDirection,
|
||||
AlignItems,
|
||||
TextAlign,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import Box from '../../../components/ui/box';
|
||||
|
||||
export default function InstitutionalEntityDonePage(props) {
|
||||
const mostRecentOverviewPage = useSelector(getMostRecentOverviewPage);
|
||||
@ -19,7 +25,7 @@ export default function InstitutionalEntityDonePage(props) {
|
||||
const { state } = location;
|
||||
|
||||
return (
|
||||
<Box borderRadius={BorderRadius.none}>
|
||||
<Box className="page-container">
|
||||
<Box className="page-container__content">
|
||||
<Box
|
||||
paddingBottom={6}
|
||||
@ -28,15 +34,17 @@ export default function InstitutionalEntityDonePage(props) {
|
||||
className="institutional-entity-done__form"
|
||||
>
|
||||
<Box
|
||||
display={['flex']}
|
||||
flexDirection={['column']}
|
||||
alignItems={['center']}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
alignItems={AlignItems.center}
|
||||
>
|
||||
{state.imgSrc && (
|
||||
<img
|
||||
className="institutional-entity-done__img"
|
||||
src={state.imgSrc}
|
||||
alt="Entity image"
|
||||
/>
|
||||
)}
|
||||
<Text
|
||||
as="h4"
|
||||
marginTop={4}
|
||||
@ -51,23 +59,24 @@ export default function InstitutionalEntityDonePage(props) {
|
||||
marginTop={2}
|
||||
marginBottom={5}
|
||||
variant={TypographyVariant.headingSm}
|
||||
textAlign={TextAlign.Center}
|
||||
>
|
||||
{state.description}
|
||||
</Text>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
<Box className="page-container__footer">
|
||||
<footer>
|
||||
<Box as="footer" className="page-container__footer" padding={4}>
|
||||
<Box display={Display.Flex} gap={4}>
|
||||
<Button
|
||||
type="primary"
|
||||
large
|
||||
block
|
||||
variant={BUTTON_VARIANT.PRIMARY}
|
||||
data-testid="click-most-recent-overview-page"
|
||||
onClick={() => history.push(mostRecentOverviewPage)}
|
||||
>
|
||||
<Text>{t('close')}</Text>
|
||||
{t('close')}
|
||||
</Button>
|
||||
</footer>
|
||||
</Box>
|
||||
</Box>
|
||||
</Box>
|
||||
);
|
||||
|
@ -3,42 +3,41 @@
|
||||
exports[`Interactive Replacement Token Page should reject if there are errors 1`] = `
|
||||
<div>
|
||||
<div
|
||||
class="box page-container box--flex-direction-row"
|
||||
class="mm-box page-container"
|
||||
data-testid="interactive-replacement-token"
|
||||
>
|
||||
<div
|
||||
class="box page-container__header false box--flex-direction-row"
|
||||
class="mm-box page-container__header false"
|
||||
>
|
||||
<div
|
||||
class="box page-container__title box--flex-direction-row"
|
||||
class="mm-box page-container__title"
|
||||
>
|
||||
Replace custodian token
|
||||
|
||||
|
||||
</div>
|
||||
<div
|
||||
class="box page-container__subtitle box--flex-direction-row"
|
||||
class="mm-box page-container__subtitle"
|
||||
>
|
||||
This is will replace the custodian token for the following address:
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box page-container__content box--flex-direction-row"
|
||||
class="mm-box page-container__content"
|
||||
>
|
||||
<div
|
||||
class="box interactive-replacement-token-page box--margin-right-7 box--margin-left-7 box--display-flex box--flex-direction-row box--color-text-alternative"
|
||||
class="mm-box interactive-replacement-token-page mm-box--margin-right-7 mm-box--margin-left-7 mm-box--display-flex mm-box--color-text-alternative"
|
||||
overflowwrap="break-word"
|
||||
>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-column box--width-full"
|
||||
class="mm-box mm-box--display-flex mm-box--flex-direction-column mm-box--width-full"
|
||||
data-testid="interactive-replacement-token-page"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box page-container__footer box--flex-direction-row"
|
||||
<footer
|
||||
class="mm-box page-container__footer mm-box--padding-4"
|
||||
>
|
||||
<footer>
|
||||
<div
|
||||
class="pulse-loader"
|
||||
>
|
||||
@ -55,20 +54,19 @@ exports[`Interactive Replacement Token Page should reject if there are errors 1`
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
exports[`Interactive Replacement Token Page should reject if there are errors 2`] = `
|
||||
<div>
|
||||
<div
|
||||
class="box page-container box--flex-direction-row"
|
||||
class="mm-box page-container"
|
||||
data-testid="interactive-replacement-token"
|
||||
>
|
||||
<div
|
||||
class="box page-container__header error box--flex-direction-row"
|
||||
class="mm-box page-container__header error"
|
||||
>
|
||||
<div
|
||||
class="box page-container__title box--flex-direction-row"
|
||||
class="mm-box page-container__title"
|
||||
>
|
||||
Replace custodian token
|
||||
|
||||
@ -76,10 +74,10 @@ exports[`Interactive Replacement Token Page should reject if there are errors 2`
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box page-container__content box--flex-direction-row"
|
||||
class="mm-box page-container__content"
|
||||
>
|
||||
<div
|
||||
class="box interactive-replacement-token-page box--margin-right-7 box--margin-left-7 box--display-flex box--flex-direction-row box--color-text-alternative"
|
||||
class="mm-box interactive-replacement-token-page mm-box--margin-right-7 mm-box--margin-left-7 mm-box--display-flex mm-box--color-text-alternative"
|
||||
overflowwrap="break-word"
|
||||
>
|
||||
<p
|
||||
@ -88,32 +86,26 @@ exports[`Interactive Replacement Token Page should reject if there are errors 2`
|
||||
>
|
||||
Please go to displayName and click the 'Connect to MMI' button within their user interface to connect your accounts to MMI again.
|
||||
</p>
|
||||
<div
|
||||
class="box box--display-flex box--flex-direction-column box--width-full"
|
||||
data-testid="interactive-replacement-token-page"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="box page-container__footer box--flex-direction-row"
|
||||
<footer
|
||||
class="mm-box page-container__footer mm-box--padding-4"
|
||||
>
|
||||
<div
|
||||
class="mm-box mm-box--display-flex mm-box--gap-4"
|
||||
>
|
||||
<footer>
|
||||
<button
|
||||
class="button btn--rounded btn-default btn--large page-container__footer-button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="box mm-text mm-button-base mm-button-base--size-lg mm-button-base--block mm-button-secondary mm-text--body-md-medium box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-default box--background-color-transparent box--rounded-pill box--border-color-primary-default box--border-style-solid box--border-width-1"
|
||||
>
|
||||
Reject
|
||||
</button>
|
||||
<button
|
||||
class="button btn--rounded btn-primary btn--large page-container__footer-button"
|
||||
role="button"
|
||||
tabindex="0"
|
||||
class="box mm-text mm-button-base mm-button-base--size-lg mm-button-base--block mm-button-primary mm-text--body-md-medium box--padding-right-4 box--padding-left-4 box--display-inline-flex box--flex-direction-row box--justify-content-center box--align-items-center box--color-primary-inverse box--background-color-primary-default box--rounded-pill"
|
||||
>
|
||||
displayName
|
||||
</button>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
@ -4,7 +4,6 @@ import PropTypes from 'prop-types';
|
||||
import { toChecksumHexAddress } from '../../../../shared/modules/hexstring-utils';
|
||||
import { getMostRecentOverviewPage } from '../../../ducks/history/history';
|
||||
import { getMetaMaskAccounts } from '../../../selectors';
|
||||
import Button from '../../../components/ui/button';
|
||||
import CustodyLabels from '../../../components/institutional/custody-labels/custody-labels';
|
||||
import PulseLoader from '../../../components/ui/pulse-loader';
|
||||
import { INSTITUTIONAL_FEATURES_DONE_ROUTE } from '../../../helpers/constants/routes';
|
||||
@ -17,7 +16,6 @@ import {
|
||||
mmiActionsFactory,
|
||||
showInteractiveReplacementTokenBanner,
|
||||
} from '../../../store/institutional/institution-background';
|
||||
import Box from '../../../components/ui/box';
|
||||
import {
|
||||
Text,
|
||||
Label,
|
||||
@ -25,14 +23,18 @@ import {
|
||||
ButtonLink,
|
||||
IconName,
|
||||
IconSize,
|
||||
Box,
|
||||
Button,
|
||||
BUTTON_VARIANT,
|
||||
BUTTON_SIZES,
|
||||
} from '../../../components/component-library';
|
||||
import {
|
||||
OVERFLOW_WRAP,
|
||||
OverflowWrap,
|
||||
TextColor,
|
||||
JustifyContent,
|
||||
BLOCK_SIZES,
|
||||
DISPLAY,
|
||||
FLEX_DIRECTION,
|
||||
BlockSize,
|
||||
Display,
|
||||
FlexDirection,
|
||||
IconColor,
|
||||
} from '../../../helpers/constants/design-system';
|
||||
import { useCopyToClipboard } from '../../../hooks/useCopyToClipboard';
|
||||
@ -46,7 +48,9 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
const dispatch = useDispatch();
|
||||
const isMountedRef = useRef(false);
|
||||
const mmiActions = mmiActionsFactory();
|
||||
const { address } = useSelector((state) => state.metamask.modal.props);
|
||||
const address = useSelector(
|
||||
(state) => state.appState.modal.modalState.props?.address,
|
||||
);
|
||||
const {
|
||||
selectedAddress,
|
||||
custodyAccountDetails,
|
||||
@ -83,9 +87,12 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
let isMounted = true;
|
||||
|
||||
const getTokenAccounts = async () => {
|
||||
if (!connectRequest) {
|
||||
history.push(mostRecentOverviewPage);
|
||||
setIsLoading(false);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -111,23 +118,37 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
metaMaskAccounts[account.address.toLowerCase()]?.balance || 0,
|
||||
}));
|
||||
|
||||
if (isMountedRef.current) {
|
||||
if (isMounted) {
|
||||
setTokenAccounts(mappedAccounts);
|
||||
setIsLoading(false);
|
||||
}
|
||||
} catch (e) {
|
||||
setError(true);
|
||||
setIsLoading(false);
|
||||
} finally {
|
||||
if (isMounted) {
|
||||
setIsLoading(false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
getTokenAccounts();
|
||||
|
||||
return () => {
|
||||
isMounted = false;
|
||||
};
|
||||
// We just want to get the accounts in the render of the component
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!connectRequest) {
|
||||
history.push(mostRecentOverviewPage);
|
||||
setIsLoading(false);
|
||||
}
|
||||
}, [connectRequest, history, mostRecentOverviewPage]);
|
||||
|
||||
if (!connectRequest) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@ -142,8 +163,8 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
};
|
||||
|
||||
const handleReject = () => {
|
||||
setIsLoading(true);
|
||||
onRemoveAddTokenConnectRequest(connectRequest);
|
||||
history.push(mostRecentOverviewPage);
|
||||
};
|
||||
|
||||
const handleApprove = async () => {
|
||||
@ -208,10 +229,10 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
</Box>
|
||||
<Box className="page-container__content">
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
marginRight={7}
|
||||
marginLeft={7}
|
||||
overflowWrap={OVERFLOW_WRAP.BREAK_WORD}
|
||||
overflowwrap={OverflowWrap.BreakWord}
|
||||
color={TextColor.textAlternative}
|
||||
className="interactive-replacement-token-page"
|
||||
>
|
||||
@ -221,24 +242,24 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
custodian.displayName || 'Custodian',
|
||||
])}
|
||||
</Text>
|
||||
) : null}
|
||||
) : (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
width={BLOCK_SIZES.FULL}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
width={BlockSize.Full}
|
||||
data-testid="interactive-replacement-token-page"
|
||||
>
|
||||
{tokenAccounts.map((account, idx) => {
|
||||
return (
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
className="interactive-replacement-token-page__item"
|
||||
key={account.address}
|
||||
>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
flexDirection={FLEX_DIRECTION.COLUMN}
|
||||
width={BLOCK_SIZES.FULL}
|
||||
display={Display.Flex}
|
||||
flexDirection={FlexDirection.Column}
|
||||
width={BlockSize.Full}
|
||||
>
|
||||
<Label
|
||||
marginTop={3}
|
||||
@ -256,7 +277,7 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
>
|
||||
<Text
|
||||
as="span"
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
className="interactive-replacement-token-page__item__address"
|
||||
>
|
||||
<ButtonLink
|
||||
@ -286,7 +307,7 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
>
|
||||
<Icon
|
||||
name={IconName.Copy}
|
||||
size={IconSize.Xs}
|
||||
size={IconSize.Sm}
|
||||
color={IconColor.iconMuted}
|
||||
/>
|
||||
</button>
|
||||
@ -294,7 +315,7 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
</Text>
|
||||
</Label>
|
||||
<Box
|
||||
display={DISPLAY.FLEX}
|
||||
display={Display.Flex}
|
||||
justifyContent={JustifyContent.spaceBetween}
|
||||
>
|
||||
{account.labels && (
|
||||
@ -310,34 +331,33 @@ export default function InteractiveReplacementTokenPage({ history }) {
|
||||
);
|
||||
})}
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
<Box className="page-container__footer">
|
||||
<Box as="footer" className="page-container__footer" padding={4}>
|
||||
{isLoading ? (
|
||||
<footer>
|
||||
<PulseLoader />
|
||||
</footer>
|
||||
) : (
|
||||
<footer>
|
||||
<Box display={Display.Flex} gap={4}>
|
||||
<Button
|
||||
type="default"
|
||||
large
|
||||
className="page-container__footer-button"
|
||||
block
|
||||
variant={BUTTON_VARIANT.SECONDARY}
|
||||
size={BUTTON_SIZES.LG}
|
||||
onClick={handleReject}
|
||||
>
|
||||
{t('reject')}
|
||||
</Button>
|
||||
<Button
|
||||
type="primary"
|
||||
large
|
||||
className="page-container__footer-button"
|
||||
block
|
||||
variant={BUTTON_VARIANT.PRIMARY}
|
||||
size={BUTTON_SIZES.LG}
|
||||
onClick={handleApprove}
|
||||
>
|
||||
{error
|
||||
? custodian.displayName || 'Custodian'
|
||||
: t('approveButtonText')}
|
||||
</Button>
|
||||
</footer>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
</Box>
|
||||
|
@ -166,8 +166,6 @@ describe('Interactive Replacement Token Page', function () {
|
||||
});
|
||||
|
||||
it('should call onRemoveAddTokenConnectRequest and navigate to mostRecentOverviewPage when handleReject is called', () => {
|
||||
const mostRecentOverviewPage = '/mostRecentOverviewPage';
|
||||
|
||||
const { getByText } = render();
|
||||
|
||||
fireEvent.click(getByText('Reject'));
|
||||
@ -178,8 +176,6 @@ describe('Interactive Replacement Token Page', function () {
|
||||
apiUrl: connectRequests[0].apiUrl,
|
||||
token: connectRequests[0].token,
|
||||
});
|
||||
expect(props.history.push).toHaveBeenCalled();
|
||||
expect(props.history.push).toHaveBeenCalledWith(mostRecentOverviewPage);
|
||||
});
|
||||
|
||||
it('should call onRemoveAddTokenConnectRequest, setCustodianNewRefreshToken, and dispatch showInteractiveReplacementTokenBanner when handleApprove is called', async () => {
|
||||
|
@ -15,7 +15,6 @@
|
||||
@import 'connected-sites/index';
|
||||
@import 'create-account/connect-hardware/index';
|
||||
@import "institutional/connect-custody/index";
|
||||
@import "institutional/custody/index";
|
||||
@import "institutional/institutional-entity-done-page/index";
|
||||
@import "institutional/compliance-feature-page/index";
|
||||
@import "institutional/confirm-add-custodian-token/index";
|
||||
|
@ -20,12 +20,14 @@ export function showInteractiveReplacementTokenBanner({
|
||||
}: {
|
||||
url: string;
|
||||
oldRefreshToken: string;
|
||||
}): ThunkAction<void, MetaMaskReduxState, unknown, AnyAction> {
|
||||
}) {
|
||||
return async (dispatch: MetaMaskReduxDispatch) => {
|
||||
try {
|
||||
await submitRequestToBackground('showInteractiveReplacementTokenBanner', [
|
||||
{
|
||||
url,
|
||||
oldRefreshToken,
|
||||
},
|
||||
]);
|
||||
} catch (err: any) {
|
||||
if (err) {
|
||||
@ -237,19 +239,21 @@ export function mmiActionsFactory() {
|
||||
custodyType,
|
||||
token,
|
||||
]),
|
||||
setCustodianNewRefreshToken: (
|
||||
address: string,
|
||||
oldAuthDetails: string,
|
||||
oldApiUrl: string,
|
||||
newAuthDetails: string,
|
||||
newApiUrl: string,
|
||||
) =>
|
||||
createAsyncAction('setCustodianNewRefreshToken', [
|
||||
setCustodianNewRefreshToken: ({
|
||||
address,
|
||||
oldAuthDetails,
|
||||
oldApiUrl,
|
||||
newAuthDetails,
|
||||
newApiUrl,
|
||||
}: {
|
||||
address: string;
|
||||
oldAuthDetails: string;
|
||||
oldApiUrl: string;
|
||||
newAuthDetails: string;
|
||||
newApiUrl: string;
|
||||
}) =>
|
||||
createAsyncAction('setCustodianNewRefreshToken', [
|
||||
{ address, oldAuthDetails, oldApiUrl, newAuthDetails, newApiUrl },
|
||||
]),
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user