Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
isstuev committed Aug 29, 2024
1 parent 8e6cc32 commit a184eba
Show file tree
Hide file tree
Showing 17 changed files with 210 additions and 104 deletions.
3 changes: 3 additions & 0 deletions lib/api/resources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -903,6 +903,9 @@ export const RESOURCES = {
path: '/api/v2/advanced-filters/methods',
filterFields: [ 'q' as const ],
},
advanced_filter_csv: {
path: '/api/v2/advanced-filters/csv',
},

// CONFIGS
config_backend_version: {
Expand Down
1 change: 1 addition & 0 deletions theme/components/Tag/Tag.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const variants = {
container: {
bg: mode('gray.100', 'gray.800')(props),
color: mode('gray.500', 'whiteAlpha.800')(props),
cursor: 'pointer',
_hover: {
color: 'blue.400',
opacity: 0.76,
Expand Down
2 changes: 1 addition & 1 deletion types/api/advancedFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type AdvancedFilterParams = {
methods_names?: Array<string>; /* frontend only */
age_from?: string;
age_to?: string;
age?: AdvancedFilterAge; /* frontend only */
age?: AdvancedFilterAge | ''; /* frontend only */
from_address_hashes_to_include?: Array<string>;
from_address_hashes_to_exclude?: Array<string>;
to_address_hashes_to_include?: Array<string>;
Expand Down
3 changes: 1 addition & 2 deletions ui/advancedFilter/ColumnFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ const ColumnFilterContent = ({ title, isFilled, onFilter, onReset, onClose, chil
</Flex>
{ children }
<Button
// ???
// isDisabled={ !isFilled }
isDisabled={ !isFilled }
mt={ 4 }
onClick={ onFilterClick }
w="fit-content"
Expand Down
5 changes: 2 additions & 3 deletions ui/advancedFilter/ColumnsButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,21 +39,20 @@ const ColumnsButton = ({ columns, onChange }: Props) => {
colorScheme="gray"
size="sm"
leftIcon={ <IconSvg name="columns" boxSize={ 5 } color="inherit"/> }
// isLoading={ isLoading }
>
{ /* <IconSvg name='columns' boxSize={ 5 }/> */ }
Columns
</Button>
</PopoverTrigger>
<PopoverContent>
<PopoverBody px={ 4 } py={ 6 } display="flex" flexDir="column" rowGap={ 5 }>
<Grid gridTemplateColumns="1fr 1fr">
<Grid gridTemplateColumns="160px 160px" gap={ 3 }>
{ TABLE_COLUMNS.map(col => (
<Checkbox
key={ col.id }
defaultChecked={ columns[col.id] }
onChange={ onCheckboxClick }
id={ col.id }
size="lg"
>
{ col.name }
</Checkbox>
Expand Down
3 changes: 2 additions & 1 deletion ui/advancedFilter/FilterByColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const FilterByColumn = ({ column, filters, columnName, handleFilterChange, searc
);
}
case 'age': {
const value = { age: filters.age, from: filters.age_from, to: filters.age_to };
const value = { age: filters.age || '' as const, from: filters.age_from || '', to: filters.age_to || '' };
return (
<TableColumnFilterWrapper
columnName="Age"
Expand All @@ -73,6 +73,7 @@ const FilterByColumn = ({ column, filters, columnName, handleFilterChange, searc
isLoading={ isLoading }
isActive={ false }
w="106px"
value={ filters.address_relation === 'and' ? 'AND' : 'OR' }
>
<AddressRelationFilter { ...commonProps } value={ filters.address_relation }/>
</TableColumnFilterWrapper>
Expand Down
11 changes: 7 additions & 4 deletions ui/advancedFilter/ItemByColumn.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ const ItemByColumn = ({ item, column, isLoading }: Props) => {
return (
<Flex w="100%" justifyContent="space-between">
<AddressEntity address={ item.from } truncation="constant" isLoading={ isLoading }/>
<AddressFromToIcon
isLoading={ isLoading }
type="out"
/>
</Flex>
);
case 'to':
return <AddressEntity address={ item.to ? item.to : item.created_contract } truncation="constant" isLoading={ isLoading }/>;
case 'or_and':
return (
<AddressFromToIcon
isLoading={ isLoading }
type="unspecified"
/>
);
case 'amount': {
if (item.token?.type === 'ERC-721') {
return <Skeleton isLoaded={ !isLoading }>1</Skeleton>;
Expand Down
12 changes: 7 additions & 5 deletions ui/advancedFilter/filters/AddressFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Flex, Select, Input, InputGroup, InputRightElement, VStack, IconButton } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual';
import type { ChangeEvent } from 'react';
import React from 'react';

Expand Down Expand Up @@ -75,14 +76,14 @@ const AddressFilterInput = ({ address, mode, onModeChange, onChange, onClear, is

const emptyItem = { address: '', mode: 'include' as AddressFilterMode };

const AddressFilter = ({ type, value, handleFilterChange, onClose }: Props) => {
const AddressFilter = ({ type, value = [], handleFilterChange, onClose }: Props) => {
const [ currentValue, setCurrentValue ] =
React.useState<Array<{ address: string; mode: AddressFilterMode }>>([ ...value, emptyItem ] || [ emptyItem ]);
React.useState<Array<{ address: string; mode: AddressFilterMode }>>([ ...value, emptyItem ]);

const handleModeSelectChange = React.useCallback((index: number) => (event: React.ChangeEvent<HTMLSelectElement>) => {
const value = event.target.value as AddressFilterMode;
setCurrentValue(prev => {
prev[index].mode = value;
prev[index] = { ...prev[index], mode: value };
return [ ...prev ];
});
}, []);
Expand Down Expand Up @@ -114,8 +115,8 @@ const AddressFilter = ({ type, value, handleFilterChange, onClose }: Props) => {
const onFilter = React.useCallback(() => {
const includeFilterParam = type === 'from' ? FILTER_PARAM_FROM_INCLUDE : FILTER_PARAM_TO_INCLUDE;
const excludeFilterParam = type === 'from' ? FILTER_PARAM_FROM_EXCLUDE : FILTER_PARAM_TO_EXCLUDE;
const includeValue = currentValue.filter(i => i.mode === 'include').map(i => i.address);
const excludeValue = currentValue.filter(i => i.mode === 'exclude').map(i => i.address);
const includeValue = currentValue.filter(i => i.mode === 'include').map(i => i.address).filter(Boolean);
const excludeValue = currentValue.filter(i => i.mode === 'exclude').map(i => i.address).filter(Boolean);

handleFilterChange(includeFilterParam, includeValue.length ? includeValue : undefined);
handleFilterChange(excludeFilterParam, excludeValue.length ? excludeValue : undefined);
Expand All @@ -125,6 +126,7 @@ const AddressFilter = ({ type, value, handleFilterChange, onClose }: Props) => {
<TableColumnFilter
title={ type === 'from' ? 'From address' : 'To address' }
isFilled={ Boolean(currentValue[0].address) }
isTouched={ !isEqual(currentValue.filter(i => i.address).map(i => JSON.stringify(i)).sort(), value.map(i => JSON.stringify(i)).sort()) }
onFilter={ onFilter }
onReset={ onReset }
onClose={ onClose }
Expand Down
49 changes: 36 additions & 13 deletions ui/advancedFilter/filters/AgeFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Flex, Input, Tag, Text } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual';
import type { ChangeEvent } from 'react';
import React from 'react';

Expand All @@ -14,8 +15,8 @@ const FILTER_PARAM_FROM = 'age_from';
const FILTER_PARAM_TO = 'age_to';
const FILTER_PARAM_AGE = 'age';

const defaultValue = { age: undefined, from: '', to: '' };
type AgeFromToValue = { age?: AdvancedFilterAge; from?: string; to?: string }
const defaultValue = { age: '', from: '', to: '' } as const;
type AgeFromToValue = { age: AdvancedFilterAge | ''; from: string; to: string }

type Props = {
value?: AgeFromToValue;
Expand All @@ -25,25 +26,36 @@ type Props = {
onClose?: () => void;
}

const AgeFilter = ({ value = {}, handleFilterChange, onClose }: Props) => {
const [ currentValue, setCurrentValue ] = React.useState<AgeFromToValue>(value || defaultValue);
const AgeFilter = ({ value = defaultValue, handleFilterChange, onClose }: Props) => {
const [ currentValue, setCurrentValue ] = React.useState<AgeFromToValue>(value);

const handleFromChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
setCurrentValue(prev => ({ to: prev.to, from: event.target.value }));
setCurrentValue(prev => ({ age: '', to: prev.to, from: event.target.value }));
}, []);

const handleToChange = React.useCallback((event: ChangeEvent<HTMLInputElement>) => {
setCurrentValue(prev => ({ from: prev.from, to: event.target.value }));
setCurrentValue(prev => ({ age: '', from: prev.from, to: event.target.value }));
}, []);

const onPresetClick = React.useCallback((event: React.SyntheticEvent) => {
const age = (event.currentTarget as HTMLDivElement).getAttribute('data-id') as AdvancedFilterAge;
setCurrentValue({ age });
}, []);
const from = dayjs((dayjs().valueOf() - getDurationFromAge(age))).toISOString();
handleFilterChange(FILTER_PARAM_FROM, from);
const to = dayjs().toISOString();
handleFilterChange(FILTER_PARAM_TO, to);
handleFilterChange(FILTER_PARAM_AGE, age);
onClose && onClose();
}, [ onClose, handleFilterChange ]);

const onReset = React.useCallback(() => setCurrentValue(defaultValue), []);

const onFilter = React.useCallback(() => {
if (!currentValue.age && !currentValue.to && !currentValue.from) {
handleFilterChange(FILTER_PARAM_FROM, undefined);
handleFilterChange(FILTER_PARAM_TO, undefined);
handleFilterChange(FILTER_PARAM_AGE, undefined);
return;
}
const from = currentValue.age ?
dayjs((dayjs().valueOf() - getDurationFromAge(currentValue.age))).toISOString() :
dayjs(currentValue.from).startOf('day').toISOString();
Expand All @@ -57,6 +69,7 @@ const AgeFilter = ({ value = {}, handleFilterChange, onClose }: Props) => {
<TableColumnFilter
title="Set last duration"
isFilled={ Boolean(currentValue.from || currentValue.to || currentValue.age) }
isTouched={ value.age ? value.age !== currentValue.age : !isEqual(currentValue, value) }
onFilter={ onFilter }
onReset={ onReset }
onClose={ onClose }
Expand All @@ -68,18 +81,28 @@ const AgeFilter = ({ value = {}, handleFilterChange, onClose }: Props) => {
key={ val }
data-id={ val }
onClick={ onPresetClick }
colorScheme={ currentValue.age === val ? 'blue' : 'gray-blue' }
_hover={{ opacity: 0.76 }}
cursor="pointer"
variant="select"
>
{ val }
</Tag>
)) }
</Flex>
<Flex mt={ 3 }>
<Input value={ currentValue.from } onChange={ handleFromChange } placeholder="From" type="date" size="xs"/>
<Input
value={ currentValue.from }
onChange={ handleFromChange }
placeholder="From"
type="date"
size="xs"
/>
<Text mx={ 3 }>{ ndash }</Text>
<Input value={ currentValue.to } onChange={ handleToChange } placeholder="To" type="date" size="xs"/>
<Input
value={ currentValue.to }
onChange={ handleToChange }
placeholder="To"
type="date"
size="xs"
/>
</Flex>
</TableColumnFilter>
);
Expand Down
15 changes: 7 additions & 8 deletions ui/advancedFilter/filters/AmountFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Flex, Input, Tag, Text } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual';
import type { ChangeEvent } from 'react';
import React from 'react';

Expand Down Expand Up @@ -66,13 +67,16 @@ const AmountFilter = ({ value = {}, handleFilterChange, onClose }: Props) => {

const onPresetClick = React.useCallback((event: React.SyntheticEvent) => {
const to = (event.currentTarget as HTMLDivElement).getAttribute('data-id') as string;
setCurrentValue({ from: '', to });
}, []);
handleFilterChange(FILTER_PARAM_FROM, '');
handleFilterChange(FILTER_PARAM_TO, to);
onClose && onClose();
}, [ handleFilterChange, onClose ]);

return (
<TableColumnFilter
title="Amount"
isFilled={ Boolean(currentValue.from || currentValue.to) }
isTouched={ !isEqual(currentValue, value) }
onFilter={ onFilter }
onReset={ onReset }
onClose={ onClose }
Expand All @@ -84,12 +88,7 @@ const AmountFilter = ({ value = {}, handleFilterChange, onClose }: Props) => {
key={ preset.value }
data-id={ preset.value }
onClick={ onPresetClick }
// color="link"
// colorScheme="gray-blue"
colorScheme={ (!currentValue.from || currentValue.from === '0') && currentValue.to === preset.value ? 'blue' : 'gray-blue' }
// isActive={ (!currentValue.from || currentValue.from === '0') && currentValue.to === preset.value }
_hover={{ opacity: 0.76 }}
cursor="pointer"
variant="select"
>
{ preset.name }
</Tag>
Expand Down
30 changes: 17 additions & 13 deletions ui/advancedFilter/filters/AssetFilter.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Flex, Checkbox, CheckboxGroup, Text, Spinner, Select } from '@chakra-ui/react';
import isEqual from 'lodash/isEqual';
import React from 'react';

import type { AdvancedFilterParams } from 'types/api/advancedFilter';
Expand All @@ -7,7 +8,7 @@ import type { TokenInfo } from 'types/api/token';
import useApiQuery from 'lib/api/useApiQuery';
import Tag from 'ui/shared/chakra/Tag';
import ClearButton from 'ui/shared/ClearButton';
import TokenEntity from 'ui/shared/entities/token/TokenEntity';
import * as TokenEntity from 'ui/shared/entities/token/TokenEntity';
import FilterInput from 'ui/shared/filters/FilterInput';
import TableColumnFilter from 'ui/shared/filters/TableColumnFilter';

Expand All @@ -31,8 +32,8 @@ type Props = {
onClose?: () => void;
}

const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
const [ currentValue, setCurrentValue ] = React.useState<Value>(value || []);
const AssetFilter = ({ value = [], handleFilterChange, onClose }: Props) => {
const [ currentValue, setCurrentValue ] = React.useState<Value>([ ...value ]);
const [ searchTerm, setSearchTerm ] = React.useState<string>('');

const onSearchChange = React.useCallback((value: string) => {
Expand All @@ -42,7 +43,7 @@ const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
const handleModeSelectChange = React.useCallback((index: number) => (event: React.ChangeEvent<HTMLSelectElement>) => {
const value = event.target.value as AssetFilterMode;
setCurrentValue(prev => {
prev[index].mode = value;
prev[index] = { ...prev[index], mode: value };
return [ ...prev ];
});
}, []);
Expand Down Expand Up @@ -80,6 +81,7 @@ const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
<TableColumnFilter
title="Asset"
isFilled={ Boolean(currentValue.length) }
isTouched={ !isEqual(currentValue.map(i => JSON.stringify(i)).sort(), value.map(i => JSON.stringify(i)).sort()) }
onFilter={ onFilter }
onReset={ onReset }
onClose={ onClose }
Expand All @@ -92,7 +94,7 @@ const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
initialValue={ searchTerm }
/>
{ !searchTerm && currentValue.map((item, index) => (
<Flex key={ item.token.address } mt={ 3 } alignItems="center">
<Flex key={ item.token.address } alignItems="center">
<Select
size="xs"
borderRadius="base"
Expand All @@ -105,33 +107,34 @@ const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
<option value="include">Include</option>
<option value="exclude">Exclude</option>
</Select>
<TokenEntity token={ item.token } noLink noCopy flexGrow={ 1 }/>
<TokenEntity.default token={ item.token } noLink noCopy flexGrow={ 1 }/>
<ClearButton onClick={ handleRemove(index) }/>
</Flex>
)) }
{ tokensQuery.isLoading && <Spinner display="block" mt={ 3 }/> }
{ tokensQuery.data && !searchTerm && (
<>
<Text color="text_secondary" fontWeight="600" mt={ 3 }>Popular</Text>
<Flex rowGap={ 3 } flexWrap="wrap" gap={ 3 } mt={ 3 }>
<Flex rowGap={ 3 } flexWrap="wrap" gap={ 3 } mb={ 2 }>
{ [ NATIVE_TOKEN, ...tokensQuery.data.items ].map(token => (
<Tag
key={ token.address }
data-id={ token.address }
onClick={ onTokenClick(token) }
colorScheme="gray-blue"
_hover={{ opacity: 0.76 }}
cursor="pointer"
variant="select"
>
{ token.symbol || token.name || token.address }
<Flex flexGrow={ 1 } alignItems="center">
<TokenEntity.Icon token={ token }/>
{ token.symbol || token.name || token.address }
</Flex>
</Tag>
)) }
</Flex>
</>
) }
{ searchTerm && tokensQuery.data && !tokensQuery.data?.items.length && <Text>No tokens found</Text> }
{ searchTerm && tokensQuery.data && Boolean(tokensQuery.data?.items.length) && (
<Flex display="flex" flexDir="column" rowGap={ 3 } maxH="250px" overflowY="scroll" mt={ 3 }>
<Flex display="flex" flexDir="column" rowGap={ 3 } maxH="250px" overflowY="scroll" mt={ 3 } ml="-4px">
<CheckboxGroup value={ currentValue.map(i => i.token.address) }>
{ tokensQuery.data.items.map(token => (
<Flex justifyContent="space-between" alignItems="center" key={ token.address }>
Expand All @@ -141,6 +144,7 @@ const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
onChange={ onTokenClick(token) }
overflow="hidden"
w="100%"
pl={ 1 }
sx={{
'.chakra-checkbox__label': {
overflow: 'hidden',
Expand All @@ -150,7 +154,7 @@ const AssetFilter = ({ value, handleFilterChange, onClose }: Props) => {
},
}}
>
<TokenEntity token={ token } noLink noCopy/>
<TokenEntity.default token={ token } noLink noCopy/>
</Checkbox>
</Flex>
)) }
Expand Down
Loading

0 comments on commit a184eba

Please sign in to comment.