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, 'Markets', data);
|
||||||
|
aliasQuery(req, 'MarketsDataQuery', data);
|
||||||
|
aliasQuery(req, 'MarketsCandlesQuery', data);
|
||||||
});
|
});
|
||||||
cy.visit('/');
|
cy.visit('/');
|
||||||
cy.wait('@Markets');
|
cy.wait('@Markets');
|
||||||
|
cy.wait('@MarketsDataQuery');
|
||||||
|
cy.wait('@MarketsCandlesQuery');
|
||||||
cy.url().should('eq', Cypress.config().baseUrl + '/markets');
|
cy.url().should('eq', Cypress.config().baseUrl + '/markets');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,7 +3,11 @@ import Head from 'next/head';
|
|||||||
import { Navbar } from '../components/navbar';
|
import { Navbar } from '../components/navbar';
|
||||||
import { t, ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
import { t, ThemeContext, useThemeSwitcher } from '@vegaprotocol/react-helpers';
|
||||||
import { VegaConnectDialog, VegaWalletProvider } from '@vegaprotocol/wallet';
|
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 { Connectors } from '../lib/vega-connectors';
|
||||||
import { AppLoader } from '../components/app-loader';
|
import { AppLoader } from '../components/app-loader';
|
||||||
import { RiskNoticeDialog } from '../components/risk-notice-dialog';
|
import { RiskNoticeDialog } from '../components/risk-notice-dialog';
|
||||||
@ -14,19 +18,32 @@ import {
|
|||||||
useAssetDetailsDialogStore,
|
useAssetDetailsDialogStore,
|
||||||
} from '@vegaprotocol/assets';
|
} from '@vegaprotocol/assets';
|
||||||
import { Footer } from '../components/footer';
|
import { Footer } from '../components/footer';
|
||||||
|
import { useMemo } from 'react';
|
||||||
|
|
||||||
|
const DEFAULT_TITLE = t('Welcome to Vega trading!');
|
||||||
|
|
||||||
function AppBody({ Component, pageProps }: AppProps) {
|
function AppBody({ Component, pageProps }: AppProps) {
|
||||||
const { connectDialog, update } = useGlobalStore((store) => ({
|
const { connectDialog, pageTitle, update } = useGlobalStore((store) => ({
|
||||||
connectDialog: store.connectDialog,
|
connectDialog: store.connectDialog,
|
||||||
|
pageTitle: store.pageTitle,
|
||||||
update: store.update,
|
update: store.update,
|
||||||
}));
|
}));
|
||||||
const { isOpen, symbol, trigger, setOpen } = useAssetDetailsDialogStore();
|
const { isOpen, symbol, trigger, setOpen } = useAssetDetailsDialogStore();
|
||||||
const [theme, toggleTheme] = useThemeSwitcher();
|
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 (
|
return (
|
||||||
<ThemeContext.Provider value={theme}>
|
<ThemeContext.Provider value={theme}>
|
||||||
<Head>
|
<Head>
|
||||||
<title>{t('Welcome to Vega trading!')}</title>
|
<title>{title}</title>
|
||||||
</Head>
|
</Head>
|
||||||
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
|
<div className="h-full relative dark:bg-black dark:text-white z-0 grid grid-rows-[min-content,1fr,min-content]">
|
||||||
<AppLoader>
|
<AppLoader>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { activeMarketsProvider } from '@vegaprotocol/market-list';
|
import { useMarketList } from '@vegaprotocol/market-list';
|
||||||
import { useDataProvider } from '@vegaprotocol/react-helpers';
|
import { addDecimalsFormatNumber, titlefy } from '@vegaprotocol/react-helpers';
|
||||||
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer } from '@vegaprotocol/ui-toolkit';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { useEffect } from 'react';
|
import { useEffect } from 'react';
|
||||||
@ -9,10 +9,7 @@ export function Index() {
|
|||||||
const { replace } = useRouter();
|
const { replace } = useRouter();
|
||||||
// The default market selected in the platform behind the overlay
|
// 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).
|
// should be the oldest market that is currently trading in continuous mode(i.e. not in auction).
|
||||||
const { data, error, loading } = useDataProvider({
|
const { data, error, loading } = useMarketList();
|
||||||
dataProvider: activeMarketsProvider,
|
|
||||||
noUpdate: true,
|
|
||||||
});
|
|
||||||
const { riskNoticeDialog, update } = useGlobalStore((store) => ({
|
const { riskNoticeDialog, update } = useGlobalStore((store) => ({
|
||||||
riskNoticeDialog: store.riskNoticeDialog,
|
riskNoticeDialog: store.riskNoticeDialog,
|
||||||
update: store.update,
|
update: store.update,
|
||||||
@ -22,11 +19,19 @@ export function Index() {
|
|||||||
update({ landingDialog: true });
|
update({ landingDialog: true });
|
||||||
|
|
||||||
if (data) {
|
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) {
|
if (marketId) {
|
||||||
replace(`/markets/${marketId}`);
|
replace(`/markets/${marketId}`);
|
||||||
update({ marketId });
|
update({ marketId, pageTitle });
|
||||||
}
|
}
|
||||||
// Fallback to the markets list page
|
// Fallback to the markets list page
|
||||||
else {
|
else {
|
||||||
|
@ -1,13 +1,16 @@
|
|||||||
import { gql } from '@apollo/client';
|
import { gql, useQuery } from '@apollo/client';
|
||||||
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
import { useAssetDetailsDialogStore } from '@vegaprotocol/assets';
|
||||||
import { ColumnKind, SelectMarketDialog } from '@vegaprotocol/market-list';
|
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 { Interval } from '@vegaprotocol/types';
|
||||||
import { Splash } from '@vegaprotocol/ui-toolkit';
|
import { AsyncRenderer, Splash } from '@vegaprotocol/ui-toolkit';
|
||||||
import debounce from 'lodash/debounce';
|
import debounce from 'lodash/debounce';
|
||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import React, { useEffect, useMemo, useState } from 'react';
|
import React, { useEffect, useMemo, useState } from 'react';
|
||||||
import { PageQueryContainer } from '../../components/page-query-container';
|
|
||||||
import { useGlobalStore } from '../../stores';
|
import { useGlobalStore } from '../../stores';
|
||||||
import { TradeGrid, TradePanels } from './trade-grid';
|
import { TradeGrid, TradePanels } from './trade-grid';
|
||||||
import type { Market, MarketVariables } from './__generated__/Market';
|
import type { Market, MarketVariables } from './__generated__/Market';
|
||||||
@ -120,6 +123,30 @@ const MarketPage = ({ id }: { id?: string }) => {
|
|||||||
[marketId, yTimestamp]
|
[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) {
|
if (!marketId) {
|
||||||
return (
|
return (
|
||||||
<Splash>
|
<Splash>
|
||||||
@ -129,18 +156,14 @@ const MarketPage = ({ id }: { id?: string }) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<PageQueryContainer<Market, MarketVariables>
|
<AsyncRenderer<Market>
|
||||||
query={MARKET_QUERY}
|
loading={loading}
|
||||||
data-testid="market"
|
error={error}
|
||||||
options={{
|
data={data}
|
||||||
variables,
|
|
||||||
fetchPolicy: 'network-only',
|
|
||||||
}}
|
|
||||||
render={({ market }) => {
|
render={({ market }) => {
|
||||||
if (!market) {
|
if (!market) {
|
||||||
return <Splash>{t('Market not found')}</Splash>;
|
return <Splash>{t('Market not found')}</Splash>;
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{w > 960 ? (
|
{w > 960 ? (
|
||||||
|
@ -1,9 +1,15 @@
|
|||||||
import { useRouter } from 'next/router';
|
import { useRouter } from 'next/router';
|
||||||
import { MarketsContainer } from '@vegaprotocol/market-list';
|
import { MarketsContainer } from '@vegaprotocol/market-list';
|
||||||
import { useGlobalStore } from '../../stores';
|
import { useGlobalStore } from '../../stores';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { titlefy } from '@vegaprotocol/react-helpers';
|
||||||
|
|
||||||
const Markets = () => {
|
const Markets = () => {
|
||||||
const { update } = useGlobalStore((store) => ({ update: store.update }));
|
const { update } = useGlobalStore((store) => ({ update: store.update }));
|
||||||
|
useEffect(() => {
|
||||||
|
update({ pageTitle: titlefy(['Markets']) });
|
||||||
|
}, [update]);
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
return (
|
return (
|
||||||
<MarketsContainer
|
<MarketsContainer
|
||||||
|
@ -1,8 +1,17 @@
|
|||||||
import { t } from '@vegaprotocol/react-helpers';
|
import { t, titlefy } from '@vegaprotocol/react-helpers';
|
||||||
import { Web3Container } from '@vegaprotocol/web3';
|
import { Web3Container } from '@vegaprotocol/web3';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
import { useGlobalStore } from '../../../stores';
|
||||||
import { DepositContainer } from './deposit-container';
|
import { DepositContainer } from './deposit-container';
|
||||||
|
|
||||||
const Deposit = () => {
|
const Deposit = () => {
|
||||||
|
const { update } = useGlobalStore((store) => ({
|
||||||
|
update: store.update,
|
||||||
|
}));
|
||||||
|
useEffect(() => {
|
||||||
|
update({ pageTitle: titlefy([t('Deposits')]) });
|
||||||
|
}, [update]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Web3Container>
|
<Web3Container>
|
||||||
<div className="max-w-[420px] p-8 mx-auto">
|
<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 { PositionsContainer } from '@vegaprotocol/positions';
|
||||||
import { OrderListContainer } from '@vegaprotocol/orders';
|
import { OrderListContainer } from '@vegaprotocol/orders';
|
||||||
import { AccountsContainer } from '@vegaprotocol/accounts';
|
import { AccountsContainer } from '@vegaprotocol/accounts';
|
||||||
@ -6,12 +6,20 @@ import { ResizableGridPanel, Tab, Tabs } from '@vegaprotocol/ui-toolkit';
|
|||||||
import { WithdrawalsContainer } from './withdrawals-container';
|
import { WithdrawalsContainer } from './withdrawals-container';
|
||||||
import { FillsContainer } from '@vegaprotocol/fills';
|
import { FillsContainer } from '@vegaprotocol/fills';
|
||||||
import type { ReactNode } from 'react';
|
import type { ReactNode } from 'react';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
import { VegaWalletContainer } from '../../components/vega-wallet-container';
|
||||||
import { DepositsContainer } from './deposits-container';
|
import { DepositsContainer } from './deposits-container';
|
||||||
import { ResizableGrid } from '@vegaprotocol/ui-toolkit';
|
import { ResizableGrid } from '@vegaprotocol/ui-toolkit';
|
||||||
import { LayoutPriority } from 'allotment';
|
import { LayoutPriority } from 'allotment';
|
||||||
|
import { useGlobalStore } from '../../stores';
|
||||||
|
|
||||||
const Portfolio = () => {
|
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 wrapperClasses = 'h-full max-h-full flex flex-col';
|
||||||
const tabContentClassName = 'h-full grid grid-rows-[min-content_1fr]';
|
const tabContentClassName = 'h-full grid grid-rows-[min-content_1fr]';
|
||||||
return (
|
return (
|
||||||
|
@ -6,6 +6,7 @@ interface GlobalStore {
|
|||||||
landingDialog: boolean;
|
landingDialog: boolean;
|
||||||
riskNoticeDialog: boolean;
|
riskNoticeDialog: boolean;
|
||||||
marketId: string | null;
|
marketId: string | null;
|
||||||
|
pageTitle: string | null;
|
||||||
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
|
update: (store: Partial<Omit<GlobalStore, 'update'>>) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -15,6 +16,7 @@ export const useGlobalStore = create<GlobalStore>((set) => ({
|
|||||||
landingDialog: false,
|
landingDialog: false,
|
||||||
riskNoticeDialog: false,
|
riskNoticeDialog: false,
|
||||||
marketId: null,
|
marketId: null,
|
||||||
|
pageTitle: null,
|
||||||
update: (state) => {
|
update: (state) => {
|
||||||
set(state);
|
set(state);
|
||||||
},
|
},
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { truncateByChars, ELLIPSIS, shorten } from './strings';
|
import { truncateByChars, ELLIPSIS, shorten, titlefy } from './strings';
|
||||||
|
|
||||||
describe('truncateByChars', () => {
|
describe('truncateByChars', () => {
|
||||||
it.each([
|
it.each([
|
||||||
@ -27,3 +27,25 @@ describe('shorten', () => {
|
|||||||
expect(output).toStrictEqual(o);
|
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 : '';
|
const suffix = output.length < limit ? ELLIPSIS : '';
|
||||||
return input.substring(0, limit - 1) + suffix;
|
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