Commit 08f56b55 authored by isstuev's avatar isstuev

indexing alert

parent d402eecf
......@@ -5,6 +5,7 @@ import type { NewBlockSocketResponse } from 'types/api/block';
export type SocketMessageParams = SocketMessage.NewBlock |
SocketMessage.BlocksIndexStatus |
SocketMessage.InternalTxsIndexStatus |
SocketMessage.TxStatusUpdate |
SocketMessage.NewTx |
SocketMessage.NewPendingTx |
......@@ -23,7 +24,8 @@ interface SocketMessageParamsGeneric<Event extends string | undefined, Payload e
// eslint-disable-next-line @typescript-eslint/no-namespace
export namespace SocketMessage {
export type NewBlock = SocketMessageParamsGeneric<'new_block', NewBlockSocketResponse>;
export type BlocksIndexStatus = SocketMessageParamsGeneric<'index_status', {finished: boolean; ratio: string}>;
export type BlocksIndexStatus = SocketMessageParamsGeneric<'block_index_status', {finished: boolean; ratio: string}>;
export type InternalTxsIndexStatus = SocketMessageParamsGeneric<'internal_txs_index_status', {finished: boolean; ratio: string}>;
export type TxStatusUpdate = SocketMessageParamsGeneric<'collated', NewBlockSocketResponse>;
export type NewTx = SocketMessageParamsGeneric<'transaction', { transaction: number }>;
export type NewPendingTx = SocketMessageParamsGeneric<'pending_transaction', { pending_transaction: number }>;
......
import handler from 'lib/api/handler';
const getUrl = () => '/v2/main-page/indexing-status';
const requestHandler = handler(getUrl, [ 'GET' ]);
export default requestHandler;
export type IndexingStatus = {
finished_indexing: boolean;
finished_indexing_blocks: boolean;
indexed_blocks_ratio: string;
indexed_inernal_transactions_ratio: string;
}
......@@ -4,6 +4,7 @@ export enum QueryKeys {
txsValidate = 'txs-validated',
txsPending = 'txs-pending',
homeStats='homeStats',
indexingStatus='indexingStatus',
stats='stats',
charts='stats',
tx = 'tx',
......
import { Alert, AlertIcon, AlertTitle, chakra } from '@chakra-ui/react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import React from 'react';
import type { SocketMessage } from 'lib/socket/types';
import type { IndexingStatus } from 'types/api/indexingStatus';
import { QueryKeys } from 'types/client/queries';
import useFetch from 'lib/hooks/useFetch';
import useIsMobile from 'lib/hooks/useIsMobile';
import { nbsp, ndash } from 'lib/html-entities';
import useSocketChannel from 'lib/socket/useSocketChannel';
import useSocketMessage from 'lib/socket/useSocketMessage';
const IndexingAlert = ({ className }: { className?: string }) => {
const fetch = useFetch();
const isMobile = useIsMobile();
const { data } = useQuery<unknown, unknown, IndexingStatus>(
[ QueryKeys.indexingStatus ],
async() => await fetch(`/node-api/index/indexing-status`),
);
const queryClient = useQueryClient();
const handleBlocksIndexStatus: SocketMessage.BlocksIndexStatus['handler'] = React.useCallback((payload) => {
queryClient.setQueryData([ QueryKeys.indexingStatus ], (prevData: IndexingStatus | undefined) => {
const newData = prevData ? { ...prevData } : {} as IndexingStatus;
newData.finished_indexing_blocks = payload.finished;
newData.indexed_blocks_ratio = payload.ratio;
return newData;
});
}, [ queryClient ]);
const blockIndexingChannel = useSocketChannel({
topic: 'blocks:indexing',
isDisabled: !data || data.finished_indexing_blocks,
});
useSocketMessage({
channel: blockIndexingChannel,
event: 'block_index_status',
handler: handleBlocksIndexStatus,
});
const handleIntermalTxsIndexStatus: SocketMessage.InternalTxsIndexStatus['handler'] = React.useCallback((payload) => {
queryClient.setQueryData([ QueryKeys.indexingStatus ], (prevData: IndexingStatus | undefined) => {
const newData = prevData ? { ...prevData } : {} as IndexingStatus;
newData.finished_indexing = payload.finished;
newData.indexed_inernal_transactions_ratio = payload.ratio;
return newData;
});
}, [ queryClient ]);
const internalTxsIndexingChannel = useSocketChannel({
topic: 'blocks:indexing_internal_transactions',
isDisabled: !data || data.finished_indexing,
});
useSocketMessage({
channel: internalTxsIndexingChannel,
event: 'internal_txs_index_status',
handler: handleIntermalTxsIndexStatus,
});
if (!data) {
return null;
}
let content;
if (data.finished_indexing_blocks === false) {
content = `${ data.indexed_blocks_ratio && `${ (Number(data.indexed_blocks_ratio) * 100).toFixed() }% Blocks Indexed${ nbsp }${ ndash } ` }
We're indexing this chain right now. Some of the counts may be inaccurate.` ;
} else if (data.finished_indexing === false) {
content = `${ data.indexed_inernal_transactions_ratio &&
`${ (Number(data.indexed_inernal_transactions_ratio) * 100).toFixed() }% Blocks With Internal Transactions Indexed${ nbsp }${ ndash } ` }
We're indexing this chain right now. Some of the counts may be inaccurate.`;
}
if (!content) {
return null;
}
return (
<Alert status="warning" variant="solid" py={ 3 } borderRadius="12px" mb={ 6 } className={ className }>
{ !isMobile && <AlertIcon/> }
<AlertTitle>
{ content }
</AlertTitle>
</Alert>
);
};
export default chakra(IndexingAlert);
import { test, expect } from '@playwright/experimental-ct-react';
import React from 'react';
import TestApp from 'playwright/TestApp';
import Page from './Page';
const API_URL = '/node-api/index/indexing-status';
test('without indexing alert +@mobile', async({ mount }) => {
const component = await mount(
<TestApp>
<Page>Page Content</Page>
</TestApp>,
);
await expect(component).toHaveScreenshot();
});
test('with indexing alert +@mobile', async({ mount, page }) => {
await page.route(API_URL, (route) => route.fulfill({
status: 200,
body: JSON.stringify({ finished_indexing_blocks: false, indexed_blocks_ratio: 0.1 }),
}));
const component = await mount(
<TestApp>
<Page>Page Content</Page>
</TestApp>,
);
await page.waitForResponse(API_URL),
await expect(component).toHaveScreenshot();
});
import { Box } from '@chakra-ui/react';
import React from 'react';
import IndexingAlert from 'ui/home/IndexingAlert';
interface Props {
children: React.ReactNode;
isHomePage?: boolean;
......@@ -13,8 +15,9 @@ const PageContent = ({ children, isHomePage }: Props) => {
w="100%"
paddingX={{ base: 4, lg: 12 }}
paddingBottom={ 10 }
paddingTop={{ base: isHomePage ? '88px' : '138px', lg: isHomePage ? 9 : 0 }}
paddingTop={{ base: isHomePage ? '88px' : '138px', lg: 0 }}
>
<IndexingAlert display={{ base: 'block', lg: 'none' }}/>
{ children }
</Box>
);
......
......@@ -2,6 +2,7 @@ import { HStack, Box, Flex, useColorModeValue } from '@chakra-ui/react';
import React from 'react';
import { useScrollDirection } from 'lib/contexts/scrollDirection';
import IndexingAlert from 'ui/home/IndexingAlert';
import NetworkLogo from 'ui/snippets/networkMenu/NetworkLogo';
import ProfileMenuDesktop from 'ui/snippets/profileMenu/ProfileMenuDesktop';
import ProfileMenuMobile from 'ui/snippets/profileMenu/ProfileMenuMobile';
......@@ -44,6 +45,12 @@ const Header = ({ hideOnScrollDown, isHomePage }: Props) => {
</Flex>
{ !isHomePage && <SearchBar withShadow={ !hideOnScrollDown }/> }
</Box>
<Box
paddingX={ 12 }
paddingTop={ 9 }
display={{ base: 'none', lg: 'block' }}
>
<IndexingAlert/>
{ !isHomePage && (
<HStack
as="header"
......@@ -51,9 +58,6 @@ const Header = ({ hideOnScrollDown, isHomePage }: Props) => {
alignItems="center"
justifyContent="center"
gap={ 12 }
display={{ base: 'none', lg: 'flex' }}
paddingX={ 12 }
paddingTop={ 9 }
paddingBottom="52px"
>
<Box width="100%">
......@@ -63,6 +67,7 @@ const Header = ({ hideOnScrollDown, isHomePage }: Props) => {
<ProfileMenuDesktop/>
</HStack>
) }
</Box>
</>
);
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment