Skip to content

Commit

Permalink
[explorer] paginated epochs table (#11141)
Browse files Browse the repository at this point in the history
## Description 

Epochs table paginated

<img width="1356" alt="image"
src="https://user-images.githubusercontent.com/128089541/234140627-433fd180-5406-4c8d-ae8a-1043c2123e48.png">

## Test Plan 

Locally

---
If your changes are not user-facing and not a breaking change, you can
skip the following section. Otherwise, please indicate what changed, and
then add to the Release Notes section as highlighted during the release
process.

### Type of Change (Check all that apply)

- [x] user-visible impact
- [ ] breaking change for a client SDKs
- [ ] breaking change for FNs (FN binary must upgrade)
- [ ] breaking change for validators or node operators (must upgrade
binaries)
- [ ] breaking change for on-chain data layout
- [ ] necessitate either a data wipe or data migration

### Release notes
Epochs activity table paginated
  • Loading branch information
Nikhil-Mysten authored May 1, 2023
1 parent a355976 commit 2ba807a
Show file tree
Hide file tree
Showing 5 changed files with 237 additions and 202 deletions.
117 changes: 117 additions & 0 deletions apps/explorer/src/components/Activity/EpochsActivityTable.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { useRpcClient } from '@mysten/core';
import { ArrowRight12 } from '@mysten/icons';
import { useQuery } from '@tanstack/react-query';
import { useState } from 'react';

import { genTableDataFromEpochsData } from './utils';

import { useGetEpochs } from '~/hooks/useGetEpochs';
import { Link } from '~/ui/Link';
import { Pagination, useCursorPagination } from '~/ui/Pagination';
import { PlaceholderTable } from '~/ui/PlaceholderTable';
import { TableCard } from '~/ui/TableCard';
import { Text } from '~/ui/Text';
import { numberSuffix } from '~/utils/numberUtil';

const DEFAULT_EPOCHS_LIMIT = 20;

interface Props {
disablePagination?: boolean;
refetchInterval?: number;
initialLimit?: number;
}

export function EpochsActivityTable({
disablePagination,
initialLimit = DEFAULT_EPOCHS_LIMIT,
}: Props) {
const [limit, setLimit] = useState(initialLimit);
const rpc = useRpcClient();

const { data: count } = useQuery(
['epochs', 'current'],
async () => rpc.getCurrentEpoch(),
{
select: (epoch) => Number(epoch.epoch) + 1,
}
);

const epochs = useGetEpochs(limit);
const { data, isFetching, pagination, isLoading, isError } =
useCursorPagination(epochs);

const cardData = data ? genTableDataFromEpochsData(data) : undefined;

return (
<div className="flex flex-col space-y-5 text-left xl:pr-10">
{isError && (
<div className="pt-2 font-sans font-semibold text-issue-dark">
Failed to load Epochs
</div>
)}
{isLoading || isFetching || !cardData ? (
<PlaceholderTable
rowCount={limit}
rowHeight="16px"
colHeadings={[
'Epoch',
'Transaction Blocks',
'Stake Rewards',
'Checkpoint Set',
'Storage Net Inflow',
'Epoch End',
]}
colWidths={[
'100px',
'120px',
'40px',
'204px',
'90px',
'38px',
]}
/>
) : (
<div>
<TableCard
data={cardData.data}
columns={cardData.columns}
/>
</div>
)}

<div className="flex justify-between">
{!disablePagination ? (
<Pagination {...pagination} />
) : (
<Link to="/recent?tab=epochs" after={<ArrowRight12 />}>
More Epochs
</Link>
)}

<div className="flex items-center space-x-3">
<Text variant="body/medium" color="steel-dark">
{count ? numberSuffix(Number(count)) : '-'}
{` Epochs`}
</Text>
{!disablePagination && (
<select
className="form-select rounded-md border border-gray-45 px-3 py-2 pr-8 text-bodySmall font-medium leading-[1.2] text-steel-dark shadow-button"
value={limit}
onChange={(e) => {
setLimit(Number(e.target.value));
pagination.onFirst();
}}
>
<option value={20}>20 Per Page</option>
<option value={40}>40 Per Page</option>
<option value={60}>60 Per Page</option>
</select>
)}
</div>
</div>
</div>
);
}
4 changes: 2 additions & 2 deletions apps/explorer/src/components/Activity/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import { useState } from 'react';
// import toast from 'react-hot-toast';

import { CheckpointsTable } from '../checkpoints/CheckpointsTable';
import { EpochsActivityTable } from './EpochsActivityTable';
import { TransactionsActivityTable } from './TransactionsActivityTable';

import { EpochsTable } from '~/pages/epochs/EpochsTable';
// import { PlayPause } from '~/ui/PlayPause';
import { Tab, TabGroup, TabList, TabPanel, TabPanels } from '~/ui/Tabs';

Expand Down Expand Up @@ -81,7 +81,7 @@ export function Activity({
/>
</TabPanel>
<TabPanel>
<EpochsTable
<EpochsActivityTable
refetchInterval={refetchInterval}
initialLimit={initialLimit}
disablePagination={disablePagination}
Expand Down
88 changes: 88 additions & 0 deletions apps/explorer/src/components/Activity/utils.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0
import { type EpochPage } from '@mysten/sui.js/src/types/epochs';

import { SuiAmount } from '../Table/SuiAmount';
import { TxTableCol } from '../transactions/TxCardUtils';
import { TxTimeType } from '../tx-time/TxTimeType';

import { CheckpointSequenceLink, EpochLink } from '~/ui/InternalLink';
import { Text } from '~/ui/Text';

// Generate table data from the epochs data
export const genTableDataFromEpochsData = (results: EpochPage) => ({
data: results?.data.map((epoch) => ({
epoch: (
<TxTableCol isHighlightedOnHover>
<EpochLink epoch={epoch.epoch.toString()} />
</TxTableCol>
),
transactions: (
<TxTableCol>
<Text variant="bodySmall/medium">
{epoch.epochTotalTransactions}
</Text>
</TxTableCol>
),
stakeRewards: (
<TxTableCol>
<SuiAmount
amount={epoch.endOfEpochInfo?.totalStakeRewardsDistributed}
/>
</TxTableCol>
),
checkpointSet: (
<div>
<CheckpointSequenceLink
sequence={epoch.firstCheckpointId.toString()}
/>
{` - `}
<CheckpointSequenceLink
sequence={
epoch.endOfEpochInfo?.lastCheckpointId.toString() ?? ''
}
/>
</div>
),
storageNetInflow: (
<TxTableCol>
<SuiAmount amount={epoch.endOfEpochInfo?.storageCharge} />
</TxTableCol>
),
time: (
<TxTableCol>
<TxTimeType
timestamp={Number(
epoch.endOfEpochInfo?.epochEndTimestamp ?? 0
)}
/>
</TxTableCol>
),
})),
columns: [
{
header: 'Epoch',
accessorKey: 'epoch',
},
{
header: 'Transaction Blocks',
accessorKey: 'transactions',
},
{
header: 'Stake Rewards',
accessorKey: 'stakeRewards',
},
{
header: 'Checkpoint Set',
accessorKey: 'checkpointSet',
},
{
header: 'Storage Net Inflow',
accessorKey: 'storageNetInflow',
},
{
header: 'Epoch End',
accessorKey: 'time',
},
],
});
30 changes: 30 additions & 0 deletions apps/explorer/src/hooks/useGetEpochs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

import { useRpcClient } from '@mysten/core';
import { useInfiniteQuery } from '@tanstack/react-query';

export const DEFAULT_EPOCHS_LIMIT = 20;

// Fetch paginated epochs
export function useGetEpochs(limit = DEFAULT_EPOCHS_LIMIT) {
const rpc = useRpcClient();

return useInfiniteQuery(
['get-epochs-blocks', limit],
({ pageParam = null }) =>
rpc.getEpochs({
descendingOrder: true,
cursor: pageParam,
limit,
}),
{
getNextPageParam: ({ nextCursor, hasNextPage }) =>
hasNextPage ? nextCursor : null,
staleTime: 10 * 1000,
cacheTime: 24 * 60 * 60 * 1000,
retry: false,
keepPreviousData: true,
}
);
}
Loading

2 comments on commit 2ba807a

@vercel
Copy link

@vercel vercel bot commented on 2ba807a May 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vercel
Copy link

@vercel vercel bot commented on 2ba807a May 1, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

explorer-storybook – ./apps/explorer

explorer-storybook-mysten-labs.vercel.app
explorer-storybook.vercel.app
explorer-storybook-git-main-mysten-labs.vercel.app

Please sign in to comment.