chore(trading): open connect dialog from onboarding dialog (#4744)

Co-authored-by: Matthew Russell <mattrussell36@gmail.com>
This commit is contained in:
Maciek 2023-09-12 17:07:37 +02:00 committed by GitHub
parent a0945be721
commit 2453d7841a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 88 additions and 125 deletions

View File

@ -22,7 +22,7 @@ describe('GetStarted', () => {
}; };
const checkTicks = (elements: Element[]) => { const checkTicks = (elements: Element[]) => {
elements.forEach((item, i) => { elements.forEach((item, i) => {
if (i + 1 < mockStep) { if (i + 1 < mockStep - 1) {
expect(item.querySelector('[data-testid="icon-tick"]')).toBeTruthy(); expect(item.querySelector('[data-testid="icon-tick"]')).toBeTruthy();
} }
}); });
@ -57,19 +57,9 @@ describe('GetStarted', () => {
'get' 'get'
); );
navigatorGetter.mockReturnValue('Chrome'); navigatorGetter.mockReturnValue('Chrome');
mockStep = 1;
const { rerender, container } = renderComponent();
expect(screen.queryByTestId('icon-tick')).not.toBeInTheDocument();
expect(screen.getByTestId('get-wallet-button')).toBeInTheDocument();
mockStep = 2; mockStep = 2;
rerender( const { rerender, container } = renderComponent();
<MemoryRouter>
<VegaWalletContext.Provider value={{} as VegaWalletContextShape}>
<GetStarted />
</VegaWalletContext.Provider>
</MemoryRouter>
);
checkTicks(screen.getAllByRole('listitem')); checkTicks(screen.getAllByRole('listitem'));
expect(screen.getByRole('button', { name: 'Connect' })).toBeInTheDocument(); expect(screen.getByRole('button', { name: 'Connect' })).toBeInTheDocument();
@ -93,7 +83,9 @@ describe('GetStarted', () => {
</MemoryRouter> </MemoryRouter>
); );
checkTicks(screen.getAllByRole('listitem')); checkTicks(screen.getAllByRole('listitem'));
expect(screen.getByRole('button', { name: 'Dismiss' })).toBeInTheDocument(); expect(
screen.getByRole('button', { name: 'Ready to trade' })
).toBeInTheDocument();
mockStep = 5; mockStep = 5;
rerender( rerender(

View File

@ -7,11 +7,7 @@ import {
VegaIcon, VegaIcon,
VegaIconNames, VegaIconNames,
} from '@vegaprotocol/ui-toolkit'; } from '@vegaprotocol/ui-toolkit';
import { import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
GetWalletButton,
useVegaWallet,
useVegaWalletDialogStore,
} from '@vegaprotocol/wallet';
import { Networks, useEnvironment } from '@vegaprotocol/environment'; import { Networks, useEnvironment } from '@vegaprotocol/environment';
import { useLocalStorage } from '@vegaprotocol/react-helpers'; import { useLocalStorage } from '@vegaprotocol/react-helpers';
import { useNavigate } from 'react-router-dom'; import { useNavigate } from 'react-router-dom';
@ -30,7 +26,6 @@ interface Props {
} }
const GetStartedButton = ({ step }: { step: OnboardingStep }) => { const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
const { CHROME_EXTENSION_URL, MOZILLA_EXTENSION_URL } = useEnvironment();
const navigate = useNavigate(); const navigate = useNavigate();
const [, setOnboardingViewed] = useLocalStorage( const [, setOnboardingViewed] = useLocalStorage(
constants.ONBOARDING_VIEWED_KEY constants.ONBOARDING_VIEWED_KEY
@ -47,15 +42,7 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
let onClickHandle = () => { let onClickHandle = () => {
openVegaWalletDialog(); openVegaWalletDialog();
}; };
if (step === OnboardingStep.ONBOARDING_WALLET_STEP) { if (step <= OnboardingStep.ONBOARDING_CONNECT_STEP) {
return (
<GetWalletButton
className="justify-between"
chromeExtensionUrl={CHROME_EXTENSION_URL}
mozillaExtensionUrl={MOZILLA_EXTENSION_URL}
/>
);
} else if (step === OnboardingStep.ONBOARDING_CONNECT_STEP) {
buttonText = t('Connect'); buttonText = t('Connect');
} else if (step === OnboardingStep.ONBOARDING_DEPOSIT_STEP) { } else if (step === OnboardingStep.ONBOARDING_DEPOSIT_STEP) {
buttonText = t('Deposit'); buttonText = t('Deposit');
@ -65,7 +52,7 @@ const GetStartedButton = ({ step }: { step: OnboardingStep }) => {
dismiss(); dismiss();
}; };
} else if (step === OnboardingStep.ONBOARDING_ORDER_STEP) { } else if (step === OnboardingStep.ONBOARDING_ORDER_STEP) {
buttonText = t('Dismiss'); buttonText = t('Ready to trade');
onClickHandle = () => { onClickHandle = () => {
navigate(link); navigate(link);
setView({ type: ViewType.Order }); setView({ type: ViewType.Order });
@ -116,23 +103,18 @@ export const GetStarted = ({ lead }: Props) => {
<ul className="list-none"> <ul className="list-none">
<Step <Step
step={1} step={1}
text={t('Get a Vega wallet')}
complete={currentStep > OnboardingStep.ONBOARDING_WALLET_STEP}
/>
<Step
step={2}
text={t('Connect')} text={t('Connect')}
complete={Boolean( complete={Boolean(
currentStep > OnboardingStep.ONBOARDING_CONNECT_STEP || pubKey currentStep > OnboardingStep.ONBOARDING_CONNECT_STEP || pubKey
)} )}
/> />
<Step <Step
step={3} step={2}
text={t('Deposit funds')} text={t('Deposit funds')}
complete={currentStep > OnboardingStep.ONBOARDING_DEPOSIT_STEP} complete={currentStep > OnboardingStep.ONBOARDING_DEPOSIT_STEP}
/> />
<Step <Step
step={4} step={3}
text={t('Open a position')} text={t('Open a position')}
complete={currentStep > OnboardingStep.ONBOARDING_ORDER_STEP} complete={currentStep > OnboardingStep.ONBOARDING_ORDER_STEP}
/> />

View File

@ -7,8 +7,6 @@ import {
import type { VegaWalletContextShape } from '@vegaprotocol/wallet'; import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import { VegaWalletContext } from '@vegaprotocol/wallet'; import { VegaWalletContext } from '@vegaprotocol/wallet';
import { useDataProvider } from '@vegaprotocol/data-provider'; import { useDataProvider } from '@vegaprotocol/data-provider';
import { depositsProvider } from '@vegaprotocol/deposits';
import { aggregatedAccountsDataProvider } from '@vegaprotocol/accounts';
import { ordersWithMarketProvider } from '@vegaprotocol/orders'; import { ordersWithMarketProvider } from '@vegaprotocol/orders';
import { positionsDataProvider } from '@vegaprotocol/positions'; import { positionsDataProvider } from '@vegaprotocol/positions';
@ -23,7 +21,7 @@ let mockContext: Partial<VegaWalletContextShape> = { pubKey: 'test-pubkey' };
describe('useGetOnboardingStep', () => { describe('useGetOnboardingStep', () => {
beforeEach(() => { beforeEach(() => {
jest.clearAllMocks(); jest.clearAllMocks();
mockData = [{ id: 'item-id' }]; mockData = [];
mockContext = { pubKey: 'test-pubkey' }; mockContext = { pubKey: 'test-pubkey' };
globalThis.window.vega = {} as Vega; globalThis.window.vega = {} as Vega;
}); });
@ -42,13 +40,6 @@ describe('useGetOnboardingStep', () => {
expect(result.current).toEqual(OnboardingStep.ONBOARDING_UNKNOWN_STEP); expect(result.current).toEqual(OnboardingStep.ONBOARDING_UNKNOWN_STEP);
}); });
it('should return properly ONBOARDING_WALLET_STEP', () => {
// @ts-ignore test only purpose
globalThis.window.vega = undefined;
const { result } = renderHook(() => useGetOnboardingStep(), { wrapper });
expect(result.current).toEqual(OnboardingStep.ONBOARDING_WALLET_STEP);
});
it('should return properly ONBOARDING_CONNECT_STEP', () => { it('should return properly ONBOARDING_CONNECT_STEP', () => {
mockContext = { pubKey: null }; mockContext = { pubKey: null };
const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); const { result } = renderHook(() => useGetOnboardingStep(), { wrapper });
@ -56,15 +47,6 @@ describe('useGetOnboardingStep', () => {
}); });
it('should return properly ONBOARDING_DEPOSIT_STEP', async () => { it('should return properly ONBOARDING_DEPOSIT_STEP', async () => {
(useDataProvider as jest.Mock).mockImplementation((args) => {
if (
args.dataProvider === depositsProvider ||
args.dataProvider === aggregatedAccountsDataProvider
) {
return { data: [] };
}
return { data: mockData };
});
const { result } = renderHook(() => useGetOnboardingStep(), { wrapper }); const { result } = renderHook(() => useGetOnboardingStep(), { wrapper });
await expect(result.current).toEqual( await expect(result.current).toEqual(
OnboardingStep.ONBOARDING_DEPOSIT_STEP OnboardingStep.ONBOARDING_DEPOSIT_STEP
@ -72,6 +54,7 @@ describe('useGetOnboardingStep', () => {
}); });
it('should return properly ONBOARDING_ORDER_STEP', async () => { it('should return properly ONBOARDING_ORDER_STEP', async () => {
mockData = [{ id: 'item-id' }];
(useDataProvider as jest.Mock).mockImplementation((args) => { (useDataProvider as jest.Mock).mockImplementation((args) => {
if ( if (
args.dataProvider === ordersWithMarketProvider || args.dataProvider === ordersWithMarketProvider ||
@ -86,6 +69,7 @@ describe('useGetOnboardingStep', () => {
}); });
it('should return properly ONBOARDING_COMPLETE_STEP', async () => { it('should return properly ONBOARDING_COMPLETE_STEP', async () => {
mockData = [{ id: 'item-id' }];
(useDataProvider as jest.Mock).mockImplementation(() => { (useDataProvider as jest.Mock).mockImplementation(() => {
return { data: mockData }; return { data: mockData };
}); });

View File

@ -1,4 +1,4 @@
import { isBrowserWalletInstalled, useVegaWallet } from '@vegaprotocol/wallet'; import { useVegaWallet } from '@vegaprotocol/wallet';
import { depositsProvider } from '@vegaprotocol/deposits'; import { depositsProvider } from '@vegaprotocol/deposits';
import { useDataProvider } from '@vegaprotocol/data-provider'; import { useDataProvider } from '@vegaprotocol/data-provider';
import { ordersWithMarketProvider } from '@vegaprotocol/orders'; import { ordersWithMarketProvider } from '@vegaprotocol/orders';
@ -63,20 +63,21 @@ export const useGetOnboardingStep = () => {
collateralData === null || collateralData === null ||
positionsData === null) positionsData === null)
); );
let step = OnboardingStep.ONBOARDING_UNKNOWN_STEP;
if (isLoading) { if (isLoading) {
return OnboardingStep.ONBOARDING_UNKNOWN_STEP; return step;
}
if (!isBrowserWalletInstalled()) {
return OnboardingStep.ONBOARDING_WALLET_STEP;
} }
if (!pubKey) { if (!pubKey) {
return OnboardingStep.ONBOARDING_CONNECT_STEP; step = OnboardingStep.ONBOARDING_CONNECT_STEP;
} }
if (!deposits && !collaterals) { if (pubKey) {
return OnboardingStep.ONBOARDING_DEPOSIT_STEP; step = OnboardingStep.ONBOARDING_DEPOSIT_STEP;
} }
if (!orders && !positions) { if (pubKey && (deposits || collaterals)) {
return OnboardingStep.ONBOARDING_ORDER_STEP; step = OnboardingStep.ONBOARDING_ORDER_STEP;
} }
return OnboardingStep.ONBOARDING_COMPLETE_STEP; if (pubKey && (orders || positions)) {
step = OnboardingStep.ONBOARDING_COMPLETE_STEP;
}
return step;
}; };

View File

@ -39,17 +39,17 @@ const getClassName = (
}, },
// colours // colours
{ {
'bg-vega-yellow hover:bg-vega-yellow-550 dark:bg-vega-yellow dark:hover:bg-vega-yellow-450': 'bg-vega-yellow enabled:hover:bg-vega-yellow-550 dark:bg-vega-yellow dark:enabled:hover:bg-vega-yellow-450':
intent === Intent.Primary, intent === Intent.Primary,
'bg-vega-clight-500 hover:bg-vega-clight-400 dark:bg-vega-cdark-500 dark:hover:bg-vega-cdark-400': 'bg-vega-clight-500 enabled:hover:bg-vega-clight-400 dark:bg-vega-cdark-500 dark:enabled:hover:bg-vega-cdark-400':
intent === Intent.None, intent === Intent.None,
'bg-vega-blue-350 hover:bg-vega-blue-400 dark:bg-vega-blue-650 dark:hover:bg-vega-blue-600': 'bg-vega-blue-350 enabled:hover:bg-vega-blue-400 dark:bg-vega-blue-650 dark:enabled:hover:bg-vega-blue-600':
intent === Intent.Info, intent === Intent.Info,
'bg-vega-orange-350 hover:bg-vega-orange-400 dark:bg-vega-orange-650 dark:hover:bg-vega-orange-600': 'bg-vega-orange-350 enabled:hover:bg-vega-orange-400 dark:bg-vega-orange-650 dark:enabled:hover:bg-vega-orange-600':
intent === Intent.Warning, intent === Intent.Warning,
'bg-vega-red-350 hover:bg-vega-red-400 dark:bg-vega-red-650 dark:hover:bg-vega-red-600': 'bg-vega-red-350 enabled:hover:bg-vega-red-400 dark:bg-vega-red-650 dark:enabled:hover:bg-vega-red-600':
intent === Intent.Danger, intent === Intent.Danger,
'bg-vega-green-350 hover:bg-vega-green-400 dark:bg-vega-green-650 dark:hover:bg-vega-green-600': 'bg-vega-green-350 enabled:hover:bg-vega-green-400 dark:bg-vega-green-650 dark:enabled:hover:bg-vega-green-600':
intent === Intent.Success, intent === Intent.Success,
'text-vega-clight-50 dark:text-vega-cdark-50': intent !== Intent.Primary, 'text-vega-clight-50 dark:text-vega-cdark-50': intent !== Intent.Primary,
'text-vega-clight-900 dark:text-vega-cdark-900': 'text-vega-clight-900 dark:text-vega-cdark-900':
@ -73,7 +73,7 @@ const Content = ({
children, children,
}: Pick<TradingButtonProps, 'icon' | 'subLabel' | 'children'>) => ( }: Pick<TradingButtonProps, 'icon' | 'subLabel' | 'children'>) => (
<> <>
<span data-label className="font-alpha leading-none" key="children"> <span data-label className="leading-none font-alpha" key="children">
{children} {children}
</span> </span>
{icon} {icon}

View File

@ -241,51 +241,49 @@ const ConnectorList = ({
'Connect securely, deposit funds and approve or reject transactions with the Vega wallet' 'Connect securely, deposit funds and approve or reject transactions with the Vega wallet'
)} )}
</p> </p>
<div data-testid="connectors-list" className="flex flex-col mt-4 gap-4"> <div data-testid="connectors-list" className="flex flex-col mt-4 gap-2">
<div> {isBrowserWalletInstalled() ? (
{isBrowserWalletInstalled() ? ( <ConnectionOptionWithDescription
<ConnectionOptionWithDescription type="injected"
type="injected" text={extendedText}
text={extendedText} onClick={() => onSelect('injected')}
onClick={() => onSelect('injected')} title={
title={ <>
<> <span>{t('Vega Wallet')}</span>
<span>{t('Vega Wallet')}</span> {' '}
{' '} <span className="text-xs">{t('full featured')}</span>
<span className="text-xs">{t('full featured')}</span> </>
</> }
} description={t(
description={t( `Connect Vega Wallet extension
`Connect Vega Wallet extension for %s to access all features including key
management and detailed transaction views from your
browser.`,
[browserName]
)}
/>
) : (
<div>
<h1 className="mb-1 text-lg">
<span>{t('Vega Wallet')}</span>
{' '}
<span className="text-xs"> {t('full featured')}</span>
</h1>
<p className="mb-2 text-sm">
{t(
`Install Vega Wallet extension
for %s to access all features including key for %s to access all features including key
management and detailed transaction views from your management and detailed transaction views from your
browser.`, browser.`,
[browserName] [browserName]
)} )}
</p>
<GetWalletButton
chromeExtensionUrl={links.chromeExtensionUrl}
mozillaExtensionUrl={links.mozillaExtensionUrl}
/> />
) : ( </div>
<div className="py-2"> )}
<h1 className="px-2 text-lg">
<span>{t('Vega Wallet')}</span>
{' '}
<span className="text-xs"> {t('full featured')}</span>
</h1>
<p className="p-2 text-sm">
{t(
`Install Vega Wallet extension
for %s to access all features including key
management and detailed transaction views from your
browser.`,
[browserName]
)}
</p>
<GetWalletButton
chromeExtensionUrl={links.chromeExtensionUrl}
mozillaExtensionUrl={links.mozillaExtensionUrl}
/>
</div>
)}
</div>
{connectors['snap'] !== undefined ? ( {connectors['snap'] !== undefined ? (
<div> <div>
{snapStatus === SnapStatus.INSTALLED ? ( {snapStatus === SnapStatus.INSTALLED ? (
@ -335,7 +333,7 @@ const ConnectorList = ({
}} }}
/> />
{snapStatus === SnapStatus.NOT_SUPPORTED ? ( {snapStatus === SnapStatus.NOT_SUPPORTED ? (
<p className="pt-1 text-xs leading-tight text-default"> <p className="pt-1 text-xs leading-tight text-muted">
{t('No MetaMask version that supports snaps detected.')}{' '} {t('No MetaMask version that supports snaps detected.')}{' '}
{t('Learn more about')}{' '} {t('Learn more about')}{' '}
<ExternalLink href="https://metamask.io/snaps/"> <ExternalLink href="https://metamask.io/snaps/">
@ -348,7 +346,7 @@ const ConnectorList = ({
</div> </div>
) : null} ) : null}
<div> <div>
<h1 className="my-1 text-md">{t('Advanced / Other options...')}</h1> <h1 className="mb-1 text-md">{t('Advanced / Other options...')}</h1>
<ConnectionOption <ConnectionOption
type="view" type="view"
text={t('View as party')} text={t('View as party')}
@ -520,7 +518,7 @@ const ConnectionOptionWithDescription = ({
return ( return (
<div> <div>
<h1 className="text-md">{title}</h1> <h1 className="text-md">{title}</h1>
<p className="pb-2 text-sm text-gray-60 text-muted">{description}</p> <p className="mb-2 text-sm text-gray-60 text-muted">{description}</p>
<ConnectionOption <ConnectionOption
disabled={disabled} disabled={disabled}
type={type} type={type}
@ -579,10 +577,11 @@ const CustomUrlInput = ({
<div className="flex justify-between mb-1.5"> <div className="flex justify-between mb-1.5">
<p className="text-sm text-secondary">{t('Custom wallet location')}</p> <p className="text-sm text-secondary">{t('Custom wallet location')}</p>
<button <button
className="text-sm underline" className="text-sm text-muted"
onClick={() => setUrlInputExpanded(false)} onClick={() => setUrlInputExpanded(false)}
> >
<VegaIcon name={VegaIconNames.ARROW_LEFT} /> {t('Go back')} <VegaIcon name={VegaIconNames.ARROW_LEFT} />{' '}
<span className="underline underline-offset-4">{t('Go back')}</span>
</button> </button>
</div> </div>
<TradingFormGroup <TradingFormGroup
@ -612,18 +611,20 @@ const CustomUrlInput = ({
onClick={() => onSelect('jsonRpc')} onClick={() => onSelect('jsonRpc')}
/> />
{isDesktopWalletRunning !== null && ( {isDesktopWalletRunning !== null && (
<p className="pt-1 mb-2 text-sm leading-tight"> <div className="pt-1 mb-2 text-sm">
{isDesktopWalletRunning ? ( {isDesktopWalletRunning ? (
<button <button
className="underline text-default" className="text-muted"
onClick={() => setUrlInputExpanded(true)} onClick={() => setUrlInputExpanded(true)}
disabled={Boolean(pubKey)} disabled={Boolean(pubKey)}
> >
{t('Enter a custom wallet location')}{' '} <span className="underline underline-offset-4">
{t('Enter a custom wallet location')}
</span>{' '}
<VegaIcon name={VegaIconNames.ARROW_RIGHT} /> <VegaIcon name={VegaIconNames.ARROW_RIGHT} />
</button> </button>
) : ( ) : (
<> <p className="leading-tight text-muted">
<span className="text-xs"> <span className="text-xs">
{t( {t(
'No running Desktop App/CLI detected. Open your app now to connect or enter a' 'No running Desktop App/CLI detected. Open your app now to connect or enter a'
@ -636,9 +637,9 @@ const CustomUrlInput = ({
> >
{t('custom wallet location')} {t('custom wallet location')}
</button> </button>
</> </p>
)} )}
</p> </div>
)} )}
</> </>
); );

View File

@ -88,10 +88,13 @@ export function ViewConnectorForm({
<div className="flex justify-end"> <div className="flex justify-end">
<button <button
onClick={reset} onClick={reset}
className="p-2 text-sm underline" className="p-2 text-sm"
data-testid="back-button" data-testid="back-button"
> >
<VegaIcon name={VegaIconNames.ARROW_LEFT} /> {t('Go back')} <VegaIcon name={VegaIconNames.ARROW_LEFT} />{' '}
<span className="underline underline-offset-4">
{t('Go back')}
</span>
</button> </button>
</div> </div>
)} )}