Skip to content

Commit

Permalink
adv filters stage 3
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed Aug 21, 2024
1 parent 74db846 commit 10c5b47
Show file tree
Hide file tree
Showing 25 changed files with 515 additions and 220 deletions.
6 changes: 6 additions & 0 deletions icons/columns.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion lib/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import type {
} from 'types/api/address';
import type { AddressesResponse } from 'types/api/addresses';
import type { AddressMetadataInfo, PublicTagTypesResponse } from 'types/api/addressMetadata';
import type { AdvancedFilterParams, AdvancedFilterResponse, AdvancedFilterMethodsResponse } from 'types/api/advancedFilter';
import type {
ArbitrumL2MessagesResponse,
ArbitrumL2MessagesItem,
Expand All @@ -50,7 +51,6 @@ import type {
ArbitrumL2BatchBlocks,
ArbitrumL2TxnBatchesItem,
} from 'types/api/arbitrumL2';
import type { AdvancedFilterParams, AdvancedFilterResponse, AdvancedFilterMethodsResponse } from 'types/api/advancedFilter';
import type { TxBlobs, Blob } from 'types/api/blobs';
import type { BlocksResponse, BlockTransactionsResponse, Block, BlockFilters, BlockWithdrawalsResponse, BlockCountdownResponse } from 'types/api/block';
import type { ChartMarketResponse, ChartSecondaryCoinPriceResponse, ChartTransactionResponse } from 'types/api/charts';
Expand Down
14 changes: 5 additions & 9 deletions lib/getFilterValuesFromQuery.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import getValuesArrayFromQuery from './getValuesArrayFromQuery';

export default function getFilterValue<FilterType>(filterValues: ReadonlyArray<FilterType>, val: string | Array<string> | undefined) {
if (val === undefined) {
return;
}
const valArray = getValuesArrayFromQuery(val);

const valArray = [];
if (typeof val === 'string') {
valArray.push(...val.split(','));
}
if (Array.isArray(val)) {
val.forEach(el => valArray.push(...el.split(',')));
if (!valArray) {
return;
}

return valArray.filter(el => filterValues.includes(el as unknown as FilterType)) as unknown as Array<FilterType>;
Expand Down
18 changes: 18 additions & 0 deletions lib/getValuesArrayFromQuery.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export default function getValuesArrayFromQuery(val: string | Array<string> | undefined) {
if (val === undefined) {
return;
}

const valArray = [];
if (typeof val === 'string') {
valArray.push(...val.split(','));
}
if (Array.isArray(val)) {
if (!val.length) {
return;
}
val.forEach(el => valArray.push(...el.split(',')));
}

return valArray;
}
2 changes: 1 addition & 1 deletion nextjs/nextjs-routes.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ declare module "nextjs-routes" {
| StaticRoute<"/accounts">
| DynamicRoute<"/address/[hash]/contract-verification", { "hash": string }>
| DynamicRoute<"/address/[hash]", { "hash": string }>
| StaticRoute<"/api/config">
| StaticRoute<"/advanced-filter">
| StaticRoute<"/api/config">
| StaticRoute<"/api/csrf">
| StaticRoute<"/api/healthz">
| StaticRoute<"/api/log">
Expand Down
1 change: 1 addition & 0 deletions public/icons/name.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
| "clock"
| "coins/bitcoin"
| "collection"
| "columns"
| "contracts/proxy"
| "contracts/regular_many"
| "contracts/regular"
Expand Down
5 changes: 4 additions & 1 deletion types/api/advancedFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { TokenInfo } from './token';
export type AdvancedFilterParams = {
tx_types?: Array<AdvancedFilterType>;
methods?: Array<string>;
methods_names?: Array<string>; /* frontend only */
age_from?: string;
age_to?: string;
age?: AdvancedFilterAge; /* frontend only */
Expand All @@ -16,6 +17,8 @@ export type AdvancedFilterParams = {
amount_to?: string;
token_contract_address_hashes_to_include?: Array<string>;
token_contract_address_hashes_to_exclude?: Array<string>;
token_contract_symbols_to_include?: Array<string>;
token_contract_symbols_to_exclude?: Array<string>;
};

export const ADVANCED_FILTER_TYPES = [ 'coin_transfer', 'ERC-20', 'ERC-404', 'ERC-721', 'ERC-1155' ] as const;
Expand All @@ -42,7 +45,7 @@ export type AdvancedFilterResponseItem = {
}

export type AdvancedFiltersSearchParams = {
methods: Record<string, AdvancedFilterMethodInfo>;
methods: Record<string, string>;
tokens: Record<string, TokenInfo>;
}

Expand Down
28 changes: 10 additions & 18 deletions ui/address/mud/AddressMudRecordsKeyFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React from 'react';

import FilterInput from 'ui/shared/filters/FilterInput';
import TableColumnFilter from 'ui/shared/filters/TableColumnFilter';
import TableColumnFilterWrapper from 'ui/shared/filters/TableColumnFilterWrapper';

import AddressMudRecordsKeyFilterContent from './AddressMudRecordsKeyFilterContent';

type Props = {
value?: string;
Expand All @@ -12,29 +13,20 @@ type Props = {
}

const AddressMudRecordsKeyFilter = ({ value = '', handleFilterChange, columnName, title, isLoading }: Props) => {
const [ filterValue, setFilterValue ] = React.useState<string>(value);

const onFilter = React.useCallback(() => {
handleFilterChange(filterValue);
}, [ handleFilterChange, filterValue ]);

return (
<TableColumnFilter
<TableColumnFilterWrapper
columnName={ columnName }
title={ title }
isActive={ Boolean(value) }
isFilled={ filterValue !== value }
onFilter={ onFilter }
isLoading={ isLoading }
w="350px"
>
<FilterInput
initialValue={ value }
size="xs"
onChange={ setFilterValue }
placeholder={ columnName }
<AddressMudRecordsKeyFilterContent
value={ value }
handleFilterChange={ handleFilterChange }
title={ title }
columnName={ columnName }
/>
</TableColumnFilter>
</TableColumnFilterWrapper>
);
};

Expand Down
38 changes: 38 additions & 0 deletions ui/address/mud/AddressMudRecordsKeyFilterContent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';

import FilterInput from 'ui/shared/filters/FilterInput';
import TableColumnFilter from 'ui/shared/filters/TableColumnFilter';

type Props = {
value?: string;
handleFilterChange: (val: string) => void;
title: string;
columnName: string;
onClose?: () => void;
}

const AddressMudRecordsKeyFilter = ({ value = '', handleFilterChange, columnName, title, onClose }: Props) => {
const [ filterValue, setFilterValue ] = React.useState<string>(value);

const onFilter = React.useCallback(() => {
handleFilterChange(filterValue);
}, [ handleFilterChange, filterValue ]);

return (
<TableColumnFilter
title={ title }
isFilled={ filterValue !== value }
onFilter={ onFilter }
onClose={ onClose }
>
<FilterInput
initialValue={ value }
size="xs"
onChange={ setFilterValue }
placeholder={ columnName }
/>
</TableColumnFilter>
);
};

export default AddressMudRecordsKeyFilter;
2 changes: 1 addition & 1 deletion ui/advancedFilter/ColumnFilterWrapper.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import {
Popover,
PopoverTrigger,
PopoverContent,
PopoverBody,
Expand All @@ -9,6 +8,7 @@ import {
} from '@chakra-ui/react';
import React from 'react';

import Popover from 'ui/shared/chakra/Popover';
import IconSvg from 'ui/shared/IconSvg';

interface Props {
Expand Down
6 changes: 5 additions & 1 deletion ui/advancedFilter/ColumnsButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
Button,
Grid,
Popover,
PopoverTrigger,
PopoverContent,
PopoverBody,
Expand All @@ -13,6 +12,8 @@ import type { ChangeEvent } from 'react';

import type { ColumnsIds } from 'ui/pages/AdvancedFilter';
import { TABLE_COLUMNS } from 'ui/pages/AdvancedFilter';
import Popover from 'ui/shared/chakra/Popover';
import IconSvg from 'ui/shared/IconSvg';

interface Props {
columns: Record<ColumnsIds, boolean>;
Expand All @@ -36,8 +37,11 @@ const ColumnsButton = ({ columns, onChange }: Props) => {
onClick={ onToggle }
variant="outline"
colorScheme="gray"
size="sm"
leftIcon={ <IconSvg name="columns" boxSize={ 5 } color="inherit"/> }
// isLoading={ isLoading }
>
{ /* <IconSvg name='columns' boxSize={ 5 }/> */ }
Columns
</Button>
</PopoverTrigger>
Expand Down
119 changes: 102 additions & 17 deletions ui/advancedFilter/FilterByColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@ import React from 'react';
import type { AdvancedFilterParams, AdvancedFiltersSearchParams } from 'types/api/advancedFilter';

import type { ColumnsIds } from 'ui/pages/AdvancedFilter';
import TableColumnFilterWrapper from 'ui/shared/filters/TableColumnFilterWrapper';

import { NATIVE_TOKEN } from './constants';
import type { AddressFilterMode } from './filters/AddressFilter';
import AddressFilter from './filters/AddressFilter';
import AddressRelationFilter from './filters/AddressRelationFilter';
Expand All @@ -22,38 +24,106 @@ type Props = {
handleFilterChange: (field: keyof AdvancedFilterParams, val: unknown) => void;
isLoading?: boolean;
}

const FilterByColumn = ({ column, filters, columnName, handleFilterChange, searchParams, isLoading }: Props) => {
const commonProps = { columnName, handleFilterChange, isLoading };
switch (column) {
case 'type':
return <TypeFilter { ...commonProps } value={ filters.tx_types }/>;
case 'type': {
const value = filters.tx_types;
return (
<TableColumnFilterWrapper
columnName="Type"
isLoading={ isLoading }
isActive={ Boolean(value && value.length) }
>
<TypeFilter { ...commonProps } value={ value }/>
</TableColumnFilterWrapper>
);
}
case 'method': {
const value = filters.methods?.map(m => searchParams?.methods[m] || { method_id: m });
return <MethodFilter { ...commonProps } value={ value }/>;
const value = filters.methods?.map(m => ({ name: searchParams?.methods[m], method_id: m }));
return (
<TableColumnFilterWrapper
columnName="Method"
isLoading={ isLoading }
isActive={ Boolean(value && value.length) }
w="350px"
>
<MethodFilter { ...commonProps } value={ value }/>
</TableColumnFilterWrapper>
);
}
case 'age': {
const value = { age: filters.age, from: filters.age_from, to: filters.age_to };
return (
<TableColumnFilterWrapper
columnName="Age"
isLoading={ isLoading }
isActive={ Boolean(value.from || value.to || value.age) }
w="382px"
>
<AgeFilter { ...commonProps } value={ value }/>
</TableColumnFilterWrapper>
);
}
case 'or_and': {
return (
<TableColumnFilterWrapper
columnName="And/Or"
isLoading={ isLoading }
isActive={ false }
w="106px"
>
<AddressRelationFilter { ...commonProps } value={ filters.address_relation }/>
</TableColumnFilterWrapper>
);
}
case 'age':
return <AgeFilter { ...commonProps } value={{ age: filters.age, from: filters.age_from, to: filters.age_to }}/>;
case 'or_and':
return <AddressRelationFilter { ...commonProps } value={ filters.address_relation }/>;
case 'from': {
const valueInclude = filters?.from_address_hashes_to_include?.map(hash => ({ address: hash, mode: 'include' as AddressFilterMode }));
const valueExclude = filters?.from_address_hashes_to_exclude?.map(hash => ({ address: hash, mode: 'exclude' as AddressFilterMode }));

const value = (valueInclude || []).concat(valueExclude || []);

return <AddressFilter { ...commonProps } type="from" value={ value }/>;
return (
<TableColumnFilterWrapper
columnName="Address from"
isLoading={ isLoading }
isActive={ Boolean(value.length) }
w="480px"
>
<AddressFilter { ...commonProps } type="from" value={ value }/>
</TableColumnFilterWrapper>
);

}
case 'to': {
const valueInclude = filters?.to_address_hashes_to_include?.map(hash => ({ address: hash, mode: 'include' as AddressFilterMode }));
const valueExclude = filters?.to_address_hashes_to_exclude?.map(hash => ({ address: hash, mode: 'exclude' as AddressFilterMode }));

const value = (valueInclude || []).concat(valueExclude || []);

return <AddressFilter { ...commonProps } type="to" value={ value }/>;
return (
<TableColumnFilterWrapper
columnName="Address to"
isLoading={ isLoading }
isActive={ Boolean(value.length) }
w="480px"
>
<AddressFilter { ...commonProps } type="to" value={ value }/>
</TableColumnFilterWrapper>
);
}
case 'amount': {
const value = { from: filters.amount_from, to: filters.amount_to };
return (
<TableColumnFilterWrapper
columnName="Amount"
isLoading={ isLoading }
isActive={ Boolean(value.from || value.to) }
w="382px"
>
<AmountFilter { ...commonProps } value={ value }/>
</TableColumnFilterWrapper>
);
}
case 'amount':
return <AmountFilter { ...commonProps } value={{ from: filters.amount_from, to: filters.amount_to }}/>;
case 'asset': {
const tokens = searchParams?.tokens;

Expand All @@ -64,11 +134,26 @@ const FilterByColumn = ({ column, filters, columnName, handleFilterChange, searc
'exclude' as AssetFilterMode;
return ({ token, mode });
}) : [];

return <AssetFilter { ...commonProps } value={ value }/>;
if (filters.token_contract_address_hashes_to_include?.includes('native')) {
value.unshift({ token: NATIVE_TOKEN, mode: 'include' });
}
if (filters.token_contract_address_hashes_to_exclude?.includes('native')) {
value.unshift({ token: NATIVE_TOKEN, mode: 'exclude' });
}
return (
<TableColumnFilterWrapper
columnName="Asset"
isLoading={ isLoading }
isActive={ Boolean(value.length) }
w="382px"
>
<AssetFilter { ...commonProps } value={ value }/>
</TableColumnFilterWrapper>
);
}
default:
default: {
return null;
}
}
};

Expand Down
Loading

0 comments on commit 10c5b47

Please sign in to comment.