diff --git a/hyperglass/configuration/models/web.py b/hyperglass/configuration/models/web.py
index 0272690..269886d 100644
--- a/hyperglass/configuration/models/web.py
+++ b/hyperglass/configuration/models/web.py
@@ -139,7 +139,7 @@ class Text(HyperglassModel):
query_vrf: StrictStr = "Routing Table"
fqdn_tooltip: StrictStr = "Use {protocol}" # Formatted by Javascript
cache_prefix: StrictStr = "Results cached for "
- cache_icon: StrictStr = "Cached Response from {time}" # Formatted by Javascript
+ cache_icon: StrictStr = "Cached Response from {time} UTC" # Formatted by Javascript
complete_time: StrictStr = "Completed in {seconds}" # Formatted by Javascript
@validator("title_mode")
diff --git a/hyperglass/constants.py b/hyperglass/constants.py
index 74f56ad..e3e30ba 100644
--- a/hyperglass/constants.py
+++ b/hyperglass/constants.py
@@ -4,7 +4,7 @@
from datetime import datetime
__name__ = "hyperglass"
-__version__ = "1.0.0-beta.26"
+__version__ = "1.0.0-beta.27"
__author__ = "Matt Love"
__copyright__ = f"Copyright {datetime.now().year} Matthew Love"
__license__ = "BSD 3-Clause Clear License"
diff --git a/hyperglass/ui/components/Result.js b/hyperglass/ui/components/Result.js
index cd2aef1..4907e7f 100644
--- a/hyperglass/ui/components/Result.js
+++ b/hyperglass/ui/components/Result.js
@@ -1,16 +1,16 @@
import React, { useEffect, useState } from "react";
import {
- AccordionItem,
- AccordionHeader,
- AccordionPanel,
- Alert,
- Box,
- ButtonGroup,
- css,
- Flex,
- Tooltip,
- Text,
- useColorMode,
+ AccordionItem,
+ AccordionHeader,
+ AccordionPanel,
+ Alert,
+ Box,
+ ButtonGroup,
+ css,
+ Flex,
+ Tooltip,
+ Text,
+ useColorMode
} from "@chakra-ui/core";
import styled from "@emotion/styled";
import LightningBolt from "~/components/icons/LightningBolt";
@@ -28,230 +28,301 @@ import CacheTimeout from "~/components/CacheTimeout";
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 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";
- }
+ 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 statusMap = {
+ success: "success",
+ warning: "warning",
+ error: "warning",
+ danger: "error"
+};
const bg = { dark: "gray.800", light: "blackAlpha.100" };
const color = { dark: "white", light: "black" };
const selectionBg = { dark: "white", light: "black" };
const selectionColor = { dark: "black", light: "white" };
const Result = React.forwardRef(
- (
- {
- device,
- timeout,
- queryLocation,
- queryType,
- queryVrf,
- queryTarget,
- index,
- resultsComplete,
- setComplete,
- },
- ref
- ) => {
- const config = useConfig();
- const { isSm } = useMedia();
- const { colorMode } = useColorMode();
- const [{ 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,
- });
+ (
+ {
+ device,
+ timeout,
+ queryLocation,
+ queryType,
+ queryVrf,
+ queryTarget,
+ index,
+ resultsComplete,
+ setComplete
+ },
+ ref
+ ) => {
+ const config = useConfig();
+ const { isSm } = useMedia();
+ const { colorMode } = useColorMode();
+ const [{ 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 [isOpen, setOpen] = useState(false);
+ const [hasOverride, setOverride] = useState(false);
- const handleToggle = () => {
- setOpen(!isOpen);
- setOverride(true);
- };
- const cleanOutput =
- data &&
- data.output
- .split("\\n")
- .join("\n")
- .replace(/\n\n/g, "\n");
+ const handleToggle = () => {
+ setOpen(!isOpen);
+ setOverride(true);
+ };
+ const cleanOutput =
+ data &&
+ data.output
+ .split("\\n")
+ .join("\n")
+ .replace(/\n\n/g, "\n");
- const errorKw = (error && error.response?.data?.keywords) || [];
+ 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.dir(error);
-
- const errorLevel =
- (error?.response?.data?.level && statusMap[error.response?.data?.level]) ?? "error";
-
- const cacheLg = (
- <>
-
- {data?.cached && (
-
-
-
-
-
- )}
- >
- );
- const cacheSm = (
- <>
- {data?.cached && (
-
-
-
-
-
- )}
-
- >
- );
-
- const cacheData = isSm ? cacheSm : cacheLg;
-
- useEffect(() => {
- !loading && resultsComplete === null && setComplete(index);
- }, [loading, resultsComplete]);
-
- useEffect(() => {
- resultsComplete === index && !hasOverride && setOpen(true);
- }, [resultsComplete, index]);
- return (
-
-
-
-
-
-
-
-
-
-
-
-
-
- {data && !error && (
-
- {cleanOutput}
-
- )}
- {error && (
-
-
-
- )}
-
-
-
-
-
- {data && !error && config.cache.show_text && cacheData}
-
-
-
-
- );
+ 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.dir(error);
+
+ const errorLevel =
+ (error?.response?.data?.level &&
+ statusMap[error.response?.data?.level]) ??
+ "error";
+
+ const cacheLg = (
+ <>
+
+ {data?.cached && (
+
+
+
+
+
+ )}
+ >
+ );
+ const cacheSm = (
+ <>
+ {data?.cached && (
+
+
+
+
+
+ )}
+
+ >
+ );
+
+ const cacheData = isSm ? cacheSm : cacheLg;
+
+ useEffect(() => {
+ !loading && resultsComplete === null && setComplete(index);
+ }, [loading, resultsComplete]);
+
+ useEffect(() => {
+ resultsComplete === index && !hasOverride && setOpen(true);
+ }, [resultsComplete, index]);
+ useEffect(() => {
+ data && console.log(data);
+ });
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {data && !error && (
+
+ {cleanOutput}
+
+ )}
+ {error && (
+
+
+
+ )}
+
+
+
+
+
+ {data && !error && config.cache.show_text && isSm ? (
+ <>
+
+
+
+
+
+
+ >
+ ) : data && !error && config.cache.show_text ? (
+ <>
+
+
+
+
+
+
+ >
+ ) : null}
+
+
+
+
+ );
+ }
);
Result.displayName = "HyperglassQueryResult";
diff --git a/hyperglass/ui/components/ResultHeader.js b/hyperglass/ui/components/ResultHeader.js
index 764d0f5..9e0845c 100644
--- a/hyperglass/ui/components/ResultHeader.js
+++ b/hyperglass/ui/components/ResultHeader.js
@@ -1,55 +1,70 @@
import React from "react";
-import { AccordionIcon, Icon, Spinner, Stack, Text, Tooltip, useColorMode } from "@chakra-ui/core";
+import {
+ AccordionIcon,
+ Icon,
+ Spinner,
+ Stack,
+ Text,
+ Tooltip,
+ useColorMode
+} from "@chakra-ui/core";
import format from "string-format";
import useConfig from "~/components/HyperglassProvider";
format.extend(String.prototype, {});
const runtimeText = (runtime, text) => {
- let unit;
- if (runtime === 1) {
- unit = "seconds";
- } else {
- unit = "second";
- }
- const fmt = text.format({ seconds: runtime });
- return `${fmt} ${unit}`;
+ let unit;
+ if (runtime === 1) {
+ unit = "second";
+ } else {
+ unit = "seconds";
+ }
+ const fmt = text.format({ seconds: runtime });
+ return `${fmt} ${unit}`;
};
const statusColor = { dark: "primary.300", light: "primary.500" };
const warningColor = { dark: 300, light: 500 };
const defaultStatusColor = {
- dark: "success.300",
- light: "success.500",
+ dark: "success.300",
+ light: "success.500"
};
-export default React.forwardRef(({ title, loading, error, errorMsg, errorLevel, runtime }, ref) => {
+export default React.forwardRef(
+ ({ title, loading, error, errorMsg, errorLevel, runtime }, ref) => {
const { colorMode } = useColorMode();
const config = useConfig();
return (
-
- {loading ? (
-
- ) : error ? (
-
-
-
- ) : (
-
-
-
- )}
- {title}
-
-
+
+ {loading ? (
+
+ ) : error ? (
+
+
+
+ ) : (
+
+
+
+ )}
+ {title}
+
+
);
-});
+ }
+);
diff --git a/install.sh b/install.sh
index 6f93636..c3da15a 100755
--- a/install.sh
+++ b/install.sh
@@ -2,7 +2,7 @@
set -e
-HYPERGLASS_VERSION="1.0.0b26"
+HYPERGLASS_VERSION="1.0.0b27"
MIN_PYTHON_MAJOR="3"
MIN_PYTHON_MINOR="6"
diff --git a/pyproject.toml b/pyproject.toml
index 7fbfe7f..4079d49 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -4,7 +4,7 @@ build-backend = "poetry.masonry.api"
[tool.poetry]
name = "hyperglass"
-version = "1.0.0-beta.26"
+version = "1.0.0-beta.27"
description = "hyperglass is the modern network looking glass that tries to make the internet better."
authors = ["Matt Love "]
readme = "README.md"