diff --git a/docs/docs/ui/text.mdx b/docs/docs/ui/text.mdx index c9eff8f..fc41528 100644 --- a/docs/docs/ui/text.mdx +++ b/docs/docs/ui/text.mdx @@ -8,19 +8,21 @@ description: Customize the text used in the web UI ## `text` -| Parameter | Type | Default | Description | -| :--------------- | :----: | :------------------------------ | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `cache_prefix` | String | `'Results cached for '` | Text displayed with the cache timeout countdown. | -| `cache_icon` | String | `'Cached Response from {time}'` | Text displayed when a user hovers over the lightning bolt icon, which is displayed when a response from the server was a cached response. `{time}` is replaced with the _original_ query's timestamp. | -| `completed_time` | String | `'Completed in {seconds}'` | Text displayed when a user hovers over the success icon for a query result. `{seconds}` will be replaced with 'n seconds' where n is the time a query took to complete. | -| `fqdn_tooltip` | String | `'Use {protocol}'` | Text displayed when a user hovers over the IPv4 or IPv6 button on an FQDN target resolved by DNS. `{protocol}` is replaced with the relevant IP protocol. | -| `query_location` | String | `'Location'` | Query Location (router) form label. | -| `query_target` | String | `'Target'` | Query Target (IP/hostname/community/AS Path) form label. | -| `query_type` | String | `'Query Type'` | Query Type (BGP Route, Ping, Traceroute, etc.) form label. | -| `query_vrf` | String | `'Routing Table'` | Query VRF form label. | -| `subtitle` | String | `'Network Looking Glass'` | Subtitle text. value. | -| `title` | String | `'hyperglass'` | Title text. | -| `title_mode` | String | `'text_only'` | Set the title mode. Must be text_only, logo_only, logo_subtitle, or all | +| Parameter | Type | Default | Description | +| :--------------- | :----: | :-------------------------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `cache_prefix` | String | `'Results cached for '` | Text displayed with the cache timeout countdown. | +| `cache_icon` | String | `'Cached Response from {time}'` | Text displayed when a user hovers over the lightning bolt icon, which is displayed when a response from the server was a cached response. `{time}` is replaced with the _original_ query's timestamp. | +| `completed_time` | String | `'Completed in {seconds}'` | Text displayed when a user hovers over the success icon for a query result. `{seconds}` will be replaced with 'n seconds' where n is the time a query took to complete. | +| `fqdn_message` | String | `'Your browser has resolved {fqdn} to'` | Text displayed when prompting a user to select a resolve IPv4 or IPv6 address for an FQDN query. | +| `fqdn_error` | String | `'Unable to resolve {fqdn}'` | Text displayed when an FQDN is not resolvable. | +| `fqdn_button` | String | `'Try Again'` | Button text used when an FQDN is not resolvable. | +| `query_location` | String | `'Location'` | Query Location (router) form label. | +| `query_target` | String | `'Target'` | Query Target (IP/hostname/community/AS Path) form label. | +| `query_type` | String | `'Query Type'` | Query Type (BGP Route, Ping, Traceroute, etc.) form label. | +| `query_vrf` | String | `'Routing Table'` | Query VRF form label. | +| `subtitle` | String | `'Network Looking Glass'` | Subtitle text. value. | +| `title` | String | `'hyperglass'` | Title text. | +| `title_mode` | String | `'text_only'` | Set the title mode. Must be text_only, logo_only, logo_subtitle, or all | ### Title Mode diff --git a/hyperglass/models/config/web.py b/hyperglass/models/config/web.py index 85b432f..8a72884 100644 --- a/hyperglass/models/config/web.py +++ b/hyperglass/models/config/web.py @@ -127,6 +127,8 @@ class Text(HyperglassModel): query_vrf: StrictStr = "Routing Table" fqdn_tooltip: StrictStr = "Use {protocol}" # Formatted by Javascript fqdn_message: StrictStr = "Your browser has resolved {fqdn} to" # Formatted by Javascript + fqdn_error: StrictStr = "Unable to resolve {fqdn}" # Formatted by Javascript + fqdn_error_button: StrictStr = "Try Again" cache_prefix: StrictStr = "Results cached for " cache_icon: StrictStr = "Cached from {time} UTC" # Formatted by Javascript complete_time: StrictStr = "Completed in {seconds}" # Formatted by Javascript diff --git a/hyperglass/ui/components/form/resolvedTarget.tsx b/hyperglass/ui/components/form/resolvedTarget.tsx index 569b370..305f55c 100644 --- a/hyperglass/ui/components/form/resolvedTarget.tsx +++ b/hyperglass/ui/components/form/resolvedTarget.tsx @@ -1,9 +1,17 @@ import { useEffect, useMemo } from 'react'; -import { Button, Stack, Text, VStack } from '@chakra-ui/react'; -import { FiArrowRightCircle as RightArrow } from '@meronex/icons/fi'; +import dynamic from 'next/dynamic'; +import { Button, chakra, Icon, Stack, Text, VStack } from '@chakra-ui/react'; import { useConfig, useColorValue } from '~/context'; import { useStrf, useLGState, useDNSQuery } from '~/hooks'; +const RightArrow = chakra( + dynamic(() => import('@meronex/icons/fa').then(i => i.FaArrowCircleRight)), +); + +const LeftArrow = chakra( + dynamic(() => import('@meronex/icons/fa').then(i => i.FaArrowCircleLeft)), +); + import type { DnsOverHttps } from '~/types'; import type { TResolvedTarget } from './types'; @@ -17,31 +25,38 @@ function findAnswer(data: DnsOverHttps.Response | undefined): string { } export const ResolvedTarget = (props: TResolvedTarget) => { - const { setTarget } = props; + const { setTarget, errorClose } = props; const { web } = useConfig(); const { displayTarget, isSubmitting, families, queryTarget } = useLGState(); const color = useColorValue('secondary.500', 'secondary.300'); + const errorColor = useColorValue('red.500', 'red.300'); const query4 = Array.from(families.value).includes(4); const query6 = Array.from(families.value).includes(6); const tooltip4 = useStrf(web.text.fqdn_tooltip, { protocol: 'IPv4' }); const tooltip6 = useStrf(web.text.fqdn_tooltip, { protocol: 'IPv6' }); - const [messageStart, messageEnd] = useMemo(() => web.text.fqdn_message.split('{fqdn}'), [ - web.text.fqdn_message, - ]); - const { data: data4, isLoading: isLoading4, isError: isError4 } = useDNSQuery( + const [messageStart, messageEnd] = web.text.fqdn_message.split('{fqdn}'); + const [errorStart, errorEnd] = web.text.fqdn_error.split('{fqdn}'); + + const { data: data4, isLoading: isLoading4, isError: isError4, error: error4 } = useDNSQuery( displayTarget.value, 4, ); - const { data: data6, isLoading: isLoading6, isError: isError6 } = useDNSQuery( + const { data: data6, isLoading: isLoading6, isError: isError6, error: error6 } = useDNSQuery( displayTarget.value, 6, ); + isError4 && console.error(error4); + isError6 && console.error(error6); + + const answer4 = useMemo(() => findAnswer(data4), [data4]); + const answer6 = useMemo(() => findAnswer(data6), [data6]); + function handleOverride(value: string): void { setTarget({ field: 'query_target', value }); } @@ -62,40 +77,60 @@ export const ResolvedTarget = (props: TResolvedTarget) => { return ( - - {messageStart} - - {`${displayTarget.value}`.toLowerCase()} + {(answer4 || answer6) && ( + + {messageStart} + + {`${displayTarget.value}`.toLowerCase()} + + {messageEnd} - {messageEnd} - + )} - {!isLoading4 && !isError4 && query4 && findAnswer(data4) && ( + {!isLoading4 && !isError4 && query4 && answer4 && ( )} - {!isLoading6 && !isError6 && query6 && findAnswer(data6) && ( + {!isLoading6 && !isError6 && query6 && answer6 && ( )} + {!answer4 && !answer6 && ( + <> + + {errorStart} + + {`${displayTarget.value}`.toLowerCase()} + + {errorEnd} + + + + )} ); diff --git a/hyperglass/ui/components/form/types.ts b/hyperglass/ui/components/form/types.ts index 2d0070c..b85526b 100644 --- a/hyperglass/ui/components/form/types.ts +++ b/hyperglass/ui/components/form/types.ts @@ -40,4 +40,5 @@ export interface TQueryTarget { export interface TResolvedTarget { setTarget(e: OnChangeArgs): void; + errorClose(): void; } diff --git a/hyperglass/ui/components/submit/submit.tsx b/hyperglass/ui/components/submit/submit.tsx index 179b881..5f02bb0 100644 --- a/hyperglass/ui/components/submit/submit.tsx +++ b/hyperglass/ui/components/submit/submit.tsx @@ -63,7 +63,7 @@ const MSubmitButton = (props: TRSubmitButton) => { - {isOpen && } + {isOpen && } @@ -83,7 +83,9 @@ const DSubmitButton = (props: TRSubmitButton) => { - {isOpen && } + + {isOpen && } + ); diff --git a/hyperglass/ui/types/config.ts b/hyperglass/ui/types/config.ts index 2730ba8..38493bf 100644 --- a/hyperglass/ui/types/config.ts +++ b/hyperglass/ui/types/config.ts @@ -36,6 +36,8 @@ export interface IConfigWebText { query_vrf: string; fqdn_tooltip: string; fqdn_message: string; + fqdn_error: string; + fqdn_error_button: string; cache_prefix: string; cache_icon: string; complete_time: string;