diff --git a/hyperglass/exceptions/_common.py b/hyperglass/exceptions/_common.py index 69bb9fc..9963324 100644 --- a/hyperglass/exceptions/_common.py +++ b/hyperglass/exceptions/_common.py @@ -2,7 +2,7 @@ # Standard Library import json as _json -from typing import Any, Dict, List, Union, Literal, Optional +from typing import Any, Dict, List, Union, Literal, Optional, Set # Third Party from pydantic import ValidationError @@ -48,7 +48,7 @@ class HyperglassError(Exception): return { "message": self._message, "level": self._level, - "keywords": self._keywords, + "keywords": self.keywords, } def json(self) -> str: @@ -76,6 +76,18 @@ class HyperglassError(Exception): return "\n".join(errs) + def _process_keywords(self) -> None: + out: Set[str] = set() + for val in self._keywords: + if isinstance(val, str): + out.add(val) + elif isinstance(val, list): + for v in val: + out.add(v) + else: + out.add(str(val)) + self._keywords = list(out) + @property def message(self) -> str: """Return the instance's `message` attribute.""" @@ -89,6 +101,7 @@ class HyperglassError(Exception): @property def keywords(self) -> List[str]: """Return the instance's `keywords` attribute.""" + self._process_keywords() return self._keywords @property diff --git a/hyperglass/ui/components/results/header.tsx b/hyperglass/ui/components/results/header.tsx index 0adf3ea..f82a62a 100644 --- a/hyperglass/ui/components/results/header.tsx +++ b/hyperglass/ui/components/results/header.tsx @@ -1,5 +1,5 @@ +import { AccordionIcon, Box, HStack, Spinner, Text, Tooltip } from '@chakra-ui/react'; import { useMemo } from 'react'; -import { AccordionIcon, Box, Spinner, HStack, Text, Tooltip } from '@chakra-ui/react'; import { useConfig } from '~/context'; import { DynamicIcon } from '~/elements'; import { useColorValue, useOpposingColor, useStrf } from '~/hooks'; @@ -52,7 +52,7 @@ export const ResultHeader = (props: ResultHeaderProps): JSX.Element => { ) : ( = ( const addResponse = useFormState(s => s.addResponse); const form = useFormState(s => s.form); + const [errorLevel, _setErrorLevel] = useState('error'); - const { data, error, isError, isLoading, refetch, isFetchedAfterMount } = useLGQuery( - { - queryLocation, - queryTarget: form.queryTarget, - queryType: form.queryType, - }, + const setErrorLevel = (level: ResponseLevel): void => { + let e: ErrorLevels = 'error'; + switch (level) { + case 'success': + e = level; + break; + case 'warning' || 'error': + e = 'warning'; + break; + } + _setErrorLevel(e); + }; + + const { data, error, isLoading, refetch, isFetchedAfterMount } = useLGQuery( + { queryLocation, queryTarget: form.queryTarget, queryType: form.queryType }, { onSuccess(data) { if (device !== null) { addResponse(device.id, data); } + if (isLGOutputOrError(data)) { + console.error(data); + setErrorLevel(data.level); + } }, onError(error) { - console.error(error); + console.error({ error }); + if (isLGOutputOrError(error)) { + setErrorLevel(error.level); + } }, }, ); + + const isError = useMemo(() => isLGOutputOrError(data), [data, error]); + const isCached = useMemo(() => data?.cached || !isFetchedAfterMount, [data, isFetchedAfterMount]); const strF = useStrf(); @@ -123,23 +143,6 @@ const _Result: React.ForwardRefRenderFunction = ( return messages.general; }, [error, data, messages.general, messages.requestTimeout]); - const errorLevel = useMemo(() => { - const statusMap = { - success: 'success', - warning: 'warning', - error: 'warning', - danger: 'error', - } as { [K in ResponseLevel]: 'success' | 'warning' | 'error' }; - - let e: ErrorLevels = 'error'; - - if (isLGError(error)) { - const idx = error.level as ResponseLevel; - e = statusMap[idx]; - } - return e; - }, [error]); - const tableComponent = useMemo(() => { let result = false; if (data?.format === 'application/json') {