/** @jsx jsx */
import { jsx } from '@emotion/core';
import { forwardRef, useEffect, useState } from 'react';
import {
AccordionItem,
AccordionHeader,
AccordionPanel,
Alert,
Box,
ButtonGroup,
css,
Flex,
Tooltip,
Text,
useColorMode,
useTheme,
} from '@chakra-ui/core';
import { BsLightningFill } from '@meronex/icons/bs';
import styled from '@emotion/styled';
import useAxios from 'axios-hooks';
import strReplace from 'react-string-replace';
import format from 'string-format';
import { startCase } from 'lodash';
import { useConfig, useMedia } from 'app/context';
import {
BGPTable,
CacheTimeout,
CopyButton,
RequeryButton,
ResultHeader,
TextOutput,
} from 'app/components';
import { tableToString } from 'app/util';
format.extend(String.prototype, {});
const FormattedError = ({ keywords, message }) => {
const patternStr = keywords.map(kw => `(${kw})`).join('|');
const pattern = new RegExp(patternStr, 'gi');
let errorFmt;
try {
errorFmt = strReplace(message, pattern, match => (
{match}
));
} catch (err) {
errorFmt = {message};
}
return {keywords.length !== 0 ? errorFmt : message};
};
const AccordionHeaderWrapper = styled(Flex)`
justify-content: space-between;
&:hover {
background-color: ${props => props.hoverBg};
}
&:focus {
box-shadow: 'outline';
}
`;
const statusMap = {
success: 'success',
warning: 'warning',
error: 'warning',
danger: 'error',
};
const color = { dark: 'white', light: 'black' };
const scrollbar = { dark: 'whiteAlpha.300', light: 'blackAlpha.300' };
const scrollbarHover = { dark: 'whiteAlpha.400', light: 'blackAlpha.400' };
const scrollbarBg = { dark: 'whiteAlpha.50', light: 'blackAlpha.50' };
export const Result = forwardRef(
(
{
device,
timeout,
queryLocation,
queryType,
queryVrf,
queryTarget,
index,
resultsComplete,
setComplete,
},
ref,
) => {
const config = useConfig();
const theme = useTheme();
const { isSm } = useMedia();
const { colorMode } = useColorMode();
let [{ data, loading, error }, refetch] = useAxios({
url: '/api/query/',
method: 'post',
data: {
query_location: queryLocation,
query_type: queryType,
query_vrf: queryVrf,
query_target: queryTarget,
},
timeout: timeout,
useCache: false,
});
const [isOpen, setOpen] = useState(false);
const [hasOverride, setOverride] = useState(false);
const handleToggle = () => {
setOpen(!isOpen);
setOverride(true);
};
const errorKw = (error && error.response?.data?.keywords) || [];
let errorMsg;
if (error && error.response?.data?.output) {
errorMsg = error.response.data.output;
} else if (error && error.message.startsWith('timeout')) {
errorMsg = config.messages.request_timeout;
} else if (error?.response?.statusText) {
errorMsg = startCase(error.response.statusText);
} else if (error && error.message) {
errorMsg = startCase(error.message);
} else {
errorMsg = config.messages.general;
}
error && console.error(error);
const errorLevel =
(error?.response?.data?.level && statusMap[error.response?.data?.level]) ?? 'error';
const structuredDataComponent = {
bgp_route: BGPTable,
bgp_aspath: BGPTable,
bgp_community: BGPTable,
ping: TextOutput,
traceroute: TextOutput,
};
let Output = TextOutput;
let copyValue = data?.output;
if (data?.format === 'application/json') {
Output = structuredDataComponent[queryType];
copyValue = tableToString(queryTarget, data, config);
}
if (error) {
copyValue = errorMsg;
}
useEffect(() => {
!loading && resultsComplete === null && setComplete(index);
}, [loading, resultsComplete]);
useEffect(() => {
resultsComplete === index && !hasOverride && setOpen(true);
}, [resultsComplete, index]);
return (
{!error && data && }
{error && (
)}
{config.cache.show_text && data && !error && (
<>
{!isSm && (
)}
{isSm && (
)}
>
)}
);
},
);