Skip to content

Commit

Permalink
Extend transaction method filtering to consensus and validators
Browse files Browse the repository at this point in the history
  • Loading branch information
csillag committed Jan 20, 2025
1 parent eef9995 commit f1ffc24
Show file tree
Hide file tree
Showing 13 changed files with 143 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .changelog/1679.trivial.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
Add support for filtering latest TX list for method type
Add support for filtering transactions by method type
44 changes: 44 additions & 0 deletions src/app/components/Transactions/ConsensusTransactionTypeFilter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { FC } from 'react'
import { getConsensusTxMethodOptions } from '../ConsensusTransactionMethod'
import { useTranslation } from 'react-i18next'
import { Select } from '../Select'
import Typography from '@mui/material/Typography'
import { ConsensusTxMethod } from 'oasis-nexus/api'

const FilterLabel: FC = () => {
const { t } = useTranslation()
return (
<Typography
component={'span'}
sx={{
fontStyle: 'normal',
fontWeight: 700,
fontSize: 16,
lineHeight: '150%',
marginRight: 4,
}}
>
{t('transactions.filterByType')}
</Typography>
)
}

export type WantedConsensusTxMethod = ConsensusTxMethod | 'all'

export const ConsensusTransactionTypeFilter: FC<{
value: WantedConsensusTxMethod
setValue: (value: WantedConsensusTxMethod) => void
expand?: boolean
}> = ({ value, setValue, expand }) => {
const { t } = useTranslation()
return (
<Select
className={expand ? 'expand' : undefined}
light={true}
label={<FilterLabel />}
options={[{ value: 'all', label: 'All' }, ...getConsensusTxMethodOptions(t)]}
defaultValue={value}
handleChange={setValue as any}
/>
)
}
3 changes: 3 additions & 0 deletions src/app/components/Transactions/ConsensusTransactions.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type ConsensusTransactionsProps = {
limit: number
pagination: false | TablePaginationProps
verbose?: boolean
filtered: boolean
}

export const ConsensusTransactions: FC<ConsensusTransactionsProps> = ({
Expand All @@ -40,6 +41,7 @@ export const ConsensusTransactions: FC<ConsensusTransactionsProps> = ({
transactions,
ownAddress,
verbose = true,
filtered,
}) => {
const { t } = useTranslation()

Expand Down Expand Up @@ -142,6 +144,7 @@ export const ConsensusTransactions: FC<ConsensusTransactionsProps> = ({
name={t('transactions.latest')}
isLoading={isLoading}
pagination={pagination}
emptyMessage={filtered ? t('tableSearch.noMatchingResults') : t('account.emptyTransactionList')}
/>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,12 @@ export const ConsensusAccountEventsList: FC<ConsensusAccountDetailsContext> = ({
)
}

export const ConsensusAccountEventsCard: FC<ConsensusAccountDetailsContext> = ({ scope, address }) => {
export const ConsensusAccountEventsCard: FC<ConsensusAccountDetailsContext> = context => {
const { t } = useTranslation()

return (
<LinkableCardLayout containerId={eventsContainerId} title={t('common.events')}>
<ConsensusAccountEventsList scope={scope} address={address} />
<ConsensusAccountEventsList {...context} />
</LinkableCardLayout>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,57 +3,58 @@ import { useTranslation } from 'react-i18next'
import { useGetConsensusTransactions } from '../../../oasis-nexus/api'
import { NUMBER_OF_ITEMS_ON_SEPARATE_PAGE as limit } from '../../config'
import { ConsensusTransactions } from '../../components/Transactions'
import { CardEmptyState } from '../../components/CardEmptyState'
import { useSearchParamsPagination } from '../../components/Table/useSearchParamsPagination'
import { ConsensusAccountDetailsContext } from './hooks'
import { LinkableCardLayout } from 'app/components/LinkableCardLayout'
import { useScreenSize } from '../../hooks/useScreensize'
import { ConsensusTransactionTypeFilter } from '../../components/Transactions/ConsensusTransactionTypeFilter'

const consensusAccountTransactionsContainerId = 'transactions'

export const ConsensusAccountTransactionsCard: FC<ConsensusAccountDetailsContext> = ({ scope, address }) => {
export const ConsensusAccountTransactionsCard: FC<ConsensusAccountDetailsContext> = context => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()
const { method, setMethod } = context

return (
<LinkableCardLayout
containerId={consensusAccountTransactionsContainerId}
title={t('common.transactions')}
action={isMobile ? undefined : <ConsensusTransactionTypeFilter value={method} setValue={setMethod} />}
>
<ConsensusAccountTransactions scope={scope} address={address} />
{isMobile && <ConsensusTransactionTypeFilter value={method} setValue={setMethod} expand />}
<ConsensusAccountTransactions {...context} />
</LinkableCardLayout>
)
}

const ConsensusAccountTransactions: FC<ConsensusAccountDetailsContext> = ({ scope, address }) => {
const { t } = useTranslation()
const ConsensusAccountTransactions: FC<ConsensusAccountDetailsContext> = ({ scope, address, method }) => {
const { network } = scope
const pagination = useSearchParamsPagination('page')
const offset = (pagination.selectedPage - 1) * limit
const transactionsQuery = useGetConsensusTransactions(network, {
limit,
offset,
rel: address,
method: method === 'all' ? undefined : method,
})
const { isFetched, isLoading, data } = transactionsQuery
const { isLoading, data } = transactionsQuery
const transactions = data?.data.transactions

return (
<>
{isFetched && !transactions?.length && (
<CardEmptyState label={t('account.emptyAccountTransactionList')} />
)}
<ConsensusTransactions
transactions={transactions}
ownAddress={address}
isLoading={isLoading}
limit={limit}
pagination={{
selectedPage: pagination.selectedPage,
linkToPage: pagination.linkToPage,
totalCount: data?.data.total_count,
isTotalCountClipped: data?.data.is_total_count_clipped,
rowsPerPage: limit,
}}
/>
</>
<ConsensusTransactions
transactions={transactions}
ownAddress={address}
isLoading={isLoading}
limit={limit}
pagination={{
selectedPage: pagination.selectedPage,
linkToPage: pagination.linkToPage,
totalCount: data?.data.total_count,
isTotalCountClipped: data?.data.is_total_count_clipped,
rowsPerPage: limit,
}}
filtered={method !== 'all'}
/>
)
}
3 changes: 3 additions & 0 deletions src/app/pages/ConsensusAccountDetailsPage/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { useOutletContext } from 'react-router-dom'
import { SearchScope } from '../../../types/searchScope'
import { WantedConsensusTxMethod } from '../../components/Transactions/ConsensusTransactionTypeFilter'

export type ConsensusAccountDetailsContext = {
scope: SearchScope
address: string
method: WantedConsensusTxMethod
setMethod: (value: WantedConsensusTxMethod) => void
}

export const useConsensusAccountDetailsProps = () => useOutletContext<ConsensusAccountDetailsContext>()
7 changes: 6 additions & 1 deletion src/app/pages/ConsensusAccountDetailsPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,24 @@ import { BalanceDistribution } from './BalanceDistribution'
import { Staking } from './Staking'
import { ConsensusAccountDetailsContext } from './hooks'
import { eventsContainerId } from './ConsensusAccountEventsCard'
import { WantedConsensusTxMethod } from '../../components/Transactions/ConsensusTransactionTypeFilter'
import { useTypedSearchParam } from '../../hooks/useTypedSearchParam'

export const ConsensusAccountDetailsPage: FC = () => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()
const scope = useRequiredScopeParam()
const { network } = scope
const { address, searchTerm } = useLoaderData() as AddressLoaderData
const [method, setMethod] = useTypedSearchParam<WantedConsensusTxMethod>('method', 'all', {
deleteParams: ['page'],
})
const accountQuery = useGetConsensusAccountsAddress(network, address)
const { isError, isLoading, data } = accountQuery
const account = data?.data
const transactionsLink = useHref('')
const eventsLink = useHref(`events#${eventsContainerId}`)
const context: ConsensusAccountDetailsContext = { scope, address }
const context: ConsensusAccountDetailsContext = { scope, address, method, setMethod }

return (
<PageLayout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,27 @@ import { AppErrors } from '../../../types/errors'
import { SearchScope } from '../../../types/searchScope'
import { ConsensusBlockDetailsContext } from '.'
import { LinkableCardLayout } from 'app/components/LinkableCardLayout'
import { useTypedSearchParam } from '../../hooks/useTypedSearchParam'
import {
ConsensusTransactionTypeFilter,
WantedConsensusTxMethod,
} from '../../components/Transactions/ConsensusTransactionTypeFilter'
import { useScreenSize } from '../../hooks/useScreensize'

export const transactionsContainerId = 'transactions'

const TransactionList: FC<{ scope: SearchScope; blockHeight: number }> = ({ scope, blockHeight }) => {
const TransactionList: FC<{ scope: SearchScope; blockHeight: number; method: WantedConsensusTxMethod }> = ({
scope,
blockHeight,
method,
}) => {
const txsPagination = useSearchParamsPagination('page')
const txsOffset = (txsPagination.selectedPage - 1) * NUMBER_OF_ITEMS_ON_SEPARATE_PAGE
const transactionsQuery = useGetConsensusTransactions(scope.network, {
block: blockHeight,
limit: NUMBER_OF_ITEMS_ON_SEPARATE_PAGE,
offset: txsOffset,
method: method === 'all' ? undefined : method,
})
const { isLoading, isFetched, data } = transactionsQuery
const transactions = data?.data.transactions
Expand All @@ -38,20 +49,30 @@ const TransactionList: FC<{ scope: SearchScope; blockHeight: number }> = ({ scop
isTotalCountClipped: data?.data.is_total_count_clipped,
rowsPerPage: NUMBER_OF_ITEMS_ON_SEPARATE_PAGE,
}}
filtered={method !== 'all'}
/>
)
}

export const ConsensusBlockTransactionsCard: FC<ConsensusBlockDetailsContext> = ({ scope, blockHeight }) => {
const { t } = useTranslation()
const [method, setMethod] = useTypedSearchParam<WantedConsensusTxMethod>('method', 'all', {
deleteParams: ['page'],
})
const { isMobile } = useScreenSize()

if (!blockHeight) {
return null
}

return (
<LinkableCardLayout containerId={transactionsContainerId} title={t('common.transactions')}>
<TransactionList scope={scope} blockHeight={blockHeight} />
<LinkableCardLayout
containerId={transactionsContainerId}
title={t('common.transactions')}
action={isMobile ? undefined : <ConsensusTransactionTypeFilter value={method} setValue={setMethod} />}
>
{isMobile && <ConsensusTransactionTypeFilter value={method} setValue={setMethod} expand />}
<TransactionList scope={scope} blockHeight={blockHeight} method={method} />
</LinkableCardLayout>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const LatestConsensusTransactions: FC<{ scope: SearchScope }> = ({ scope
limit={limit}
pagination={false}
verbose={false}
filtered={false}
/>
</CardContent>
</Card>
Expand Down
25 changes: 23 additions & 2 deletions src/app/pages/ConsensusTransactionsPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,20 @@ import { useRequiredScopeParam } from '../../hooks/useScopeParam'
import { VerticalList } from '../../components/VerticalList'
import { ConsensusTransactionDetailView } from '../ConsensusTransactionDetailPage'
import { useConsensusListBeforeDate } from '../../hooks/useListBeforeDate'
import { useTypedSearchParam } from '../../hooks/useTypedSearchParam'
import {
ConsensusTransactionTypeFilter,
WantedConsensusTxMethod,
} from '../../components/Transactions/ConsensusTransactionTypeFilter'

export const ConsensusTransactionsPage: FC = () => {
const [tableView, setTableView] = useState<TableLayout>(TableLayout.Horizontal)
const { t } = useTranslation()
const { isMobile } = useScreenSize()
const pagination = useSearchParamsPagination('page')
const [method, setMethod] = useTypedSearchParam<WantedConsensusTxMethod>('method', 'all', {
deleteParams: ['date'],
})
const offset = (pagination.selectedPage - 1) * limit
const scope = useRequiredScopeParam()
const enablePolling = offset === 0
Expand All @@ -39,6 +47,7 @@ export const ConsensusTransactionsPage: FC = () => {
limit: tableView === TableLayout.Vertical ? offset + limit : limit,
offset: tableView === TableLayout.Vertical ? 0 : offset,
before: enablePolling ? undefined : beforeDate,
method: method === 'all' ? undefined : method,
},
{
query: {
Expand Down Expand Up @@ -69,7 +78,9 @@ export const ConsensusTransactionsPage: FC = () => {
const { isLoading, isFetched, data } = transactionsQuery

const transactions = data?.data.transactions
setBeforeDateFromCollection(data?.data.transactions[0].timestamp)
if (transactions?.length) {
setBeforeDateFromCollection(data?.data.transactions[0].timestamp)
}

if (isFetched && pagination.selectedPage > 1 && !transactions?.length) {
throw AppErrors.PageDoesNotExist
Expand All @@ -84,7 +95,16 @@ export const ConsensusTransactionsPage: FC = () => {
{!isMobile && <Divider variant="layout" />}
<SubPageCard
title={t('transactions.latest')}
action={isMobile && <TableLayoutButton tableView={tableView} setTableView={setTableView} />}
title2={
isMobile ? <ConsensusTransactionTypeFilter value={method} setValue={setMethod} expand /> : undefined
}
action={
isMobile ? (
<TableLayoutButton tableView={tableView} setTableView={setTableView} />
) : (
<ConsensusTransactionTypeFilter value={method} setValue={setMethod} />
)
}
noPadding={tableView === TableLayout.Vertical}
mainTitle
>
Expand All @@ -101,6 +121,7 @@ export const ConsensusTransactionsPage: FC = () => {
rowsPerPage: limit,
}}
verbose={false}
filtered={method !== 'all'}
/>
)}

Expand Down
3 changes: 3 additions & 0 deletions src/app/pages/ValidatorDetailsPage/hooks.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import { useOutletContext } from 'react-router-dom'
import { SearchScope } from '../../../types/searchScope'
import { WantedConsensusTxMethod } from '../../components/Transactions/ConsensusTransactionTypeFilter'

export type ValidatorDetailsContext = {
scope: SearchScope
address: string
method: WantedConsensusTxMethod
setMethod: (method: WantedConsensusTxMethod) => void
}

export const useValidatorDetailsProps = () => useOutletContext<ValidatorDetailsContext>()
8 changes: 7 additions & 1 deletion src/app/pages/ValidatorDetailsPage/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import { eventsContainerId } from './../../pages/ConsensusAccountDetailsPage/Con
import { PercentageValue } from '../../components/PercentageValue'
import { BalancesDiff } from '../../components/BalancesDiff'
import { RoundedBalance } from '../../components/RoundedBalance'
import { WantedConsensusTxMethod } from '../../components/Transactions/ConsensusTransactionTypeFilter'
import { useTypedSearchParam } from '../../hooks/useTypedSearchParam'

export const StyledGrid = styled(Grid)(({ theme }) => ({
[theme.breakpoints.up('sm')]: {
Expand All @@ -43,6 +45,10 @@ export const ValidatorDetailsPage: FC = () => {
const { t } = useTranslation()
const { isMobile } = useScreenSize()
const scope = useRequiredScopeParam()
const [method, setMethod] = useTypedSearchParam<WantedConsensusTxMethod>('method', 'all', {
deleteParams: ['page'],
})

const { address } = useLoaderData() as AddressLoaderData
const validatorQuery = useGetConsensusValidatorsAddress(scope.network, address)
const { isLoading, isFetched, data } = validatorQuery
Expand All @@ -52,7 +58,7 @@ export const ValidatorDetailsPage: FC = () => {
const eventsLink = useHref(`events#${eventsContainerId}`)
const delegatorsLink = useHref(`delegators#${delegatorsContainerId}`)
const debondingDelegationsLink = useHref(`debonding-delegations#${debondingContainerId}`)
const context: ValidatorDetailsContext = { scope, address }
const context: ValidatorDetailsContext = { scope, address, method, setMethod }

return (
<PageLayout>
Expand Down
1 change: 1 addition & 0 deletions src/stories/Transactions.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ const ConsensusListStory: StoryFn = () => {
limit={100}
pagination={false}
transactions={mockedTransactions}
filtered={false}
/>
</Box>
)
Expand Down

0 comments on commit f1ffc24

Please sign in to comment.