market page: break down components to smaller chunks for better performance (#1726)

* chore: break down components to smaller chunks for better performance

* chore: break down components to smaller chunks for better performance

* chore: break down components to smaller chunks for better performance - fix failing tests

* chore: break down components to smaller chunks for better performance - adjust token app cases

* chore: break down components to smaller chunks for better performance - small fixes

* chore: break down components to smaller chunks for better performance - small fixes

* chore: break down components to smaller chunks for better performance - small fixes

* chore: break down components to smaller chunks for better performance - small fixes

* chore: break down components to smaller chunks for better performance - add nwe store for pageTitle

* chore: break down components to smaller chunks for better performance - sm fix

* chore: break down components to smaller chunks for better performance - sm fix

* chore: break down components to smaller chunks for better performance - sm imprv

* chore: break down components to smaller chunks for better performance - change prop names

* chore: break down components to smaller chunks for better performance - fix some test

* chore: break down components to smaller chunks for better performance - change cypress url

* chore: break down components to smaller chunks for better perf - set back redundant changes

* chore: resolve conflicts

Co-authored-by: maciek <maciek@vegaprotocol.io>
This commit is contained in:
macqbat 2022-10-14 17:42:53 +02:00 committed by GitHub
parent ecb19f226b
commit 37a6217169
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 255 additions and 178 deletions

View File

@ -40,11 +40,7 @@ function App() {
<div className="max-h-full min-h-full dark:bg-lite-black dark:text-neutral-200 bg-white text-neutral-800 grid grid-rows-[min-content,1fr]">
<Header />
<Main />
<VegaConnectDialog
connectors={Connectors}
dialogOpen={vegaWalletDialog.connect}
setDialogOpen={vegaWalletDialog.setConnect}
/>
<VegaConnectDialog connectors={Connectors} />
<VegaManageDialog
dialogOpen={vegaWalletDialog.manage}
setDialogOpen={vegaWalletDialog.setManage}

View File

@ -1,12 +1,16 @@
import React, { useContext } from 'react';
import { ThemeSwitcher } from '@vegaprotocol/ui-toolkit';
import { useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import Logo from './logo';
import { VegaWalletConnectButton } from '../vega-wallet-connect-button';
import LocalContext from '../../context/local-context';
const Header = () => {
const { updateVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
updateVegaWalletDialog: store.updateVegaWalletDialog,
}));
const {
vegaWalletDialog: { setConnect, setManage },
vegaWalletDialog: { setManage },
theme,
toggleTheme,
} = useContext(LocalContext);
@ -18,7 +22,7 @@ const Header = () => {
<Logo />
<div className="flex items-center gap-2 ml-auto relative z-10">
<VegaWalletConnectButton
setConnectDialog={setConnect}
setConnectDialog={updateVegaWalletDialog}
setManageDialog={setManage}
/>
<ThemeSwitcher theme={theme} onToggle={toggleTheme} className="-my-4" />

View File

@ -1,13 +1,12 @@
import { useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { t } from '@vegaprotocol/react-helpers';
import { Button } from '@vegaprotocol/ui-toolkit';
import * as React from 'react';
import { useContext } from 'react';
import LocalContext from '../../context/local-context';
const ConnectWallet = () => {
const {
vegaWalletDialog: { setConnect },
} = useContext(LocalContext);
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
return (
<section
className="p-8 bg-white-normal dark:bg-offBlack"
@ -17,7 +16,7 @@ const ConnectWallet = () => {
{t('Please connect your Vega wallet to make a trade')}
</h3>
<div className="mb-4">
<Button variant="primary" onClick={() => setConnect(true)} size="lg">
<Button variant="primary" onClick={openVegaWalletDialog} size="lg">
{t('Connect Vega wallet')}
</Button>
</div>

View File

@ -1,9 +1,7 @@
import { createContext } from 'react';
export interface VegaWalletDialogState {
connect: boolean;
manage: boolean;
setConnect: (isOpen: boolean) => void;
setManage: (isOpen: boolean) => void;
}

View File

@ -7,12 +7,9 @@ describe('local values hook', () => {
const { result } = renderHook(() => useLocalValues('light', setTheme));
expect(result.current.vegaWalletDialog).toBeDefined();
expect(result.current.vegaWalletDialog.manage).toBe(false);
expect(result.current.vegaWalletDialog.connect).toBe(false);
act(() => {
result.current.vegaWalletDialog.setConnect(true);
result.current.vegaWalletDialog.setManage(true);
});
expect(result.current.vegaWalletDialog.manage).toBe(true);
expect(result.current.vegaWalletDialog.connect).toBe(true);
});
});

View File

@ -2,17 +2,16 @@ import { useMemo, useState } from 'react';
import type { LocalValues } from '../context/local-context';
const useLocalValues = (theme: 'light' | 'dark', toggleTheme: () => void) => {
const [connect, setConnect] = useState<boolean>(false);
const [manage, setManage] = useState<boolean>(false);
const [menuOpen, setMenuOpen] = useState(false);
return useMemo<LocalValues>(
() => ({
vegaWalletDialog: { connect, manage, setConnect, setManage },
vegaWalletDialog: { manage, setManage },
menu: { menuOpen, setMenuOpen, onToggle: () => setMenuOpen(!menuOpen) },
theme,
toggleTheme,
}),
[connect, manage, theme, toggleTheme, menuOpen]
[manage, theme, toggleTheme, menuOpen]
);
};

View File

@ -1,7 +1,7 @@
import { Button } from '@vegaprotocol/ui-toolkit';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import {
AppStateActionType,
useAppState,
@ -10,14 +10,18 @@ import {
export const ConnectToVega = () => {
const { appDispatch } = useAppState();
const { t } = useTranslation();
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
return (
<Button
onClick={() =>
onClick={() => {
appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
isOpen: true,
})
}
});
openVegaWalletDialog();
}}
data-testid="connect-to-vega-wallet-btn"
>
{t('connectVegaWallet')}

View File

@ -1,5 +1,5 @@
import { Button } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import React from 'react';
import { useTranslation } from 'react-i18next';
@ -16,18 +16,22 @@ export const VegaWalletContainer = ({ children }: VegaWalletContainerProps) => {
const { t } = useTranslation();
const { pubKey } = useVegaWallet();
const { appDispatch } = useAppState();
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
if (!pubKey) {
return (
<p>
<Button
data-testid="connect-to-vega-wallet-btn"
onClick={() =>
onClick={() => {
appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
isOpen: true,
})
}
});
openVegaWalletDialog();
}}
>
{t('connectVegaWallet')}
</Button>

View File

@ -11,8 +11,7 @@ export const VegaWalletDialogs = () => {
<>
<VegaConnectDialog
connectors={Connectors}
dialogOpen={appState.vegaWalletOverlay}
setDialogOpen={(open) =>
onChangeOpen={(open) =>
appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
isOpen: open,

View File

@ -22,7 +22,7 @@ import {
} from '../wallet-card';
import { DownloadWalletPrompt } from './download-wallet-prompt';
import { usePollForDelegations } from './hooks';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { Button, ButtonLink } from '@vegaprotocol/ui-toolkit';
export const VegaWallet = () => {
@ -69,16 +69,19 @@ export const VegaWallet = () => {
const VegaWalletNotConnected = () => {
const { t } = useTranslation();
const { appDispatch } = useAppState();
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
return (
<>
<Button
onClick={() =>
onClick={() => {
appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
isOpen: true,
})
}
});
openVegaWalletDialog();
}}
fill={true}
data-testid="connect-vega"
>

View File

@ -14,7 +14,7 @@ import type {
VoteButtonsQueryVariables,
} from './__generated__/VoteButtonsQuery';
import { VoteState } from './use-user-vote';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import {
ProposalState,
ProposalUserAction,
@ -84,6 +84,9 @@ export const VoteButtons = ({
const { t } = useTranslation();
const { appDispatch } = useAppState();
const { pubKey } = useVegaWallet();
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const [changeVote, setChangeVote] = React.useState(false);
const cantVoteUI = React.useMemo(() => {
@ -95,12 +98,13 @@ export const VoteButtons = ({
return (
<div data-testid="connect-wallet">
<ButtonLink
onClick={() =>
onClick={() => {
appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
isOpen: true,
})
}
});
openVegaWalletDialog();
}}
>
{t('connectVegaWallet')}
</ButtonLink>{' '}
@ -144,6 +148,7 @@ export const VoteButtons = ({
appDispatch,
minVoterBalance,
spamProtectionMinTokens,
openVegaWalletDialog,
]);
function submitVote(vote: VoteValue) {

View File

@ -16,7 +16,7 @@ import {
} from '../../../contexts/app-state/app-state-context';
import type { Rewards } from './__generated__/Rewards';
import { RewardInfo } from './reward-info';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { useNetworkParams, NetworkParams } from '@vegaprotocol/react-helpers';
export const REWARDS_QUERY = gql`
@ -67,6 +67,9 @@ export const REWARDS_QUERY = gql`
export const RewardsIndex = () => {
const { t } = useTranslation();
const { pubKey, pubKeys } = useVegaWallet();
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const { appDispatch } = useAppState();
const { data, loading, error } = useQuery<Rewards>(REWARDS_QUERY, {
variables: { partyId: pubKey },
@ -147,12 +150,13 @@ export const RewardsIndex = () => {
<div>
<Button
data-testid="connect-to-vega-wallet-btn"
onClick={() =>
onClick={() => {
appDispatch({
type: AppStateActionType.SET_VEGA_WALLET_OVERLAY,
isOpen: true,
})
}
});
openVegaWalletDialog();
}}
>
{t('connectVegaWallet')}
</Button>

View File

@ -1,2 +1,2 @@
NX_VEGA_WALLET_URL=http://localhost:1789
CYPRESS_VEGA_URL=https://api.n06.testnet.vega.xyz/graphql
CYPRESS_VEGA_URL=https://api.n06.testnet.vega.xyz/graphql

View File

@ -15,9 +15,8 @@ interface NavbarProps {
}
export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
const { marketId, update } = useGlobalStore((store) => ({
const { marketId } = useGlobalStore((store) => ({
marketId: store.marketId,
update: store.update,
}));
const [tradingPath, setTradingPath] = useState('/markets');
useEffect(() => {
@ -42,9 +41,7 @@ export const Navbar = ({ theme, toggleTheme }: NavbarProps) => {
</nav>
<div className="flex items-center gap-2 ml-auto">
<ThemeSwitcher theme={theme} onToggle={toggleTheme} />
<VegaWalletConnectButton
setConnectDialog={(open) => update({ connectDialog: open })}
/>
<VegaWalletConnectButton />
</div>
</div>
);

View File

@ -1,49 +1,49 @@
import { fireEvent, render, screen } from '@testing-library/react';
import { VegaWalletContext } from '@vegaprotocol/wallet';
import type { VegaWalletContextShape } from '@vegaprotocol/wallet';
import type { VegaWalletConnectButtonProps } from './vega-wallet-connect-button';
import { VegaWalletConnectButton } from './vega-wallet-connect-button';
import { truncateByChars } from '@vegaprotocol/react-helpers';
let props: VegaWalletConnectButtonProps;
const mockUpdateDialogOpen = jest.fn();
jest.mock('@vegaprotocol/wallet', () => ({
...jest.requireActual('@vegaprotocol/wallet'),
useVegaWalletDialogStore: () => ({
openVegaWalletDialog: mockUpdateDialogOpen,
}),
}));
beforeEach(() => {
props = {
setConnectDialog: jest.fn(),
};
jest.clearAllMocks();
});
const generateJsx = (
context: VegaWalletContextShape,
props: VegaWalletConnectButtonProps
) => {
const generateJsx = (context: VegaWalletContextShape) => {
return (
<VegaWalletContext.Provider value={context}>
<VegaWalletConnectButton {...props} />
<VegaWalletConnectButton />
</VegaWalletContext.Provider>
);
};
it('Not connected', () => {
render(generateJsx({ pubKey: null } as VegaWalletContextShape, props));
render(generateJsx({ pubKey: null } as VegaWalletContextShape));
const button = screen.getByRole('button');
expect(button).toHaveTextContent('Connect Vega wallet');
fireEvent.click(button);
expect(props.setConnectDialog).toHaveBeenCalledWith(true);
expect(mockUpdateDialogOpen).toHaveBeenCalled();
});
it('Connected', () => {
const pubKey = { publicKey: '123456__123456', name: 'test' };
render(
generateJsx(
{ pubKey: pubKey.publicKey, pubKeys: [pubKey] } as VegaWalletContextShape,
props
)
generateJsx({
pubKey: pubKey.publicKey,
pubKeys: [pubKey],
} as VegaWalletContextShape)
);
const button = screen.getByRole('button');
expect(button).toHaveTextContent(truncateByChars(pubKey.publicKey));
fireEvent.click(button);
expect(props.setConnectDialog).not.toHaveBeenCalled();
expect(mockUpdateDialogOpen).not.toHaveBeenCalled();
});

View File

@ -10,18 +10,15 @@ import {
DropdownMenuTrigger,
Icon,
} from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
import { useEffect, useMemo, useState } from 'react';
import CopyToClipboard from 'react-copy-to-clipboard';
export interface VegaWalletConnectButtonProps {
setConnectDialog: (isOpen: boolean) => void;
}
export const VegaWalletConnectButton = ({
setConnectDialog,
}: VegaWalletConnectButtonProps) => {
export const VegaWalletConnectButton = () => {
const [dropdownOpen, setDropdownOpen] = useState(false);
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const { pubKey, pubKeys, selectPubKey, disconnect } = useVegaWallet();
const isConnected = pubKey !== null;
@ -64,7 +61,7 @@ export const VegaWalletConnectButton = ({
return (
<Button
data-testid="connect-vega-wallet"
onClick={() => setConnectDialog(true)}
onClick={openVegaWalletDialog}
size="sm"
>
<span className="whitespace-nowrap">{t('Connect Vega wallet')}</span>

View File

@ -1,15 +1,16 @@
import type { ReactNode } from 'react';
import { t } from '@vegaprotocol/react-helpers';
import { Button, Splash } from '@vegaprotocol/ui-toolkit';
import { useVegaWallet } from '@vegaprotocol/wallet';
import { useGlobalStore } from '../../stores';
import { useVegaWallet, useVegaWalletDialogStore } from '@vegaprotocol/wallet';
interface VegaWalletContainerProps {
children: ReactNode;
}
export const VegaWalletContainer = ({ children }: VegaWalletContainerProps) => {
const { update } = useGlobalStore((store) => ({ update: store.update }));
const { openVegaWalletDialog } = useVegaWalletDialogStore((store) => ({
openVegaWalletDialog: store.openVegaWalletDialog,
}));
const { pubKey } = useVegaWallet();
if (!pubKey) {
@ -20,7 +21,7 @@ export const VegaWalletContainer = ({ children }: VegaWalletContainerProps) => {
{t('Connect your Vega wallet')}
</p>
<Button
onClick={() => update({ connectDialog: true })}
onClick={openVegaWalletDialog}
data-testid="vega-wallet-connect"
>
{t('Connect')}

View File

@ -2,35 +2,23 @@ import type { AppProps } from 'next/app';
import Head from 'next/head';
import { Navbar } from '../components/navbar';
import { t, ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
import { VegaConnectDialog, VegaWalletProvider } from '@vegaprotocol/wallet';
import { VegaWalletProvider } from '@vegaprotocol/wallet';
import {
EnvironmentProvider,
envTriggerMapping,
useEnvironment,
} from '@vegaprotocol/environment';
import { Connectors } from '../lib/vega-connectors';
import { AppLoader } from '../components/app-loader';
import { RiskNoticeDialog } from '../components/risk-notice-dialog';
import './styles.css';
import { useGlobalStore } from '../stores';
import {
AssetDetailsDialog,
useAssetDetailsDialogStore,
} from '@vegaprotocol/assets';
import { usePageTitleStore } from '../stores';
import { Footer } from '../components/footer';
import { useMemo } from 'react';
import DialogsContainer from './dialogs-container';
const DEFAULT_TITLE = t('Welcome to Vega trading!');
function AppBody({ Component, pageProps }: AppProps) {
const { connectDialog, update } = useGlobalStore((store) => ({
connectDialog: store.connectDialog,
update: store.update,
}));
const { isOpen, symbol, trigger, setOpen } = useAssetDetailsDialogStore();
const [theme, toggleTheme] = useThemeSwitcher();
const { pageTitle } = useGlobalStore((store) => ({
const Title = () => {
const { pageTitle } = usePageTitleStore((store) => ({
pageTitle: store.pageTitle,
}));
@ -42,32 +30,26 @@ function AppBody({ Component, pageProps }: AppProps) {
if (networkName) return `${pageTitle} [${networkName}]`;
return pageTitle;
}, [pageTitle, networkName]);
return (
<Head>
<title>{title}</title>
</Head>
);
};
function AppBody({ Component, pageProps }: AppProps) {
const [theme, toggleTheme] = useThemeSwitcher();
return (
<ThemeContext.Provider value={theme}>
<Head>
<title>{title}</title>
</Head>
<Title />
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
<AppLoader>
<Navbar theme={theme} toggleTheme={toggleTheme} />
<main data-testid={pageProps.page}>
{/* @ts-ignore conflict between @types/react and nextjs internal types */}
<Component {...pageProps} />
</main>
<Footer />
<VegaConnectDialog
connectors={Connectors}
dialogOpen={connectDialog}
setDialogOpen={(open) => update({ connectDialog: open })}
/>
<AssetDetailsDialog
assetSymbol={symbol}
trigger={trigger || null}
open={isOpen}
onChange={setOpen}
/>
<RiskNoticeDialog />
<DialogsContainer />
</AppLoader>
</div>
</ThemeContext.Provider>

View File

@ -0,0 +1,25 @@
import {
AssetDetailsDialog,
useAssetDetailsDialogStore,
} from '@vegaprotocol/assets';
import { VegaConnectDialog } from '@vegaprotocol/wallet';
import { Connectors } from '../lib/vega-connectors';
import { RiskNoticeDialog } from '../components/risk-notice-dialog';
const DialogsContainer = () => {
const { isOpen, symbol, trigger, setOpen } = useAssetDetailsDialogStore();
return (
<>
<VegaConnectDialog connectors={Connectors} />
<AssetDetailsDialog
assetSymbol={symbol}
trigger={trigger || null}
open={isOpen}
onChange={setOpen}
/>
<RiskNoticeDialog />
</>
);
};
export default DialogsContainer;

View File

@ -7,7 +7,7 @@ import {
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
import { useRouter } from 'next/router';
import { useEffect } from 'react';
import { useGlobalStore } from '../stores';
import { useGlobalStore, usePageTitleStore } from '../stores';
export function Index() {
const { replace } = useRouter();
@ -21,6 +21,11 @@ export function Index() {
update: store.update,
}));
const { pageTitle, updateTitle } = usePageTitleStore((store) => ({
pageTitle: store.pageTitle,
updateTitle: store.updateTitle,
}));
useEffect(() => {
update({ landingDialog: true });
@ -33,18 +38,21 @@ export function Index() {
data[0]?.decimalPlaces
)
: null;
const pageTitle = titlefy([marketName, marketPrice]);
const newPageTitle = titlefy([marketName, marketPrice]);
if (marketId) {
replace(`/markets/${marketId}`);
update({ marketId, pageTitle });
update({ marketId });
if (pageTitle !== newPageTitle) {
updateTitle(newPageTitle);
}
}
// Fallback to the markets list page
else {
replace('/markets');
}
}
}, [data, replace, riskNoticeDialog, update]);
}, [data, replace, riskNoticeDialog, update, pageTitle, updateTitle]);
return (
<AsyncRenderer data={data} loading={loading} error={error}>

View File

@ -16,7 +16,7 @@ import type {
MarketDataUpdateFieldsFragment,
} from '@vegaprotocol/market-list';
import { marketProvider, marketDataProvider } from '@vegaprotocol/market-list';
import { useGlobalStore } from '../../stores';
import { useGlobalStore, usePageTitleStore } from '../../stores';
import { TradeGrid, TradePanels } from './trade-grid';
import { ColumnKind, SelectMarketDialog } from '../../components/select-market';
@ -40,18 +40,17 @@ const MarketPage = ({
}) => {
const { query, push } = useRouter();
const { w } = useWindowSize();
const {
landingDialog,
riskNoticeDialog,
update,
updateTitle,
updateMarketId,
} = useGlobalStore((store) => ({
landingDialog: store.landingDialog,
riskNoticeDialog: store.riskNoticeDialog,
update: store.update,
const { landingDialog, riskNoticeDialog, update } = useGlobalStore(
(store) => ({
landingDialog: store.landingDialog,
riskNoticeDialog: store.riskNoticeDialog,
update: store.update,
})
);
const { pageTitle, updateTitle } = usePageTitleStore((store) => ({
pageTitle: store.pageTitle,
updateTitle: store.updateTitle,
updateMarketId: store.updateMarketId,
}));
const { open: openAssetDetailsDialog } = useAssetDetailsDialogStore();
@ -63,11 +62,11 @@ const MarketPage = ({
const onSelect = useCallback(
(id: string) => {
if (id && id !== marketId) {
updateMarketId(id);
update({ marketId: id });
push(`/markets/${id}`);
}
},
[marketId, updateMarketId, push]
[marketId, update, push]
);
const variables = useMemo(
@ -86,20 +85,22 @@ const MarketPage = ({
skip: !marketId,
});
const marketName = data?.tradableInstrument.instrument.name;
const updateProvider = useCallback(
({ data: marketData }: { data: MarketData }) => {
const marketName = data?.tradableInstrument.instrument.name;
const marketPrice = calculatePrice(
marketData.markPrice,
data?.decimalPlaces
);
if (marketName) {
const pageTitle = titlefy([marketName, marketPrice]);
updateTitle(pageTitle);
const newPageTitle = titlefy([marketName, marketPrice]);
if (pageTitle !== newPageTitle) {
updateTitle(newPageTitle);
}
}
return true;
},
[updateTitle, data?.tradableInstrument.instrument.name, data?.decimalPlaces]
[updateTitle, pageTitle, marketName, data?.decimalPlaces]
);
useDataProvider<MarketData, MarketDataUpdateFieldsFragment>({
@ -110,6 +111,16 @@ const MarketPage = ({
updateOnInit: true,
});
const tradeView = useMemo(() => {
if (!data) {
return null;
}
if (w > 960) {
return <TradeGrid market={data} onSelect={onSelect} />;
}
return <TradePanels market={data} onSelect={onSelect} />;
}, [w, data, onSelect]);
if (!marketId) {
return (
<Splash>
@ -129,11 +140,7 @@ const MarketPage = ({
}
return (
<>
{w > 960 ? (
<TradeGrid market={data} onSelect={onSelect} />
) : (
<TradePanels market={data} onSelect={onSelect} />
)}
{tradeView}
<SelectMarketDialog
dialogOpen={landingDialog && !riskNoticeDialog}
setDialogOpen={(isOpen: boolean) =>

View File

@ -1,16 +1,19 @@
import { useRouter } from 'next/router';
import { MarketsContainer } from '@vegaprotocol/market-list';
import { useGlobalStore } from '../../stores';
import { useGlobalStore, usePageTitleStore } from '../../stores';
import { useEffect } from 'react';
import { titlefy } from '@vegaprotocol/react-helpers';
const Markets = () => {
const { update } = useGlobalStore((store) => ({ update: store.update }));
const { updateTitle } = usePageTitleStore((store) => ({
updateTitle: store.updateTitle,
}));
useEffect(() => {
update({ pageTitle: titlefy(['Markets']) });
}, [update]);
updateTitle(titlefy(['Markets']));
}, [updateTitle]);
const router = useRouter();
return (
<MarketsContainer
onSelect={(marketId) => {

View File

@ -1,16 +1,17 @@
import { t, titlefy } from '@vegaprotocol/react-helpers';
import { Web3Container } from '@vegaprotocol/web3';
import { useEffect } from 'react';
import { useGlobalStore } from '../../../stores';
import { usePageTitleStore } from '../../../stores';
import { DepositContainer } from './deposit-container';
const Deposit = () => {
const { update } = useGlobalStore((store) => ({
update: store.update,
const { updateTitle } = usePageTitleStore((store) => ({
updateTitle: store.updateTitle,
}));
useEffect(() => {
update({ pageTitle: titlefy([t('Deposits')]) });
}, [update]);
updateTitle(titlefy([t('Deposits')]));
}, [updateTitle]);
return (
<Web3Container>

View File

@ -10,16 +10,16 @@ import { VegaWalletContainer } from '../../components/vega-wallet-container';
import { DepositsContainer } from './deposits-container';
import { ResizableGrid } from '@vegaprotocol/ui-toolkit';
import { LayoutPriority } from 'allotment';
import { useGlobalStore } from '../../stores';
import { usePageTitleStore } from '../../stores';
import { AccountsContainer } from './accounts-container';
const Portfolio = () => {
const { update } = useGlobalStore((store) => ({
update: store.update,
const { updateTitle } = usePageTitleStore((store) => ({
updateTitle: store.updateTitle,
}));
useEffect(() => {
update({ pageTitle: titlefy([t('Portfolio')]) });
}, [update]);
updateTitle(titlefy([t('Portfolio')]));
}, [updateTitle]);
const wrapperClasses = 'h-full max-h-full flex flex-col';
const tabContentClassName = 'h-full grid grid-rows-[min-content_1fr]';
return (

View File

@ -2,33 +2,32 @@ import { LocalStorage } from '@vegaprotocol/react-helpers';
import create from 'zustand';
interface GlobalStore {
connectDialog: boolean;
networkSwitcherDialog: boolean;
landingDialog: boolean;
riskNoticeDialog: boolean;
marketId: string | null;
pageTitle: string | null;
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
}
interface PageTitleStore {
pageTitle: string | null;
updateTitle: (title: string) => void;
updateMarketId: (marketId: string) => void;
}
export const useGlobalStore = create<GlobalStore>((set) => ({
connectDialog: false,
networkSwitcherDialog: false,
landingDialog: false,
riskNoticeDialog: false,
marketId: LocalStorage.getItem('marketId') || null,
pageTitle: null,
update: (state) => {
set(state);
if (state.marketId) {
LocalStorage.setItem('marketId', state.marketId);
}
},
updateTitle: (title: string) => set({ pageTitle: title }),
updateMarketId: (marketId: string) => {
set({ marketId });
LocalStorage.setItem('marketId', marketId);
},
}));
export const usePageTitleStore = create<PageTitleStore>((set) => ({
pageTitle: null,
updateTitle: (title: string) => set({ pageTitle: title }),
}));

View File

@ -20,6 +20,14 @@ import { EnvironmentProvider } from '@vegaprotocol/environment';
import type { ChainIdQuery } from '@vegaprotocol/react-helpers';
import { ChainIdDocument } from '@vegaprotocol/react-helpers';
const mockUpdateDialogOpen = jest.fn();
const mockCloseVegaDialog = jest.fn();
jest.mock('zustand', () => () => () => ({
updateVegaWalletDialog: mockUpdateDialogOpen,
closeVegaWalletDialog: mockCloseVegaDialog,
vegaWalletDialogOpen: true,
}));
let defaultProps: VegaConnectDialogProps;
const rest = new RestConnector();
@ -29,10 +37,9 @@ const connectors = {
jsonRpc,
};
beforeEach(() => {
jest.clearAllMocks();
defaultProps = {
connectors,
dialogOpen: true,
setDialogOpen: jest.fn(),
};
});
@ -122,7 +129,7 @@ describe('VegaConnectDialog', () => {
expect(spy).toHaveBeenCalledWith(fields);
expect(defaultProps.setDialogOpen).toHaveBeenCalledWith(false);
expect(mockCloseVegaDialog).toHaveBeenCalled();
});
it('handles failed connection', async () => {
@ -149,7 +156,7 @@ describe('VegaConnectDialog', () => {
expect(spy).toHaveBeenCalledWith(fields);
expect(screen.getByTestId('form-error')).toHaveTextContent(errMessage);
expect(defaultProps.setDialogOpen).not.toHaveBeenCalled();
expect(mockUpdateDialogOpen).not.toHaveBeenCalled();
// Fetch failed due to wallet not running
spy = jest
@ -249,9 +256,7 @@ describe('VegaConnectDialog', () => {
});
it('connects with permission update', async () => {
const mockSetDialog = jest.fn();
render(generateJSX({ setDialogOpen: mockSetDialog }));
render(generateJSX());
await selectJsonRpc();
// Wallet version check
@ -299,7 +304,7 @@ describe('VegaConnectDialog', () => {
await act(async () => {
jest.advanceTimersByTime(CLOSE_DELAY);
});
expect(mockSetDialog).toHaveBeenCalledWith(false);
expect(mockCloseVegaDialog).toHaveBeenCalledWith();
});
it('handles incompatible wallet', async () => {

View File

@ -1,3 +1,4 @@
import create from 'zustand';
import {
Button,
Dialog,
@ -28,15 +29,50 @@ type WalletType = 'gui' | 'cli' | 'hosted';
export interface VegaConnectDialogProps {
connectors: Connectors;
dialogOpen: boolean;
setDialogOpen: (isOpen: boolean) => void;
onChangeOpen?: (open: boolean) => void;
}
export const useVegaWalletDialogStore = create<VegaWalletDialogStore>(
(set) => ({
vegaWalletDialogOpen: false,
updateVegaWalletDialog: (open: boolean) =>
set({ vegaWalletDialogOpen: open }),
openVegaWalletDialog: () => set({ vegaWalletDialogOpen: true }),
closeVegaWalletDialog: () => set({ vegaWalletDialogOpen: false }),
})
);
interface VegaWalletDialogStore {
vegaWalletDialogOpen: boolean;
updateVegaWalletDialog: (open: boolean) => void;
openVegaWalletDialog: () => void;
closeVegaWalletDialog: () => void;
}
export const VegaConnectDialog = ({
connectors,
dialogOpen,
setDialogOpen,
onChangeOpen,
}: VegaConnectDialogProps) => {
const {
vegaWalletDialogOpen,
closeVegaWalletDialog,
updateVegaWalletDialog,
} = useVegaWalletDialogStore((store) => ({
vegaWalletDialogOpen: store.vegaWalletDialogOpen,
updateVegaWalletDialog: onChangeOpen
? (open: boolean) => {
store.updateVegaWalletDialog(open);
onChangeOpen(open);
}
: store.updateVegaWalletDialog,
closeVegaWalletDialog: onChangeOpen
? () => {
store.closeVegaWalletDialog();
onChangeOpen(false);
}
: store.closeVegaWalletDialog,
}));
const { data, error, loading } = useChainIdQuery();
const renderContent = () => {
@ -66,14 +102,18 @@ export const VegaConnectDialog = ({
return (
<ConnectDialogContainer
connectors={connectors}
closeDialog={() => setDialogOpen(false)}
closeDialog={closeVegaWalletDialog}
appChainId={data.statistics.chainId}
/>
);
};
return (
<Dialog open={dialogOpen} size="small" onChange={setDialogOpen}>
<Dialog
open={vegaWalletDialogOpen}
size="small"
onChange={updateVegaWalletDialog}
>
{renderContent()}
</Dialog>
);