feat: page title (660) (#1437)
* feat: page title (660) * fix: trading-e2e home tests
This commit is contained in:
parent
483cf05050
commit
d271f28b82
@ -63,9 +63,13 @@ describe('home', { tags: '@regression' }, () => {
|
||||
},
|
||||
};
|
||||
aliasQuery(req, 'Markets', data);
|
||||
aliasQuery(req, 'MarketsDataQuery', data);
|
||||
aliasQuery(req, 'MarketsCandlesQuery', data);
|
||||
});
|
||||
cy.visit('/');
|
||||
cy.wait('@Markets');
|
||||
cy.wait('@MarketsDataQuery');
|
||||
cy.wait('@MarketsCandlesQuery');
|
||||
cy.url().should('eq', Cypress.config().baseUrl + '/markets');
|
||||
});
|
||||
});
|
||||
|
@ -3,7 +3,11 @@ 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 { EnvironmentProvider } from '@vegaprotocol/environment';
|
||||
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';
|
||||
@ -14,19 +18,32 @@ import {
|
||||
useAssetDetailsDialogStore,
|
||||
} from '@vegaprotocol/assets';
|
||||
import { Footer } from '../components/footer';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
||||
|
||||
function AppBody({ Component, pageProps }: AppProps) {
|
||||
const { connectDialog, update } = useGlobalStore((store) => ({
|
||||
const { connectDialog, pageTitle, update } = useGlobalStore((store) => ({
|
||||
connectDialog: store.connectDialog,
|
||||
pageTitle: store.pageTitle,
|
||||
update: store.update,
|
||||
}));
|
||||
const { isOpen, symbol, trigger, setOpen } = useAssetDetailsDialogStore();
|
||||
const [theme, toggleTheme] = useThemeSwitcher();
|
||||
|
||||
const { VEGA_ENV } = useEnvironment();
|
||||
const networkName = envTriggerMapping[VEGA_ENV];
|
||||
|
||||
const title = useMemo(() => {
|
||||
if (!pageTitle) return DEFAULT_TITLE;
|
||||
if (networkName) return `${pageTitle} [${networkName}]`;
|
||||
return pageTitle;
|
||||
}, [pageTitle, networkName]);
|
||||
|
||||
return (
|
||||
<ThemeContext.Provider value={theme}>
|
||||
<Head>
|
||||
<title>{t('Welcome to Vega trading!')}</title>
|
||||
<title>{title}</title>
|
||||
</Head>
|
||||
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
|
||||
<AppLoader>
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { activeMarketsProvider } from '@vegaprotocol/market-list';
|
||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
||||
import { useMarketList } from '@vegaprotocol/market-list';
|
||||
import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/react-helpers';
|
||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||
import { useRouter } from 'next/router';
|
||||
import { useEffect } from 'react';
|
||||
@ -9,10 +9,7 @@ export function Index() {
|
||||
const { replace } = useRouter();
|
||||
// The default market selected in the platform behind the overlay
|
||||
// should be the oldest market that is currently trading in continuous mode(i.e. not in auction).
|
||||
const { data, error, loading } = useDataProvider({
|
||||
dataProvider: activeMarketsProvider,
|
||||
noUpdate: true,
|
||||
});
|
||||
const { data, error, loading } = useMarketList();
|
||||
const { riskNoticeDialog, update } = useGlobalStore((store) => ({
|
||||
riskNoticeDialog: store.riskNoticeDialog,
|
||||
update: store.update,
|
||||
@ -22,11 +19,19 @@ export function Index() {
|
||||
update({ landingDialog: true });
|
||||
|
||||
if (data) {
|
||||
const marketId = data[0]?.id;
|
||||
const marketId = data.markets[0]?.id;
|
||||
const marketName = data.markets[0]?.tradableInstrument.instrument.name;
|
||||
const marketPrice = data.marketsData[0]?.markPrice
|
||||
? addDecimalsFormatNumber(
|
||||
data.marketsData[0]?.markPrice,
|
||||
data.markets[0].decimalPlaces
|
||||
)
|
||||
: null;
|
||||
const pageTitle = titlefy([marketName, marketPrice]);
|
||||
|
||||
if (marketId) {
|
||||
replace(`/markets/${marketId}`);
|
||||
update({ marketId });
|
||||
update({ marketId, pageTitle });
|
||||
}
|
||||
// Fallback to the markets list page
|
||||
else {
|
||||
|
@ -1,13 +1,16 @@
|
||||
import { gql } from '@apollo/client';
|
||||
import { gql, useQuery } from '@apollo/client';
|
||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||
import { ColumnKind, SelectMarketDialog } from '@vegaprotocol/market-list';
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import {
|
||||
addDecimalsFormatNumber,
|
||||
t,
|
||||
titlefy,
|
||||
} from '@vegaprotocol/react-helpers';
|
||||
import { Interval } from '@vegaprotocol/types';
|
||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||
import debounce from 'lodash/debounce';
|
||||
import { useRouter } from 'next/router';
|
||||
import React, { useEffect, useMemo, useState } from 'react';
|
||||
import { PageQueryContainer } from '../../components/page-query-container';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
import { TradeGrid, TradePanels } from './trade-grid';
|
||||
import type { Market, MarketVariables } from './__generated__/Market';
|
||||
@ -120,6 +123,30 @@ const MarketPage = ({ id }: { id?: string }) => {
|
||||
[marketId, yTimestamp]
|
||||
);
|
||||
|
||||
const { data, error, loading } = useQuery<Market, MarketVariables>(
|
||||
MARKET_QUERY,
|
||||
{
|
||||
variables,
|
||||
fetchPolicy: 'network-only',
|
||||
errorPolicy: 'ignore',
|
||||
}
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const marketName = data?.market?.tradableInstrument.instrument.name;
|
||||
const marketPrice =
|
||||
data?.market && data?.market?.data
|
||||
? addDecimalsFormatNumber(
|
||||
data.market.data.markPrice,
|
||||
data.market.decimalPlaces
|
||||
)
|
||||
: null;
|
||||
if (marketName) {
|
||||
const pageTitle = titlefy([marketName, marketPrice]);
|
||||
update({ pageTitle });
|
||||
}
|
||||
}, [data, update]);
|
||||
|
||||
if (!marketId) {
|
||||
return (
|
||||
<Splash>
|
||||
@ -129,18 +156,14 @@ const MarketPage = ({ id }: { id?: string }) => {
|
||||
}
|
||||
|
||||
return (
|
||||
<PageQueryContainer<Market, MarketVariables>
|
||||
query={MARKET_QUERY}
|
||||
data-testid="market"
|
||||
options={{
|
||||
variables,
|
||||
fetchPolicy: 'network-only',
|
||||
}}
|
||||
<AsyncRenderer<Market>
|
||||
loading={loading}
|
||||
error={error}
|
||||
data={data}
|
||||
render={({ market }) => {
|
||||
if (!market) {
|
||||
return <Splash>{t('Market not found')}</Splash>;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{w > 960 ? (
|
||||
|
@ -1,9 +1,15 @@
|
||||
import { useRouter } from 'next/router';
|
||||
import { MarketsContainer } from '@vegaprotocol/market-list';
|
||||
import { useGlobalStore } from '../../stores';
|
||||
import { useEffect } from 'react';
|
||||
import { titlefy } from '@vegaprotocol/react-helpers';
|
||||
|
||||
const Markets = () => {
|
||||
const { update } = useGlobalStore((store) => ({ update: store.update }));
|
||||
useEffect(() => {
|
||||
update({ pageTitle: titlefy(['Markets']) });
|
||||
}, [update]);
|
||||
|
||||
const router = useRouter();
|
||||
return (
|
||||
<MarketsContainer
|
||||
|
@ -1,8 +1,17 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { t, titlefy } from '@vegaprotocol/react-helpers';
|
||||
import { Web3Container } from '@vegaprotocol/web3';
|
||||
import { useEffect } from 'react';
|
||||
import { useGlobalStore } from '../../../stores';
|
||||
import { DepositContainer } from './deposit-container';
|
||||
|
||||
const Deposit = () => {
|
||||
const { update } = useGlobalStore((store) => ({
|
||||
update: store.update,
|
||||
}));
|
||||
useEffect(() => {
|
||||
update({ pageTitle: titlefy([t('Deposits')]) });
|
||||
}, [update]);
|
||||
|
||||
return (
|
||||
<Web3Container>
|
||||
<div className="max-w-[420px] p-8 mx-auto">
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { t } from '@vegaprotocol/react-helpers';
|
||||
import { t, titlefy } from '@vegaprotocol/react-helpers';
|
||||
import { PositionsContainer } from '@vegaprotocol/positions';
|
||||
import { OrderListContainer } from '@vegaprotocol/orders';
|
||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||
@ -6,12 +6,20 @@ import { ResizableGridPanel, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
||||
import { WithdrawalsContainer } from './withdrawals-container';
|
||||
import { FillsContainer } from '@vegaprotocol/fills';
|
||||
import type { ReactNode } from 'react';
|
||||
import { useEffect } from 'react';
|
||||
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';
|
||||
|
||||
const Portfolio = () => {
|
||||
const { update } = useGlobalStore((store) => ({
|
||||
update: store.update,
|
||||
}));
|
||||
useEffect(() => {
|
||||
update({ pageTitle: titlefy([t('Portfolio')]) });
|
||||
}, [update]);
|
||||
const wrapperClasses = 'h-full max-h-full flex flex-col';
|
||||
const tabContentClassName = 'h-full grid grid-rows-[min-content_1fr]';
|
||||
return (
|
||||
|
@ -6,6 +6,7 @@ interface GlobalStore {
|
||||
landingDialog: boolean;
|
||||
riskNoticeDialog: boolean;
|
||||
marketId: string | null;
|
||||
pageTitle: string | null;
|
||||
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
|
||||
}
|
||||
|
||||
@ -15,6 +16,7 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
|
||||
landingDialog: false,
|
||||
riskNoticeDialog: false,
|
||||
marketId: null,
|
||||
pageTitle: null,
|
||||
update: (state) => {
|
||||
set(state);
|
||||
},
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { truncateByChars, ELLIPSIS, shorten } from './strings';
|
||||
import { truncateByChars, ELLIPSIS, shorten, titlefy } from './strings';
|
||||
|
||||
describe('truncateByChars', () => {
|
||||
it.each([
|
||||
@ -27,3 +27,25 @@ describe('shorten', () => {
|
||||
expect(output).toStrictEqual(o);
|
||||
});
|
||||
});
|
||||
|
||||
describe('titlefy', () => {
|
||||
it.each([
|
||||
{ words: [], o: 'Vega' },
|
||||
{ words: ['one'], o: 'one - Vega' },
|
||||
{ words: ['one'], o: 'one - Vega' },
|
||||
{
|
||||
words: ['one', 'two', 'three'],
|
||||
o: 'one - two - three - Vega',
|
||||
},
|
||||
{
|
||||
words: ['one', null, undefined, 'two'],
|
||||
o: 'one - two - Vega',
|
||||
},
|
||||
{
|
||||
words: ['VEGAUSD', '123.22'],
|
||||
o: 'VEGAUSD - 123.22 - Vega',
|
||||
},
|
||||
])('should convert to title-like string', ({ words, o }) => {
|
||||
expect(titlefy(words)).toEqual(o);
|
||||
});
|
||||
});
|
||||
|
@ -17,3 +17,12 @@ export function shorten(input: string, limit?: number) {
|
||||
const suffix = output.length < limit ? ELLIPSIS : '';
|
||||
return input.substring(0, limit - 1) + suffix;
|
||||
}
|
||||
|
||||
const TITLE_SEPARATOR = ' - ';
|
||||
const TITLE_SUFFIX = 'Vega';
|
||||
export function titlefy(words: (string | null | undefined)[]) {
|
||||
const title = [...words, TITLE_SUFFIX]
|
||||
.filter((w) => w && w.length > 0)
|
||||
.join(TITLE_SEPARATOR);
|
||||
return title;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user