diff --git a/hyperglass/ui/components/path/chart.tsx b/hyperglass/ui/components/path/chart.tsx index eabc753..1df6a94 100644 --- a/hyperglass/ui/components/path/chart.tsx +++ b/hyperglass/ui/components/path/chart.tsx @@ -20,7 +20,7 @@ export const Chart = (props: TChart) => { const flowProps = useBreakpointValue>({ base: { defaultPosition: [0, 300], defaultZoom: 0 }, lg: { defaultPosition: [100, 300], defaultZoom: 0.7 }, - }); + }) ?? { defaultPosition: [100, 300], defaultZoom: 0.7 }; const elements = useMemo(() => [...buildElements({ asn: primary_asn, name: org_name }, data)], [ data, @@ -45,7 +45,7 @@ const ASNode = (props: TNode) => { const color = useColorValue('black', 'white'); const bg = useColorValue('white', 'whiteAlpha.100'); - const { data: asnData, isError, isLoading } = useASNDetail(asn); + const { data: asnData, isError, isLoading } = useASNDetail(String(asn)); return ( <> diff --git a/hyperglass/ui/components/results/individual.tsx b/hyperglass/ui/components/results/individual.tsx index af54bc2..a672f6a 100644 --- a/hyperglass/ui/components/results/individual.tsx +++ b/hyperglass/ui/components/results/individual.tsx @@ -4,6 +4,7 @@ import { Flex, Alert, Tooltip, + Icon, HStack, AccordionItem, AccordionPanel, @@ -60,13 +61,19 @@ export const Result = forwardRef((props, ref) => { const { responses } = useLGState(); - const { data, error, isError, isLoading, refetch } = useLGQuery({ + const { data, error, isError, isLoading, refetch, isFetching, isFetchedAfterMount } = useLGQuery({ queryLocation, queryTarget, queryType, queryVrf, }); + const isCached = useMemo(() => data?.cached || !isFetchedAfterMount, [ + data, + isLoading, + isFetching, + ]); + if (typeof data !== 'undefined') { responses.merge({ [device.name]: data }); } @@ -234,29 +241,26 @@ export const Result = forwardRef((props, ref) => { - - + spacing={1} + flex="1 0 auto" + justifyContent={{ base: 'flex-start', lg: 'flex-end' }}> + - - - + + + - + diff --git a/hyperglass/ui/context/HyperglassProvider.tsx b/hyperglass/ui/context/HyperglassProvider.tsx index 99f3196..35be636 100644 --- a/hyperglass/ui/context/HyperglassProvider.tsx +++ b/hyperglass/ui/context/HyperglassProvider.tsx @@ -6,6 +6,7 @@ import { useBreakpointValue, useTheme as useChakraTheme, } from '@chakra-ui/react'; +import { QueryClient, QueryClientProvider } from 'react-query'; import { makeTheme, defaultTheme } from '~/util'; import type { IConfig, ITheme } from '~/types'; @@ -13,6 +14,8 @@ import type { THyperglassProvider } from './types'; const HyperglassContext = createContext(Object()); +const queryClient = new QueryClient(); + export const HyperglassProvider = (props: THyperglassProvider) => { const { config, children } = props; const value = useMemo(() => config, []); @@ -20,7 +23,9 @@ export const HyperglassProvider = (props: THyperglassProvider) => { const theme = value ? userTheme : defaultTheme; return ( - {children} + + {children} + ); }; diff --git a/hyperglass/ui/hooks/index.ts b/hyperglass/ui/hooks/index.ts index 05b99d6..6339718 100644 --- a/hyperglass/ui/hooks/index.ts +++ b/hyperglass/ui/hooks/index.ts @@ -7,5 +7,4 @@ export * from './useLGState'; export * from './useOpposingColor'; export * from './useStrf'; export * from './useTableToString'; -export * from './useScaledText'; export * from './useScaledTitle'; diff --git a/hyperglass/ui/hooks/types.ts b/hyperglass/ui/hooks/types.ts index 69cae3a..fc8e012 100644 --- a/hyperglass/ui/hooks/types.ts +++ b/hyperglass/ui/hooks/types.ts @@ -1,6 +1,19 @@ +import type { QueryFunctionContext } from 'react-query'; +import type { TFormQuery } from '~/types'; + export interface TOpposingOptions { light?: string; dark?: string; } export type TUseGreetingReturn = [boolean, (v?: boolean) => void]; + +export interface TUseLGQueryFn { + pageParam?: QueryFunctionContext['pageParam']; + queryKey: [string, TFormQuery]; +} + +export interface TUseASNDetailFn { + pageParam?: QueryFunctionContext['pageParam']; + queryKey: string; +} diff --git a/hyperglass/ui/hooks/useASNDetail.ts b/hyperglass/ui/hooks/useASNDetail.ts index 2d1dd2a..807daba 100644 --- a/hyperglass/ui/hooks/useASNDetail.ts +++ b/hyperglass/ui/hooks/useASNDetail.ts @@ -1,11 +1,19 @@ import { useQuery } from 'react-query'; -import type { TASNDetails } from '~/types'; -async function query(asn: string): Promise { +import type { TASNDetails } from '~/types'; +import type { TUseASNDetailFn } from './types'; + +async function query(ctx: TUseASNDetailFn): Promise { + const [asn] = ctx.queryKey; const res = await fetch(`https://api.bgpview.io/asn/${asn}`, { mode: 'cors' }); return await res.json(); } export function useASNDetail(asn: string) { - return useQuery(asn, query); + return useQuery(asn, query, { + refetchOnWindowFocus: false, + refetchInterval: false, + refetchOnMount: false, + cacheTime: Infinity, + }); } diff --git a/hyperglass/ui/hooks/useLGQuery.ts b/hyperglass/ui/hooks/useLGQuery.ts index a6d86e7..8063fae 100644 --- a/hyperglass/ui/hooks/useLGQuery.ts +++ b/hyperglass/ui/hooks/useLGQuery.ts @@ -2,6 +2,7 @@ import { useQuery } from 'react-query'; import { useConfig } from '~/context'; import type { TFormQuery } from '~/types'; +import type { TUseLGQueryFn } from './types'; /** * Fetch Wrapper that incorporates a timeout via a passed AbortController instance. @@ -31,11 +32,12 @@ export async function fetchWithTimeout( } export function useLGQuery(query: TFormQuery) { - const { request_timeout } = useConfig(); + const { request_timeout, cache } = useConfig(); const controller = new AbortController(); - async function runQuery(url: string, requestData: TFormQuery): Promise { - const { queryLocation, queryTarget, queryType, queryVrf } = requestData; + async function runQuery(ctx: TUseLGQueryFn): Promise { + const [url, data] = ctx.queryKey; + const { queryLocation, queryTarget, queryType, queryVrf } = data; const res = await fetchWithTimeout( url, { @@ -57,6 +59,11 @@ export function useLGQuery(query: TFormQuery) { return useQuery( ['/api/query/', query], runQuery, - { refetchInterval: false }, + { + cacheTime: cache.timeout * 1000 * 0.95, + refetchOnWindowFocus: false, + refetchInterval: false, + refetchOnMount: false, + }, ); } diff --git a/hyperglass/ui/hooks/useScaledText.ts b/hyperglass/ui/hooks/useScaledText.ts deleted file mode 100644 index 888fa33..0000000 --- a/hyperglass/ui/hooks/useScaledText.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { useMemo } from 'react'; -import { useMeasure } from 'react-use'; - -import type { UseMeasureRef as UM } from 'react-use/esm/useMeasure'; - -/** - * These type aliases are for the readability of the function below. - */ -type DC = HTMLElement; -type DT = HTMLHeadingElement; -type A = any; -type B = boolean; - -/** - * Wrapper for useMeasure() which determines if a text element should be scaled down due to its - * size relative to its parent's size. - */ -export function useScaledText(deps: A[]): [UM, UM, B] { - // Get a ref & state object for the containing element. - const [containerRef, container] = useMeasure(); - - // Get a ref & state object for the text element. - const [textRef, text] = useMeasure(); - - // Memoize the values. - const textWidth = useMemo(() => text.width, [...deps, text.width !== 0]); - const containerWidth = useMemo(() => container.width, [...deps, container.width]); - - // If the text element is the same size or larger than the container, it should be resized. - const shouldResize = textWidth !== 0 && textWidth >= containerWidth; - - return [containerRef, textRef, shouldResize]; -}