Stats page now stores the search query in url

main
Štěpán Škorpil 2022-05-15 12:57:18 +02:00
rodzic 861e2a1476
commit 75c9fd63e7
5 zmienionych plików z 33 dodań i 25 usunięć

Wyświetl plik

@ -16,8 +16,6 @@ const CACHE_KEY = 'stats'
const handleGetStats = async (req: NextApiRequest, res: NextApiResponse<StatsResponse>): Promise<void> => { const handleGetStats = async (req: NextApiRequest, res: NextApiResponse<StatsResponse>): Promise<void> => {
const query = await statsRequestSchema.parseAsync(req.query) const query = await statsRequestSchema.parseAsync(req.query)
query.sortBy = query.sortBy ?? 'nodeCount'
query.sortWay = query.sortWay ?? 'desc'
const cacheKey = `${CACHE_KEY}_${query.sortWay}_${query.sortBy}` const cacheKey = `${CACHE_KEY}_${query.sortWay}_${query.sortBy}`
if (!cache.has(cacheKey)) { if (!cache.has(cacheKey)) {
console.info('Retrieving new stats', { cacheKey, query }) console.info('Retrieving new stats', { cacheKey, query })

Wyświetl plik

@ -56,8 +56,8 @@ const Feeds: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
setResults([]) setResults([])
setHasMore(false) setHasMore(false)
setLoaded(false) setLoaded(false)
router.query = query
router.push(router) router.push({ query })
if ((query.search ?? '').length < 1) { if ((query.search ?? '').length < 1) {
console.info('Query too short.') console.info('Query too short.')

Wyświetl plik

@ -54,8 +54,7 @@ const Nodes: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
const loadNewQueryResults = () => { const loadNewQueryResults = () => {
console.info('Cancelling searches') console.info('Cancelling searches')
source.cancel('New query on the way') source.cancel('New query on the way')
router.query = query router.push({ query })
router.push(router)
setResults([]) setResults([])
setHasMore(false) setHasMore(false)
setLoaded(false) setLoaded(false)

Wyświetl plik

@ -8,23 +8,24 @@ import axios from 'axios'
import { StatsResponse, statsResponseSchema } from '../types/StatsResponse' import { StatsResponse, statsResponseSchema } from '../types/StatsResponse'
import SoftwareBadge from '../components/badges/SoftwareBadge' import SoftwareBadge from '../components/badges/SoftwareBadge'
import ProgressBar from '../components/ProgressBar' import ProgressBar from '../components/ProgressBar'
import { StatsRequestSortBy } from '../types/StatsRequest' import { StatsRequest, statsRequestSchema, StatsRequestSortBy } from '../types/StatsRequest'
import SortToggle from '../components/SortToggle' import SortToggle from '../components/SortToggle'
import getMatomo from '../lib/getMatomo' import getMatomo from '../lib/getMatomo'
import { Sort } from '../types/Sort' import { useRouter } from 'next/router'
let source = axios.CancelToken.source() let source = axios.CancelToken.source()
const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }) => { const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> = ({ matomoConfig }) => {
const router = useRouter()
const routerQuery = statsRequestSchema.parse(router.query)
console.log('Router query', routerQuery)
const [query, setQuery] = useState<StatsRequest>(routerQuery)
const [loading, setLoading] = useState<boolean>(true) const [loading, setLoading] = useState<boolean>(true)
const [loaded, setLoaded] = useState<boolean>(false) const [loaded, setLoaded] = useState<boolean>(false)
const [stats, setStats] = useState<StatsResponse | null>(null) const [stats, setStats] = useState<StatsResponse | null>(null)
const [sort, setSort] = useState<Sort>({
sortBy: 'nodeCount', sortWay: 'desc'
})
const toggleSort = (sortBy: StatsRequestSortBy) => { const toggleSort = (sortBy: StatsRequestSortBy) => {
const sortWay = sort.sortBy === sortBy && sort.sortWay === 'asc' ? 'desc' : 'asc' const sortWay = query.sortBy === sortBy && query.sortWay === 'asc' ? 'desc' : 'asc'
getMatomo(matomoConfig).trackEvent({ getMatomo(matomoConfig).trackEvent({
category: 'stats', category: 'stats',
action: 'sort', action: 'sort',
@ -35,19 +36,20 @@ const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
} }
] ]
}) })
setSort({ const newQuery:StatsRequest = { ...query }
sortBy: sortBy, newQuery.sortBy = sortBy
sortWay: sortWay newQuery.sortWay = sortWay
}) setQuery(newQuery)
} }
const retrieveStats = async () => { const retrieveStats = async () => {
console.info('Retrieving stats', { sort }) console.info('Retrieving stats', { query })
source = axios.CancelToken.source() source = axios.CancelToken.source()
setLoading(true) setLoading(true)
await router.push({ query })
try { try {
const response = await axios.get('/api/stats', { const response = await axios.get('/api/stats', {
params: sort, params: query,
cancelToken: source.token cancelToken: source.token
}) })
const stats = await statsResponseSchema.parseAsync(response.data) const stats = await statsResponseSchema.parseAsync(response.data)
@ -67,7 +69,7 @@ const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
} }
useEffect(() => { useEffect(() => {
loadStats() loadStats()
}, [sort]) }, [query])
const sum = { const sum = {
nodeCount: 0, nodeCount: 0,
accountCount: 0, accountCount: 0,
@ -101,22 +103,22 @@ const Stats: React.FC<InferGetServerSidePropsType<typeof getServerSideProps>> =
<thead> <thead>
<tr> <tr>
<th> <th>
<SortToggle onToggle={toggleSort} field={'softwareName'} sort={sort}> <SortToggle onToggle={toggleSort} field={'softwareName'} sort={query}>
Software name Software name
</SortToggle> </SortToggle>
</th> </th>
<th className={'text-end'}> <th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'nodeCount'} sort={sort}> <SortToggle onToggle={toggleSort} field={'nodeCount'} sort={query}>
Instance count Instance count
</SortToggle> </SortToggle>
</th> </th>
<th className={'text-end'}> <th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'accountCount'} sort={sort}> <SortToggle onToggle={toggleSort} field={'accountCount'} sort={query}>
Account count Account count
</SortToggle> </SortToggle>
</th> </th>
<th className={'text-end'}> <th className={'text-end'}>
<SortToggle onToggle={toggleSort} field={'channelCount'} sort={sort}> <SortToggle onToggle={toggleSort} field={'channelCount'} sort={query}>
Channel count Channel count
</SortToggle> </SortToggle>
</th> </th>

Wyświetl plik

@ -1,9 +1,18 @@
import { z } from 'zod' import { z } from 'zod'
import { transform, undefinedToDefault } from '../lib/transform'
export const statsRequestSortBySchema = z.enum(['nodeCount', 'accountCount', 'channelCount', 'softwareName']) export const statsRequestSortBySchema = z.enum(['nodeCount', 'accountCount', 'channelCount', 'softwareName'])
export const statsRequestSortWaySchema = z.enum(['asc', 'desc']) export const statsRequestSortWaySchema = z.enum(['asc', 'desc'])
export const statsRequestSchema = z.object({ export const statsRequestSchema = z.object({
sortBy: z.optional(statsRequestSortBySchema), sortBy: transform(
sortWay: z.optional(statsRequestSortWaySchema) z.optional(statsRequestSortBySchema),
undefinedToDefault<StatsRequestSortBy>('accountCount'),
z.optional(statsRequestSortBySchema)
),
sortWay: transform(
z.optional(statsRequestSortWaySchema),
undefinedToDefault<StatsRequestSortWay>('desc'),
statsRequestSortWaySchema
)
}) })
export type StatsRequest = z.infer<typeof statsRequestSchema> export type StatsRequest = z.infer<typeof statsRequestSchema>