/** @jsx jsx */ import { jsx } from "@emotion/core"; import { useEffect, useState } from "react"; import { AccordionItem, AccordionHeader, AccordionPanel, Alert, Box, ButtonGroup, css, Flex, Tooltip, Text, useColorMode, useTheme } from "@chakra-ui/core"; import styled from "@emotion/styled"; import LightningBolt from "~/components/icons/LightningBolt"; import useAxios from "axios-hooks"; import strReplace from "react-string-replace"; import format from "string-format"; import { startCase } from "lodash"; import useConfig from "~/components/HyperglassProvider"; import useMedia from "~/components/MediaProvider"; import CopyButton from "~/components/CopyButton"; import RequeryButton from "~/components/RequeryButton"; import ResultHeader from "~/components/ResultHeader"; import CacheTimeout from "~/components/CacheTimeout"; import BGPTable from "~/components/BGPTable"; import TextOutput from "~/components/TextOutput"; 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 structuredDataComponent = { bgp_route: BGPTable, bgp_aspath: BGPTable, bgp_community: BGPTable, ping: TextOutput, traceroute: TextOutput }; 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" }; const Result = React.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"; let Output = TextOutput; if (data?.format === "application/json") { Output = structuredDataComponent[queryType]; } useEffect(() => { !loading && resultsComplete === null && setComplete(index); }, [loading, resultsComplete]); useEffect(() => { resultsComplete === index && !hasOverride && setOpen(true); }, [resultsComplete, index]); return ( {!error && data && {data?.output}} {error && ( )} {config.cache.show_text && data && !error && ( <> {!isSm && ( )} {isSm && ( )} )} ); } ); Result.displayName = "HyperglassQueryResult"; export default Result;