Commit ed7aa0ec authored by isstuev's avatar isstuev

refactoring and total fixes

parent 87d4e7a7
......@@ -372,18 +372,30 @@ export const RESOURCES = {
filterFields: [],
},
withdrawals_count: {
path: '/api/v2/optimism/withdrawals-count',
},
output_roots: {
path: '/api/v2/optimism/output-roots',
paginationFields: [ 'index' as const, 'items_count' as const ],
filterFields: [],
},
output_roots_count: {
path: '/api/v2/optimism/output-roots-count',
},
txn_batches: {
path: '/api/v2/optimism/txn-batches',
paginationFields: [ 'block_number' as const, 'items_count' as const ],
filterFields: [],
},
txn_batches_count: {
path: '/api/v2/optimism/txn-batches-count',
},
// DEPRECATED
old_api: {
path: '/api',
......@@ -508,6 +520,9 @@ Q extends 'contract_verification_config' ? SmartContractVerificationConfig :
Q extends 'output_roots' ? OutputRootsResponse :
Q extends 'withdrawals' ? WithdrawalsResponse :
Q extends 'txn_batches' ? TxnBatchesResponse :
Q extends 'output_roots_count' ? number :
Q extends 'withdrawals_count' ? number :
Q extends 'txn_batches_count' ? number :
never;
/* eslint-enable @typescript-eslint/indent */
......
......@@ -29,5 +29,4 @@ export const outputRootsData = {
index: 9877,
items_count: 50,
},
total: 9927,
};
......@@ -33,5 +33,4 @@ export const txnBatchesData = {
block_number: 5902834,
items_count: 50,
},
total: 1235016,
};
......@@ -47,5 +47,4 @@ export const data = {
items_count: 50,
nonce: '1766847064778384329583297500742918515827483896875618958121606201292620123',
},
total: 397,
};
......@@ -45,6 +45,7 @@ const OutputRootsListItem = ({ item }: Props) => {
value: (
<LinkExternal
w="100%"
display="inline-flex"
overflow="hidden"
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
>
......
......@@ -40,7 +40,11 @@ const OutputRootsTableItem = ({ item }: Props) => {
</Td>
<Td verticalAlign="middle" pr={ 12 }>
<Flex>
<LinkExternal w="100%" href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }>
<LinkExternal
w="100%"
display="inline-flex"
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
>
<Icon as={ txIcon } boxSize={ 6 } mr={ 1 }/>
<Box w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ item.l1_tx_hash }/></Box>
</LinkExternal>
......
......@@ -8,6 +8,7 @@ import buildApiUrl from 'playwright/utils/buildApiUrl';
import OutputRoots from './OutputRoots';
const OUTPUT_ROOTS_API_URL = buildApiUrl('output_roots');
const OUTPUT_ROOTS_COUNT_API_URL = buildApiUrl('output_roots_count');
test('base view +@mobile', async({ mount, page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
......@@ -20,6 +21,11 @@ test('base view +@mobile', async({ mount, page }) => {
body: JSON.stringify(outputRootsData),
}));
await page.route(OUTPUT_ROOTS_COUNT_API_URL, (route) => route.fulfill({
status: 200,
body: '9927',
}));
const component = await mount(
<TestApp>
<OutputRoots/>
......
import { Flex, Hide, Show, Skeleton, Text } from '@chakra-ui/react';
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import OutputRootsListItem from 'ui/outputRoots/OutputRootsListItem';
import OutputRootsTable from 'ui/outputRoots/OutputRootsTable';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
const OutputRoots = () => {
const isMobile = useIsMobile();
......@@ -20,31 +19,35 @@ const OutputRoots = () => {
resourceName: 'output_roots',
});
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
const countersQuery = useApiQuery('output_roots_count');
if (isLoading) {
return (
const content = data?.items ? (
<>
<Skeleton w={{ base: '100%', lg: '400px' }} h={{ base: '48px', lg: '26px' }} mb={{ base: 6, lg: 7 }} mt={{ base: 0, lg: 7 }}/>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable minW="900px" display={{ base: 'none', lg: 'block' }} columns={ [ '140px', '20%', '20%', '30%', '30%' ] }/>
<Show below="lg" ssr={ false }>{ data.items.map((item => <OutputRootsListItem key={ item.l2_output_index } item={ item }/>)) }</Show>
<Hide below="lg" ssr={ false }><OutputRootsTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
) : null;
const text = (() => {
if (countersQuery.isLoading || isLoading) {
return <Skeleton w={{ base: '100%', lg: '400px' }} h={{ base: '48px', lg: '26px' }} mb={{ base: 6, lg: 7 }} mt={{ base: 0, lg: 7 }}/>;
}
if (countersQuery.isError || isError || data?.items.length === 0) {
return null;
}
const text = (
return (
<Flex mb={{ base: 6, lg: 0 }} flexWrap="wrap">
L2 output index
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_output_index } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].l2_output_index } </Text>
(total of { data.total.toLocaleString('en') } roots)
(total of { countersQuery.data.toLocaleString('en') } roots)
</Flex>
);
})();
return (
const actionBar = (
<>
{ (isMobile || !isPaginationVisible) && text }
{ isPaginationVisible && (
......@@ -55,16 +58,21 @@ const OutputRoots = () => {
</Flex>
</ActionBar>
) }
<Show below="lg" ssr={ false }>{ data.items.map((item => <OutputRootsListItem key={ item.l2_output_index } item={ item }/>)) }</Show>
<Hide below="lg" ssr={ false }><OutputRootsTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
})();
return (
<Page>
<PageTitle text="Output roots" withTextAd/>
{ content }
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '140px', '20%', '20%', '30%', '30%' ] }}
emptyText="There are no output roots."
content={ content }
actionBar={ actionBar }
/>
</Page>
);
};
......
......@@ -8,6 +8,7 @@ import buildApiUrl from 'playwright/utils/buildApiUrl';
import TxnBatches from './TxnBatches';
const TXN_BATCHES_API_URL = buildApiUrl('txn_batches');
const TXN_BATCHES_COUNT_API_URL = buildApiUrl('txn_batches_count');
test('base view +@mobile', async({ mount, page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
......@@ -20,6 +21,11 @@ test('base view +@mobile', async({ mount, page }) => {
body: JSON.stringify(txnBatchesData),
}));
await page.route(TXN_BATCHES_COUNT_API_URL, (route) => route.fulfill({
status: 200,
body: '1235016',
}));
const component = await mount(
<TestApp>
<TxnBatches/>
......
import { Flex, Hide, Show, Skeleton, Text } from '@chakra-ui/react';
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { nbsp } from 'lib/html-entities';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import TxnBatchesListItem from 'ui/txnBatches/TxnBatchesListItem';
import TxnBatchesTable from 'ui/txnBatches/TxnBatchesTable';
......@@ -21,31 +20,35 @@ const TxnBatches = () => {
resourceName: 'txn_batches',
});
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
const countersQuery = useApiQuery('txn_batches_count');
if (isLoading) {
return (
const content = data?.items ? (
<>
<Skeleton w={{ base: '100%', lg: '400px' }} h={{ base: '48px', lg: '26px' }} mb={{ base: 6, lg: 7 }} mt={{ base: 0, lg: 7 }}/>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable display={{ base: 'none', lg: 'block' }} columns={ [ '170px', '170px', '160px', '100%', '150px' ] }/>
<Show below="lg" ssr={ false }>{ data.items.map((item => <TxnBatchesListItem key={ item.l2_block_number } item={ item }/>)) }</Show>
<Hide below="lg" ssr={ false }><TxnBatchesTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
) : null;
const text = (() => {
if (countersQuery.isLoading || isLoading) {
return <Skeleton w={{ base: '100%', lg: '400px' }} h={{ base: '48px', lg: '26px' }} mb={{ base: 6, lg: 7 }} mt={{ base: 0, lg: 7 }}/>;
}
if (countersQuery.isError || isError || data.items.length === 0) {
return null;
}
const text = (
<Flex mb={{ base: 6, lg: 0 }} flexWrap="wrap">
return (
<Flex mb={{ base: 6, lg: isPaginationVisible ? 0 : 6 }} flexWrap="wrap">
Tx batch (L2 block)
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[0].l2_block_number } </Text>to
<Text fontWeight={ 600 } whiteSpace="pre"> #{ data.items[data.items.length - 1].l2_block_number } </Text>
(total of { data.total.toLocaleString('en') } batches)
(total of { countersQuery.data.toLocaleString('en') } batches)
</Flex>
);
})();
return (
const actionBar = (
<>
{ (isMobile || !isPaginationVisible) && text }
{ isPaginationVisible && (
......@@ -56,16 +59,21 @@ const TxnBatches = () => {
</Flex>
</ActionBar>
) }
<Show below="lg" ssr={ false }>{ data.items.map((item => <TxnBatchesListItem key={ item.l2_block_number } item={ item }/>)) }</Show>
<Hide below="lg" ssr={ false }><TxnBatchesTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
})();
return (
<Page>
<PageTitle text={ `Tx batches (L2${ nbsp }blocks)` } withTextAd/>
{ content }
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: [ '170px', '170px', '160px', '100%', '150px' ] }}
emptyText="There are no tx batches."
content={ content }
actionBar={ actionBar }
/>
</Page>
);
};
......
......@@ -8,6 +8,7 @@ import buildApiUrl from 'playwright/utils/buildApiUrl';
import Withdrawals from './Withdrawals';
const WITHDRAWALS_API_URL = buildApiUrl('withdrawals');
const WITHDRAWALS_COUNT_API_URL = buildApiUrl('withdrawals_count');
test('base view +@mobile', async({ mount, page }) => {
await page.route('https://request-global.czilladx.com/serve/native.php?z=19260bf627546ab7242', (route) => route.fulfill({
......@@ -20,6 +21,11 @@ test('base view +@mobile', async({ mount, page }) => {
body: JSON.stringify(withdrawalsData),
}));
await page.route(WITHDRAWALS_COUNT_API_URL, (route) => route.fulfill({
status: 200,
body: '397',
}));
const component = await mount(
<TestApp>
<Withdrawals/>
......
import { Flex, Hide, Show, Skeleton, Text } from '@chakra-ui/react';
import React from 'react';
import useApiQuery from 'lib/api/useApiQuery';
import useIsMobile from 'lib/hooks/useIsMobile';
import useQueryWithPages from 'lib/hooks/useQueryWithPages';
import { rightLineArrow, nbsp } from 'lib/html-entities';
import ActionBar from 'ui/shared/ActionBar';
import DataFetchAlert from 'ui/shared/DataFetchAlert';
import DataListDisplay from 'ui/shared/DataListDisplay';
import Page from 'ui/shared/Page/Page';
import PageTitle from 'ui/shared/Page/PageTitle';
import Pagination from 'ui/shared/Pagination';
import SkeletonList from 'ui/shared/skeletons/SkeletonList';
import SkeletonTable from 'ui/shared/skeletons/SkeletonTable';
import WithdrawalsListItem from 'ui/withdrawals/WithdrawalsListItem';
import WithdrawalsTable from 'ui/withdrawals/WithdrawalsTable';
......@@ -21,24 +20,28 @@ const Withdrawals = () => {
resourceName: 'withdrawals',
});
const content = (() => {
if (isError) {
return <DataFetchAlert/>;
}
const countersQuery = useApiQuery('withdrawals_count');
if (isLoading) {
return (
const content = data?.items ? (
<>
<Skeleton w={{ base: '100%', lg: '320px' }} h="26px" mb={{ base: 6, lg: 7 }} mt={{ base: 0, lg: 7 }}/>
<SkeletonList display={{ base: 'block', lg: 'none' }}/>
<SkeletonTable minW="950px" display={{ base: 'none', lg: 'block' }} columns={ Array(7).fill(`${ 100 / 7 }%`) }/>
<Show below="lg" ssr={ false }>{ data.items.map((item => <WithdrawalsListItem key={ item.l2_tx_hash } item={ item }/>)) }</Show>
<Hide below="lg" ssr={ false }><WithdrawalsTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
) : null;
const text = (() => {
if (countersQuery.isLoading) {
return <Skeleton w={{ base: '100%', lg: '320px' }} h="26px" mb={{ base: 6, lg: 7 }} mt={{ base: 0, lg: 7 }}/>;
}
const text = <Text mb={{ base: 6, lg: 0 }}>A total of { data.total.toLocaleString('en') } withdrawals found</Text>;
if (countersQuery.isError) {
return null;
}
return (
return <Text mb={{ base: 6, lg: 0 }}>A total of { countersQuery.data.toLocaleString('en') } withdrawals found</Text>;
})();
const actionBar = (
<>
{ (isMobile || !isPaginationVisible) && text }
{ isPaginationVisible && (
......@@ -49,16 +52,21 @@ const Withdrawals = () => {
</Flex>
</ActionBar>
) }
<Show below="lg" ssr={ false }>{ data.items.map((item => <WithdrawalsListItem key={ item.l2_tx_hash } item={ item }/>)) }</Show>
<Hide below="lg" ssr={ false }><WithdrawalsTable items={ data.items } top={ isPaginationVisible ? 80 : 0 }/></Hide>
</>
);
})();
return (
<Page>
<PageTitle text={ `Withdrawals (L2${ nbsp }${ rightLineArrow }${ nbsp }L1)` } withTextAd/>
{ content }
<DataListDisplay
isError={ isError }
isLoading={ isLoading }
items={ data?.items }
skeletonProps={{ skeletonDesktopColumns: Array(7).fill(`${ 100 / 7 }%`), skeletonDesktopMinW: '950px' }}
emptyText="There are no withdrawals."
content={ content }
actionBar={ actionBar }
/>
</Page>
);
};
......
......@@ -12,6 +12,7 @@ type SkeletonProps =
{
skeletonDesktopColumns: Array<string>;
isLongSkeleton?: boolean;
skeletonDesktopMinW?: string;
}
type FilterProps = {
......@@ -50,6 +51,7 @@ const DataListDisplay = (props: Props) => {
display={{ base: 'none', lg: 'block' }}
columns={ props.skeletonProps.skeletonDesktopColumns || [] }
isLong={ props.skeletonProps.isLongSkeleton }
minW={ props.skeletonProps.skeletonDesktopMinW }
/>
</>
) }
......
......@@ -47,6 +47,7 @@ const TxnBatchesListItem = ({ item }: Props) => {
value: (
<LinkExternal
fontWeight={ 600 }
display="inline-flex"
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/block/[height]', query: { height: item.epoch_number.toString() } }) }
>
{ item.epoch_number }
......@@ -60,6 +61,7 @@ const TxnBatchesListItem = ({ item }: Props) => {
{ item.l1_tx_hashes.map(hash => (
<LinkExternal
w="100%"
display="inline-flex"
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }
key={ hash }
>
......
......@@ -44,6 +44,7 @@ const TxnBatchesTableItem = ({ item }: Props) => {
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/block/[height]', query: { height: item.epoch_number.toString() } }) }
fontWeight={ 600 }
lineHeight="24px"
display="inline-flex"
>
{ item.epoch_number }
</LinkExternal>
......@@ -51,7 +52,12 @@ const TxnBatchesTableItem = ({ item }: Props) => {
<Td pr={ 12 }>
<VStack spacing={ 3 }>
{ item.l1_tx_hashes.map(hash => (
<LinkExternal w="100%" key={ hash } href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }>
<LinkExternal
w="100%"
display="inline-flex"
key={ hash }
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: hash } }) }
>
<Icon as={ txIcon } boxSize={ 6 } mr={ 1 }/>
<Box w="calc(100% - 36px)" overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ hash }/></Box>
</LinkExternal>
......
......@@ -67,6 +67,7 @@ const WithdrawalsListItem = ({ item }: Props) => {
<LinkExternal
href={ appConfig.L2.L1BaseUrl + route({ pathname: '/tx/[hash]', query: { hash: item.l1_tx_hash } }) }
w="100%"
display="inline-flex"
overflow="hidden"
>
<Box w="calc(100% - 16px)" overflow="hidden" whiteSpace="nowrap"><HashStringShortenDynamic hash={ item.l1_tx_hash }/></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