diff --git a/webapp/src/components/SearchBar/index.js b/webapp/src/components/SearchBar/index.js index 550fd57d..5a333354 100644 --- a/webapp/src/components/SearchBar/index.js +++ b/webapp/src/components/SearchBar/index.js @@ -13,6 +13,8 @@ import TextField from '@mui/material/TextField' import Typography from '@mui/material/Typography' import SearchOutlinedIcon from '@mui/icons-material/SearchOutlined' +import useDebounceState from '../../hooks/customHooks/useDebounceState' + import styles from './styles' const useStyles = makeStyles(styles) @@ -21,15 +23,17 @@ const SearchBar = ({ filters: rootFilters, onChange, chips, - translationScope + translationScope, + delay, }) => { const classes = useStyles() const { t } = useTranslation(translationScope) const [selected, setSelected] = useState(chips[0]?.name ?? '') - const [filters, setFilters] = useState({}) + const [filters, setFilters] = useState(rootFilters || {}) + const debouncedFilter = useDebounceState(filters, delay) const handleOnChange = (key) => (event) => { - setFilters({ ...filters, [key]: event.target.value }) + setFilters(prev => ({ ...prev, [key]: event.target.value })) } const handleOnClick = () => { @@ -53,52 +57,53 @@ const SearchBar = ({ setFilters(rootFilters || {}) }, [rootFilters]) + useEffect(() => { + onChange(filters) + // eslint-disable-next-line + }, [debouncedFilter, onChange]) + return ( -
-
- - - - {`${t('title')}:`} - - - - - - - ) - }} - onKeyDown={handleOnKeyDown} - onChange={handleOnChange('owner')} - /> -
- {chips.map((chip, index) => ( - handleOnClickChip(chip.name)} - className={clsx({ - [classes.selected]: selected === chip.name - })} - /> - ))} -
-
-
-
-
+ <> + + + {`${t('title')}:`} + + + + + + ), + }} + onKeyDown={handleOnKeyDown} + onChange={handleOnChange('owner')} + /> +
+ {chips.map((chip, index) => ( + handleOnClickChip(chip.name)} + className={clsx({ + [classes.selected]: selected === chip.name, + })} + /> + ))} +
+
+
+ ) } @@ -106,12 +111,14 @@ SearchBar.propTypes = { filters: PropTypes.any, onChange: PropTypes.func, translationScope: PropTypes.string, - chips: PropTypes.array + chips: PropTypes.array, + delay: PropTypes.number, } SearchBar.defaultProps = { onChange: () => {}, - chips: [] + chips: [], + delay: 500, } export default memo(SearchBar) diff --git a/webapp/src/hooks/customHooks/useBlockProducerState.js b/webapp/src/hooks/customHooks/useBlockProducerState.js index f77b46ae..4bb60ee1 100644 --- a/webapp/src/hooks/customHooks/useBlockProducerState.js +++ b/webapp/src/hooks/customHooks/useBlockProducerState.js @@ -23,13 +23,12 @@ const CHIPS_NAMES = ['all', ...eosConfig.producerTypes] const useBlockProducerState = () => { const [ - { filters, pagination, loading, producers, info }, + { filters, pagination, loading, producers }, { handleOnSearch, handleOnPageChange, setPagination }, ] = useSearchState({ query: PRODUCERS_QUERY }) const { data: dataHistory, loading: loadingHistory } = useSubscription( BLOCK_TRANSACTIONS_HISTORY, ) - const [totalPages, setTotalPages] = useState(1) const [items, setItems] = useState([]) const [missedBlocks, setMissedBlocks] = useState({}) @@ -37,12 +36,6 @@ const useBlockProducerState = () => { return { name: e } }) - useEffect(() => { - if (!info) return - - setTotalPages(Math.ceil(info.producers?.count / pagination.limit)) - }, [info, pagination.limit]) - useEffect(() => { if (eosConfig.networkName === 'lacchain') return @@ -79,7 +72,6 @@ const useBlockProducerState = () => { chips, items, loading, - totalPages, missedBlocks, pagination, }, diff --git a/webapp/src/hooks/customHooks/useEndpointsState.js b/webapp/src/hooks/customHooks/useEndpointsState.js index 10e53272..5a6ee5c5 100644 --- a/webapp/src/hooks/customHooks/useEndpointsState.js +++ b/webapp/src/hooks/customHooks/useEndpointsState.js @@ -1,54 +1,34 @@ import { useState, useEffect, useCallback } from 'react' -import { useLazyQuery } from '@apollo/client' import { ENDPOINTS_QUERY } from '../../gql' +import useSearchState from './useSearchState' + const useEndpointsState = ({ useCache }) => { - const [load, { loading, data }] = useLazyQuery(ENDPOINTS_QUERY, { + const [ + { pagination, loading, producers, filters }, + { handleOnSearch, handleOnPageChange, setPagination }, + ] = useSearchState({ + query: ENDPOINTS_QUERY, pollInterval: useCache ? 0 : 120000, fetchPolicy: useCache ? 'cache-first' : 'cache-and-network', }) - const [producers, setProducers] = useState([]) const [updatedAt, setUpdatedAt] = useState() - const [pagination, setPagination] = useState({ - page: 1, - limit: 20, - totalPages: 0, - where: { nodes: { endpoints: { value: { _gt: '' } } } }, - }) + const [items, setItems] = useState() useEffect(() => { - load({ - variables: { - offset: (pagination.page - 1) * pagination.limit, - limit: pagination.limit, - where: pagination.where, - endpointFilter: pagination.endpointFilter, - }, - }) - // eslint-disable-next-line - }, [ - pagination.page, - pagination.where, - pagination.limit, - pagination.endpointFilter, - ]) - - useEffect(() => { - if (!data?.info) return - setPagination(prev => ({ ...prev, - totalPages: Math.ceil(data?.info.producers?.count / pagination.limit), + limit: 20, + where: { ...prev.where, nodes: { endpoints: { value: { _gt: '' } } } }, })) - // eslint-disable-next-line - }, [data?.info, pagination.limit]) + }, [setPagination]) useEffect(() => { - if (!data?.producers) return + if (!producers) return - setProducers( - data.producers.map(producer => { + setItems( + producers.map(producer => { const endpoints = { api: [], ssl: [], p2p: [] } const inserted = [] @@ -73,20 +53,10 @@ const useEndpointsState = ({ useCache }) => { }), ) - if (!data.producers?.[0]?.updated_at) return + if (!producers?.[0]?.updated_at) return - setUpdatedAt(data.producers[0].updated_at) - // eslint-disable-next-line - }, [data?.producers]) - - const handleOnPageChange = (_, page) => { - if (pagination.page === page) return - - setPagination(prev => ({ - ...prev, - page, - })) - } + setUpdatedAt(producers[0].updated_at) + }, [producers]) const handleFilter = useCallback(value => { const filter = value @@ -96,16 +66,16 @@ const useEndpointsState = ({ useCache }) => { setPagination(prev => ({ ...prev, page: 1, - where: { nodes: { endpoints: filter } }, + where: { ...prev.where, nodes: { endpoints: filter } }, endpointFilter: value ? { _or: [{ type: { _eq: 'p2p' } }, filter] } : undefined, })) - }, []) + }, [setPagination]) return [ - { loading, pagination, producers, updatedAt }, - { handleFilter, handleOnPageChange, setPagination }, + { loading, pagination, producers: items, updatedAt, filters }, + { handleFilter, handleOnPageChange, handleOnSearch, setPagination }, ] } diff --git a/webapp/src/hooks/customHooks/useNodeState.js b/webapp/src/hooks/customHooks/useNodeState.js index 6f656174..c4cfb0e4 100644 --- a/webapp/src/hooks/customHooks/useNodeState.js +++ b/webapp/src/hooks/customHooks/useNodeState.js @@ -7,7 +7,7 @@ import useSearchState from './useSearchState' const useNodeState = () => { const [ - { filters, pagination, loading, producers, info }, + { filters, pagination, loading, producers }, { handleOnSearch, handleOnPageChange, setPagination }, ] = useSearchState({ query: NODES_QUERY }) const [items, setItems] = useState([]) @@ -40,15 +40,6 @@ const useNodeState = () => { })) }, [filters.name, setPagination]) - useEffect(() => { - if (!info) return - - setPagination((prev) => ({ - ...prev, - pages: Math.ceil(info.producers?.count / prev.limit), - })) - }, [info, setPagination]) - useEffect(() => { if (!producers) return diff --git a/webapp/src/hooks/customHooks/useSearchState.js b/webapp/src/hooks/customHooks/useSearchState.js index 74085109..f169e47e 100644 --- a/webapp/src/hooks/customHooks/useSearchState.js +++ b/webapp/src/hooks/customHooks/useSearchState.js @@ -1,11 +1,11 @@ -import { useState, useEffect } from 'react' +import { useState, useEffect, useCallback } from 'react' import { useLazyQuery } from '@apollo/client' import { useLocation } from 'react-router-dom' import queryString from 'query-string' -const useSearchState = ({ query }) => { +const useSearchState = ({ query, ...options }) => { const [loadProducers, { loading = true, data: { producers, info } = {} }] = - useLazyQuery(query) + useLazyQuery(query, options) const location = useLocation() const [pagination, setPagination] = useState({ page: 1, @@ -15,20 +15,22 @@ const useSearchState = ({ query }) => { }) const [filters, setFilters] = useState({ name: 'all', owner: '' }) - const handleOnSearch = (newFilters) => { - setPagination((prev) => ({ + const handleOnSearch = useCallback(newFilters => { + setPagination(prev => ({ ...prev, page: 1, where: { - ...pagination.where, + ...prev.where, owner: { _like: `%${newFilters?.owner ?? ''}%` }, }, })) setFilters(newFilters) - } + }, []) const handleOnPageChange = (_, page) => { - setPagination((prev) => ({ + if (pagination.page === page) return + + setPagination(prev => ({ ...prev, page, })) @@ -40,26 +42,43 @@ const useSearchState = ({ query }) => { where: pagination.where, offset: (pagination.page - 1) * pagination.limit, limit: pagination.limit, - nodeFilter: pagination.nodeFilter + nodeFilter: pagination.nodeFilter, + endpointFilter: pagination.endpointFilter, }, }) // eslint-disable-next-line - }, [pagination.where, pagination.page, pagination.limit, pagination.offset, pagination.nodeFilter]) + }, [ + pagination.where, + pagination.page, + pagination.limit, + pagination.offset, + pagination.nodeFilter, + pagination.endpointFilter + ]) useEffect(() => { const params = queryString.parse(location.search) if (!params.owner) return - setPagination((prev) => ({ + setPagination(prev => ({ ...prev, page: 1, where: { owner: { _like: `%${params.owner}%` } }, })) - setFilters((prev) => ({ ...prev, owner: params.owner })) + setFilters(prev => ({ ...prev, owner: params.owner })) }, [location.search]) + useEffect(() => { + if (!info) return + + setPagination(prev => ({ + ...prev, + pages: Math.ceil(info.producers?.count / prev.limit), + })) + }, [info]) + return [ { filters, pagination, loading, producers, info }, { diff --git a/webapp/src/routes/Accounts/index.js b/webapp/src/routes/Accounts/index.js index e7d29199..d753c0b5 100644 --- a/webapp/src/routes/Accounts/index.js +++ b/webapp/src/routes/Accounts/index.js @@ -27,6 +27,7 @@ const Accounts = () => { diff --git a/webapp/src/routes/BlockProducers/index.js b/webapp/src/routes/BlockProducers/index.js index 43fef27c..928fee2a 100644 --- a/webapp/src/routes/BlockProducers/index.js +++ b/webapp/src/routes/BlockProducers/index.js @@ -46,7 +46,7 @@ PaginationWrapper.propTypes = { const Producers = () => { const classes = useStyles() const [ - { filters, chips, items, loading, totalPages, missedBlocks, pagination }, + { filters, chips, items, loading, missedBlocks, pagination }, { handleOnSearch, handleOnPageChange }, ] = useBlockProducerState() @@ -81,7 +81,7 @@ const Producers = () => { )} { const classes = useStyles() const { t } = useTranslation('endpointsListRoute') const [ - { loading, pagination, producers, updatedAt }, - { handleFilter, handleOnPageChange, setPagination }, + { loading, pagination, producers, updatedAt, filters }, + { handleFilter, handleOnSearch, handleOnPageChange, setPagination }, ] = useEndpointsState({ useCache: false }) return ( @@ -83,19 +84,26 @@ const EndpointsList = () => { +
+ +
{loading ? ( ) : ( <> - {!!producers.length ? ( + {!!producers?.length ? ( ) : ( )} - {pagination.totalPages > 1 && ( + {pagination.pages > 1 && (
({ alignSelf: 'center', margin: theme.spacing(4), }, + searchWrapper: { + flex: '100%', + marginTop: theme.spacing(1), + marginBottom: theme.spacing(1), + '& .MuiGrid-root': { + paddingTop: '0px !important', + }, + }, select: { minWidth: 150, },