mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
Refactor React components & update deps
This commit is contained in:
@@ -218,8 +218,6 @@ const Cell = ({ data, rawData, longestASN }) => {
|
||||
const BGPTable = ({ children: data, ...props }) => {
|
||||
const config = useConfig();
|
||||
const columns = makeColumns(config.parsed_data_fields);
|
||||
// const allASN = data.routes.map(r => r.as_path).flat();
|
||||
// const asLength = longestASNLength(allASN);
|
||||
|
||||
return (
|
||||
<Flex my={8} maxW={["100%", "100%", "100%", "100%"]} w="100%" {...props}>
|
||||
@@ -235,6 +233,4 @@ const BGPTable = ({ children: data, ...props }) => {
|
||||
);
|
||||
};
|
||||
|
||||
BGPTable.displayName = "BGPTable";
|
||||
|
||||
export default BGPTable;
|
||||
|
@@ -5,37 +5,35 @@ import { Text, useColorMode } from "@chakra-ui/core";
|
||||
const bg = { dark: "white", light: "black" };
|
||||
|
||||
const Renderer = ({ hours, minutes, seconds, completed, props }) => {
|
||||
if (completed) {
|
||||
return <Text fontSize="xs" />;
|
||||
} else {
|
||||
let time = [zeroPad(seconds)];
|
||||
minutes !== 0 && time.unshift(zeroPad(minutes));
|
||||
hours !== 0 && time.unshift(zeroPad(hours));
|
||||
return (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
{props.text}
|
||||
<Text as="span" fontSize="xs" color={bg[props.colorMode]}>
|
||||
{time.join(":")}
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
if (completed) {
|
||||
return <Text fontSize="xs" />;
|
||||
} else {
|
||||
let time = [zeroPad(seconds)];
|
||||
minutes !== 0 && time.unshift(zeroPad(minutes));
|
||||
hours !== 0 && time.unshift(zeroPad(hours));
|
||||
return (
|
||||
<Text fontSize="xs" color="gray.500">
|
||||
{props.text}
|
||||
<Text as="span" fontSize="xs" color={bg[props.colorMode]}>
|
||||
{time.join(":")}
|
||||
</Text>
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const CacheTimeout = ({ timeout, text }) => {
|
||||
const then = timeout * 1000;
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Countdown
|
||||
date={Date.now() + then}
|
||||
renderer={Renderer}
|
||||
daysInHours
|
||||
text={text}
|
||||
colorMode={colorMode}
|
||||
/>
|
||||
);
|
||||
const then = timeout * 1000;
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Countdown
|
||||
date={Date.now() + then}
|
||||
renderer={Renderer}
|
||||
daysInHours
|
||||
text={text}
|
||||
colorMode={colorMode}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
CacheTimeout.displayName = "CacheTimeout";
|
||||
|
||||
export default CacheTimeout;
|
||||
|
@@ -4,7 +4,7 @@ import { Flex, useColorMode } from "@chakra-ui/core";
|
||||
const bg = { light: "white", dark: "original.dark" };
|
||||
const color = { light: "original.dark", dark: "white" };
|
||||
|
||||
const CardBody = ({ onClick = () => false, children, ...props }) => {
|
||||
export const CardBody = ({ onClick = () => false, children, ...props }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Flex
|
||||
@@ -23,7 +23,3 @@ const CardBody = ({ onClick = () => false, children, ...props }) => {
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
CardBody.displayName = "CardBody";
|
||||
|
||||
export default CardBody;
|
||||
|
@@ -1,25 +1,19 @@
|
||||
import * as React from "react";
|
||||
import { Flex } from "@chakra-ui/core";
|
||||
|
||||
const CardFooter = ({ children, ...props }) => {
|
||||
return (
|
||||
<Flex
|
||||
p={4}
|
||||
roundedBottomLeft={4}
|
||||
roundedBottomRight={4}
|
||||
direction="column"
|
||||
borderTopWidth="1px"
|
||||
overflowX="hidden"
|
||||
overflowY="hidden"
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
CardFooter.displayName = "CardFooter";
|
||||
|
||||
export default CardFooter;
|
||||
export const CardFooter = ({ children, ...props }) => (
|
||||
<Flex
|
||||
p={4}
|
||||
roundedBottomLeft={4}
|
||||
roundedBottomRight={4}
|
||||
direction="column"
|
||||
borderTopWidth="1px"
|
||||
overflowX="hidden"
|
||||
overflowY="hidden"
|
||||
flexDirection="row"
|
||||
justifyContent="space-between"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Flex>
|
||||
);
|
||||
|
@@ -3,7 +3,7 @@ import { Flex, Text, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
const bg = { light: "blackAlpha.50", dark: "whiteAlpha.100" };
|
||||
|
||||
const CardHeader = ({ children, ...props }) => {
|
||||
export const CardHeader = ({ children, ...props }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
return (
|
||||
<Flex
|
||||
@@ -19,7 +19,3 @@ const CardHeader = ({ children, ...props }) => {
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
CardHeader.displayName = "CardHeader";
|
||||
|
||||
export default CardHeader;
|
||||
|
@@ -1,5 +1,3 @@
|
||||
import CardBody from "./CardBody";
|
||||
import CardFooter from "./CardFooter";
|
||||
import CardHeader from "./CardHeader";
|
||||
|
||||
export { CardBody, CardFooter, CardHeader };
|
||||
export { CardBody } from "./CardBody";
|
||||
export { CardFooter } from "./CardFooter";
|
||||
export { CardHeader } from "./CardHeader";
|
||||
|
@@ -203,5 +203,4 @@ const ChakraSelect = React.forwardRef(
|
||||
}
|
||||
);
|
||||
|
||||
ChakraSelect.displayName = "ChakraSelect";
|
||||
export default ChakraSelect;
|
||||
|
@@ -1,26 +1,25 @@
|
||||
import React from "react";
|
||||
import { Box, useColorMode, useTheme } from "@chakra-ui/core";
|
||||
import * as React from "react";
|
||||
import { Box, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
export default ({ children }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const theme = useTheme();
|
||||
const bg = { dark: theme.colors.gray[800], light: theme.colors.blackAlpha[100] };
|
||||
const color = { dark: theme.colors.white, light: theme.colors.black };
|
||||
return (
|
||||
<Box
|
||||
fontFamily="mono"
|
||||
mt={5}
|
||||
p={3}
|
||||
border="1px"
|
||||
borderColor="inherit"
|
||||
rounded="md"
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
fontSize="sm"
|
||||
whiteSpace="pre-wrap"
|
||||
as="pre"
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
const { colorMode } = useColorMode();
|
||||
const bg = { dark: "gray.800", light: "blackAlpha.100" };
|
||||
const color = { dark: "white", light: "black" };
|
||||
return (
|
||||
<Box
|
||||
fontFamily="mono"
|
||||
mt={5}
|
||||
p={3}
|
||||
border="1px"
|
||||
borderColor="inherit"
|
||||
rounded="md"
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
fontSize="sm"
|
||||
whiteSpace="pre-wrap"
|
||||
as="pre"
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
@@ -4,38 +4,46 @@ import { Text } from "@chakra-ui/core";
|
||||
import { components } from "react-select";
|
||||
import ChakraSelect from "~/components/ChakraSelect";
|
||||
|
||||
const CommunitySelect = ({ name, communities, onChange, register, unregister }) => {
|
||||
const communitySelections = communities.map((c) => {
|
||||
return { value: c.community, label: c.display_name, description: c.description };
|
||||
});
|
||||
const Option = ({ label, data, ...props }) => {
|
||||
return (
|
||||
<components.Option {...props}>
|
||||
<Text>{label}</Text>
|
||||
<Text fontSize="xs" as="span">
|
||||
{data.description}
|
||||
</Text>
|
||||
</components.Option>
|
||||
);
|
||||
const CommunitySelect = ({
|
||||
name,
|
||||
communities,
|
||||
onChange,
|
||||
register,
|
||||
unregister
|
||||
}) => {
|
||||
const communitySelections = communities.map(c => {
|
||||
return {
|
||||
value: c.community,
|
||||
label: c.display_name,
|
||||
description: c.description
|
||||
};
|
||||
useEffect(() => {
|
||||
register({ name });
|
||||
return () => unregister(name);
|
||||
}, [name, register, unregister]);
|
||||
});
|
||||
const Option = ({ label, data, ...props }) => {
|
||||
return (
|
||||
<ChakraSelect
|
||||
innerRef={register}
|
||||
size="lg"
|
||||
name={name}
|
||||
onChange={(e) => {
|
||||
onChange({ field: name, value: e.value || "" });
|
||||
}}
|
||||
options={communitySelections}
|
||||
components={{ Option }}
|
||||
/>
|
||||
<components.Option {...props}>
|
||||
<Text>{label}</Text>
|
||||
<Text fontSize="xs" as="span">
|
||||
{data.description}
|
||||
</Text>
|
||||
</components.Option>
|
||||
);
|
||||
};
|
||||
useEffect(() => {
|
||||
register({ name });
|
||||
return () => unregister(name);
|
||||
}, [name, register, unregister]);
|
||||
return (
|
||||
<ChakraSelect
|
||||
innerRef={register}
|
||||
size="lg"
|
||||
name={name}
|
||||
onChange={e => {
|
||||
onChange({ field: name, value: e.value || "" });
|
||||
}}
|
||||
options={communitySelections}
|
||||
components={{ Option }}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
CommunitySelect.displayName = "CommunitySelect";
|
||||
|
||||
export default CommunitySelect;
|
||||
|
@@ -1,21 +1,27 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Button, Icon, Tooltip, useClipboard } from "@chakra-ui/core";
|
||||
|
||||
export default ({ bg = "secondary", copyValue, ...props }) => {
|
||||
const { onCopy, hasCopied } = useClipboard(copyValue);
|
||||
return (
|
||||
<Tooltip hasArrow label="Copy Output" placement="top">
|
||||
<Button
|
||||
as="a"
|
||||
size="sm"
|
||||
variantColor={bg}
|
||||
zIndex="dropdown"
|
||||
onClick={onCopy}
|
||||
mx={1}
|
||||
{...props}
|
||||
>
|
||||
{hasCopied ? <Icon name="check" size="16px" /> : <Icon name="copy" size="16px" />}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
const CopyButton = ({ bg = "secondary", copyValue, ...props }) => {
|
||||
const { onCopy, hasCopied } = useClipboard(copyValue);
|
||||
return (
|
||||
<Tooltip hasArrow label="Copy Output" placement="top">
|
||||
<Button
|
||||
as="a"
|
||||
size="sm"
|
||||
variantColor={bg}
|
||||
zIndex="dropdown"
|
||||
onClick={onCopy}
|
||||
mx={1}
|
||||
{...props}
|
||||
>
|
||||
{hasCopied ? (
|
||||
<Icon name="check" size="16px" />
|
||||
) : (
|
||||
<Icon name="copy" size="16px" />
|
||||
)}
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
|
||||
export default CopyButton;
|
||||
|
@@ -1,94 +1,106 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
Stack,
|
||||
Tag,
|
||||
useDisclosure,
|
||||
useColorMode,
|
||||
useTheme,
|
||||
Button,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
Stack,
|
||||
Tag,
|
||||
useDisclosure,
|
||||
useColorMode,
|
||||
useTheme
|
||||
} from "@chakra-ui/core";
|
||||
import useConfig from "~/components/HyperglassProvider";
|
||||
import useMedia from "~/components/MediaProvider";
|
||||
import CodeBlock from "~/components/CodeBlock";
|
||||
|
||||
const prettyMediaSize = { sm: "SMALL", md: "MEDIUM", lg: "LARGE", xl: "X-LARGE" };
|
||||
|
||||
const Debugger = () => {
|
||||
const { isOpen: configOpen, onOpen: onConfigOpen, onClose: configClose } = useDisclosure();
|
||||
const { isOpen: themeOpen, onOpen: onThemeOpen, onClose: themeClose } = useDisclosure();
|
||||
const config = useConfig();
|
||||
const theme = useTheme();
|
||||
const bg = { light: "white", dark: "black" };
|
||||
const color = { light: "black", dark: "white" };
|
||||
const { colorMode } = useColorMode();
|
||||
const { mediaSize } = useMedia();
|
||||
const borderColor = { light: "gray.100", dark: "gray.600" };
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
borderWidth="1px"
|
||||
borderColor={borderColor[colorMode]}
|
||||
py={4}
|
||||
px={4}
|
||||
isInline
|
||||
position="relative"
|
||||
left={0}
|
||||
right={0}
|
||||
bottom={0}
|
||||
justifyContent="center"
|
||||
zIndex={1000}
|
||||
maxW="100%"
|
||||
>
|
||||
<Tag variantColor="gray">{colorMode.toUpperCase()}</Tag>
|
||||
<Tag variantColor="teal">{prettyMediaSize[mediaSize]}</Tag>
|
||||
<Button size="sm" variantColor="cyan" onClick={onConfigOpen}>
|
||||
View Config
|
||||
</Button>
|
||||
<Button size="sm" variantColor="purple" onClick={onThemeOpen}>
|
||||
View Theme
|
||||
</Button>
|
||||
</Stack>
|
||||
<Modal isOpen={configOpen} onClose={configClose} size="full">
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
maxW="90%"
|
||||
>
|
||||
<ModalHeader>Loaded Configuration</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<CodeBlock>{JSON.stringify(config, null, 4)}</CodeBlock>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<Modal isOpen={themeOpen} onClose={themeClose} size="full">
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
maxW="90%"
|
||||
>
|
||||
<ModalHeader>Loaded Theme</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<CodeBlock>{JSON.stringify(theme, null, 4)}</CodeBlock>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
const prettyMediaSize = {
|
||||
sm: "SMALL",
|
||||
md: "MEDIUM",
|
||||
lg: "LARGE",
|
||||
xl: "X-LARGE"
|
||||
};
|
||||
|
||||
const Debugger = () => {
|
||||
const {
|
||||
isOpen: configOpen,
|
||||
onOpen: onConfigOpen,
|
||||
onClose: configClose
|
||||
} = useDisclosure();
|
||||
const {
|
||||
isOpen: themeOpen,
|
||||
onOpen: onThemeOpen,
|
||||
onClose: themeClose
|
||||
} = useDisclosure();
|
||||
const config = useConfig();
|
||||
const theme = useTheme();
|
||||
const bg = { light: "white", dark: "black" };
|
||||
const color = { light: "black", dark: "white" };
|
||||
const { colorMode } = useColorMode();
|
||||
const { mediaSize } = useMedia();
|
||||
const borderColor = { light: "gray.100", dark: "gray.600" };
|
||||
return (
|
||||
<>
|
||||
<Stack
|
||||
borderWidth="1px"
|
||||
borderColor={borderColor[colorMode]}
|
||||
py={4}
|
||||
px={4}
|
||||
isInline
|
||||
position="relative"
|
||||
left={0}
|
||||
right={0}
|
||||
bottom={0}
|
||||
justifyContent="center"
|
||||
zIndex={1000}
|
||||
maxW="100%"
|
||||
>
|
||||
<Tag variantColor="gray">{colorMode.toUpperCase()}</Tag>
|
||||
<Tag variantColor="teal">{prettyMediaSize[mediaSize]}</Tag>
|
||||
<Button size="sm" variantColor="cyan" onClick={onConfigOpen}>
|
||||
View Config
|
||||
</Button>
|
||||
<Button size="sm" variantColor="purple" onClick={onThemeOpen}>
|
||||
View Theme
|
||||
</Button>
|
||||
</Stack>
|
||||
<Modal isOpen={configOpen} onClose={configClose} size="full">
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
maxW="90%"
|
||||
>
|
||||
<ModalHeader>Loaded Configuration</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<CodeBlock>{JSON.stringify(config, null, 4)}</CodeBlock>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
<Modal isOpen={themeOpen} onClose={themeClose} size="full">
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
maxW="90%"
|
||||
>
|
||||
<ModalHeader>Loaded Theme</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<CodeBlock>{JSON.stringify(theme, null, 4)}</CodeBlock>
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Debugger.displayName = "Debugger";
|
||||
export default Debugger;
|
||||
|
@@ -1,33 +1,25 @@
|
||||
import React, { useState } from "react";
|
||||
import { Flex, useColorMode, useTheme } from "@chakra-ui/core";
|
||||
import * as React from "react";
|
||||
import { useState } from "react";
|
||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
||||
import { FiCode } from "react-icons/fi";
|
||||
import { GoLinkExternal } from "react-icons/go";
|
||||
import format from "string-format";
|
||||
import useConfig from "~/components/HyperglassProvider";
|
||||
import FooterButton from "~/components/FooterButton";
|
||||
import FooterContent from "~/components/FooterContent";
|
||||
import FooterButton from "./FooterButton";
|
||||
import FooterContent from "./FooterContent";
|
||||
|
||||
format.extend(String.prototype, {});
|
||||
|
||||
const footerBg = { light: "blackAlpha.50", dark: "whiteAlpha.100" };
|
||||
const footerColor = { light: "black", dark: "white" };
|
||||
const contentBorder = { light: "blackAlpha.100", dark: "whiteAlpha.200" };
|
||||
|
||||
const Footer = () => {
|
||||
const theme = useTheme();
|
||||
const config = useConfig();
|
||||
const { colorMode } = useColorMode();
|
||||
const footerBg = {
|
||||
light: theme.colors.blackAlpha[50],
|
||||
dark: theme.colors.whiteAlpha[100]
|
||||
};
|
||||
const footerColor = { light: theme.colors.black, dark: theme.colors.white };
|
||||
const contentBorder = {
|
||||
light: theme.colors.blackAlpha[100],
|
||||
dark: theme.colors.whiteAlpha[200]
|
||||
};
|
||||
const [helpVisible, showHelp] = useState(false);
|
||||
const [termsVisible, showTerms] = useState(false);
|
||||
const [creditVisible, showCredit] = useState(false);
|
||||
const extUrl = config.web.external_link.url.includes("{primary_asn}")
|
||||
? config.web.external_link.url.format({ primary_asn: config.primary_asn })
|
||||
: config.web.external_link.url || "/";
|
||||
const handleCollapse = i => {
|
||||
if (i === "help") {
|
||||
showTerms(false);
|
||||
@@ -43,6 +35,9 @@ const Footer = () => {
|
||||
showTerms(!termsVisible);
|
||||
}
|
||||
};
|
||||
const extUrl = config.web.external_link.url.includes("{primary_asn}")
|
||||
? config.web.external_link.url.format({ primary_asn: config.primary_asn })
|
||||
: config.web.external_link.url || "/";
|
||||
return (
|
||||
<>
|
||||
{config.web.help_menu.enable && (
|
||||
@@ -141,5 +136,4 @@ const Footer = () => {
|
||||
);
|
||||
};
|
||||
|
||||
Footer.displayName = "Footer";
|
||||
export default Footer;
|
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Button, Flex } from "@chakra-ui/core";
|
||||
import { motion } from "framer-motion";
|
||||
|
||||
@@ -28,5 +28,4 @@ const FooterButton = React.forwardRef(
|
||||
}
|
||||
);
|
||||
|
||||
FooterButton.displayName = "FooterButton";
|
||||
export default FooterButton;
|
30
hyperglass/ui/components/Footer/FooterContent.js
Normal file
30
hyperglass/ui/components/Footer/FooterContent.js
Normal file
@@ -0,0 +1,30 @@
|
||||
import * as React from "react";
|
||||
import { forwardRef } from "react";
|
||||
import { Box, Collapse } from "@chakra-ui/core";
|
||||
import MarkDown from "~/components/MarkDown";
|
||||
|
||||
const FooterContent = forwardRef(
|
||||
({ isOpen = false, content, side = "left", title, ...props }, ref) => {
|
||||
return (
|
||||
<Collapse
|
||||
px={6}
|
||||
py={4}
|
||||
w="auto"
|
||||
ref={ref}
|
||||
borderBottom="1px"
|
||||
display="flex"
|
||||
maxWidth="100%"
|
||||
isOpen={isOpen}
|
||||
flexBasis="auto"
|
||||
justifyContent={side === "left" ? "flex-start" : "flex-end"}
|
||||
{...props}
|
||||
>
|
||||
<Box textAlign={side}>
|
||||
<MarkDown content={content} />
|
||||
</Box>
|
||||
</Collapse>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default FooterContent;
|
2
hyperglass/ui/components/Footer/index.js
Normal file
2
hyperglass/ui/components/Footer/index.js
Normal file
@@ -0,0 +1,2 @@
|
||||
import Footer from "./Footer";
|
||||
export default Footer;
|
@@ -1,27 +0,0 @@
|
||||
import React from "react";
|
||||
import { Box, Collapse } from "@chakra-ui/core";
|
||||
import MarkDown from "~/components/MarkDown";
|
||||
|
||||
export default React.forwardRef(
|
||||
({ isOpen = false, content, side = "left", title, ...props }, ref) => {
|
||||
return (
|
||||
<Collapse
|
||||
px={6}
|
||||
py={4}
|
||||
w="auto"
|
||||
ref={ref}
|
||||
borderBottom="1px"
|
||||
display="flex"
|
||||
maxWidth="100%"
|
||||
isOpen={isOpen}
|
||||
flexBasis="auto"
|
||||
justifyContent={side === "left" ? "flex-start" : "flex-end"}
|
||||
{...props}
|
||||
>
|
||||
<Box textAlign={side}>
|
||||
<MarkDown content={content} />
|
||||
</Box>
|
||||
</Collapse>
|
||||
);
|
||||
}
|
||||
);
|
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import {
|
||||
Flex,
|
||||
FormControl,
|
||||
@@ -7,7 +7,9 @@ import {
|
||||
useColorMode
|
||||
} from "@chakra-ui/core";
|
||||
|
||||
export default ({
|
||||
const labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" };
|
||||
|
||||
const FormField = ({
|
||||
label,
|
||||
name,
|
||||
error,
|
||||
@@ -21,7 +23,7 @@ export default ({
|
||||
...props
|
||||
}) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" };
|
||||
|
||||
return (
|
||||
<FormControl
|
||||
as={Flex}
|
||||
@@ -59,3 +61,5 @@ export default ({
|
||||
</FormControl>
|
||||
);
|
||||
};
|
||||
|
||||
export default FormField;
|
||||
|
@@ -1,15 +1,15 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Button,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useColorMode,
|
||||
useDisclosure,
|
||||
Button,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalFooter,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useColorMode,
|
||||
useDisclosure
|
||||
} from "@chakra-ui/core";
|
||||
import MarkDown from "~/components/MarkDown";
|
||||
import { motion } from "framer-motion";
|
||||
@@ -21,53 +21,51 @@ const AnimatedModalContent = motion.custom(ModalContent);
|
||||
const AnimatedModalOverlay = motion.custom(ModalOverlay);
|
||||
|
||||
const Greeting = ({ greetingConfig, content, onClickThrough }) => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure(true);
|
||||
const { colorMode } = useColorMode();
|
||||
const { isOpen, onOpen, onClose } = useDisclosure(true);
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
const handleClick = () => {
|
||||
onClickThrough(true);
|
||||
onClose();
|
||||
};
|
||||
const handleClick = () => {
|
||||
onClickThrough(true);
|
||||
onClose();
|
||||
};
|
||||
|
||||
return (
|
||||
<Modal
|
||||
onClose={handleClick}
|
||||
isOpen={isOpen}
|
||||
size="full"
|
||||
isCentered
|
||||
closeOnOverlayClick={!greetingConfig.required}
|
||||
closeOnEsc={!greetingConfig.required}
|
||||
>
|
||||
<AnimatedModalOverlay
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3, delay: 0.7 }}
|
||||
/>
|
||||
<AnimatedModalContent
|
||||
initial={{ scale: 0.5, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{ duration: 0.3, delay: 0.7 }}
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
maxW={["95%", "75%", "75%", "75%"]}
|
||||
>
|
||||
<ModalHeader>{greetingConfig.title}</ModalHeader>
|
||||
{!greetingConfig.required && <ModalCloseButton />}
|
||||
<ModalBody>
|
||||
<MarkDown content={content} />
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variantColor="primary" onClick={handleClick}>
|
||||
{greetingConfig.button}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</AnimatedModalContent>
|
||||
</Modal>
|
||||
);
|
||||
return (
|
||||
<Modal
|
||||
onClose={handleClick}
|
||||
isOpen={isOpen}
|
||||
size="full"
|
||||
isCentered
|
||||
closeOnOverlayClick={!greetingConfig.required}
|
||||
closeOnEsc={!greetingConfig.required}
|
||||
>
|
||||
<AnimatedModalOverlay
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3, delay: 0.7 }}
|
||||
/>
|
||||
<AnimatedModalContent
|
||||
initial={{ scale: 0.5, opacity: 0 }}
|
||||
animate={{ scale: 1, opacity: 1 }}
|
||||
transition={{ duration: 0.3, delay: 0.7 }}
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
maxW={["95%", "75%", "75%", "75%"]}
|
||||
>
|
||||
<ModalHeader>{greetingConfig.title}</ModalHeader>
|
||||
{!greetingConfig.required && <ModalCloseButton />}
|
||||
<ModalBody>
|
||||
<MarkDown content={content} />
|
||||
</ModalBody>
|
||||
<ModalFooter>
|
||||
<Button variantColor="primary" onClick={handleClick}>
|
||||
{greetingConfig.button}
|
||||
</Button>
|
||||
</ModalFooter>
|
||||
</AnimatedModalContent>
|
||||
</Modal>
|
||||
);
|
||||
};
|
||||
|
||||
Greeting.displayName = "Greeting";
|
||||
|
||||
export default Greeting;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import ResetButton from "~/components/ResetButton";
|
||||
@@ -33,12 +33,7 @@ const titleVariants = {
|
||||
}
|
||||
};
|
||||
|
||||
const icon = { light: "moon", dark: "sun" };
|
||||
const bg = { light: "white", dark: "black" };
|
||||
const colorSwitch = {
|
||||
dark: "Switch to light mode",
|
||||
light: "Switch to dark mode"
|
||||
};
|
||||
const headerTransition = {
|
||||
type: "spring",
|
||||
ease: "anticipate",
|
||||
@@ -107,7 +102,6 @@ const Header = ({ layoutRef, ...props }) => {
|
||||
}
|
||||
variants={titleVariants[mediaSize]}
|
||||
justifyContent={titleJustify[isSubmitting]}
|
||||
mb={[null, isSubmitting ? "auto" : null]}
|
||||
mt={[null, isSubmitting ? null : "auto"]}
|
||||
maxW={widthMap[web.text.title_mode]}
|
||||
flex="1 0 0"
|
||||
@@ -168,6 +162,4 @@ const Header = ({ layoutRef, ...props }) => {
|
||||
);
|
||||
};
|
||||
|
||||
Header.displayName = "Header";
|
||||
|
||||
export default Header;
|
||||
|
@@ -1,63 +1,73 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import {
|
||||
IconButton,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useDisclosure,
|
||||
useColorMode,
|
||||
useTheme
|
||||
IconButton,
|
||||
Modal,
|
||||
ModalOverlay,
|
||||
ModalContent,
|
||||
ModalHeader,
|
||||
ModalBody,
|
||||
ModalCloseButton,
|
||||
useDisclosure,
|
||||
useColorMode,
|
||||
useTheme
|
||||
} from "@chakra-ui/core";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import MarkDown from "~/components/MarkDown";
|
||||
|
||||
const AnimatedIcon = motion.custom(IconButton);
|
||||
|
||||
export default ({ item, name }) => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const theme = useTheme();
|
||||
const { colorMode } = useColorMode();
|
||||
const bg = { light: theme.colors.white, dark: theme.colors.dark };
|
||||
const color = { light: theme.colors.black, dark: theme.colors.white };
|
||||
const iconColor = { light: theme.colors.primary[500], dark: theme.colors.primary[300] };
|
||||
return (
|
||||
<>
|
||||
<AnimatePresence>
|
||||
<AnimatedIcon
|
||||
initial={{ opacity: 0, scale: 0.3, color: theme.colors.gray[500] }}
|
||||
animate={{ opacity: 1, scale: 1, color: iconColor[colorMode] }}
|
||||
transition={{ duration: 0.2 }}
|
||||
exit={{ opacity: 0, scale: 0.3 }}
|
||||
variantColor="primary"
|
||||
aria-label={`${name}_help`}
|
||||
icon="info-outline"
|
||||
variant="link"
|
||||
size="sm"
|
||||
h="unset"
|
||||
w={3}
|
||||
minW={3}
|
||||
maxW={3}
|
||||
h={3}
|
||||
minH={3}
|
||||
maxH={3}
|
||||
ml={1}
|
||||
mb={1}
|
||||
onClick={onOpen}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent bg={bg[colorMode]} color={color[colorMode]} py={4} borderRadius="md">
|
||||
<ModalHeader>{item.params.title}</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<MarkDown content={item.content} />
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
const HelpModal = ({ item, name }) => {
|
||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||
const { colors } = useTheme();
|
||||
const { colorMode } = useColorMode();
|
||||
const bg = { light: "whiteFaded.50", dark: "blackFaded.800" };
|
||||
const color = { light: "black", dark: "white" };
|
||||
const iconColor = {
|
||||
light: colors.primary[500],
|
||||
dark: colors.primary[300]
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<AnimatePresence>
|
||||
<AnimatedIcon
|
||||
initial={{ opacity: 0, scale: 0.3, color: colors.gray[500] }}
|
||||
animate={{ opacity: 1, scale: 1, color: iconColor[colorMode] }}
|
||||
transition={{ duration: 0.2 }}
|
||||
exit={{ opacity: 0, scale: 0.3 }}
|
||||
variantColor="primary"
|
||||
aria-label={`${name}_help`}
|
||||
icon="info-outline"
|
||||
variant="link"
|
||||
size="sm"
|
||||
h="unset"
|
||||
w={3}
|
||||
minW={3}
|
||||
maxW={3}
|
||||
h={3}
|
||||
minH={3}
|
||||
maxH={3}
|
||||
ml={1}
|
||||
mb={1}
|
||||
onClick={onOpen}
|
||||
/>
|
||||
</AnimatePresence>
|
||||
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
||||
<ModalOverlay />
|
||||
<ModalContent
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
py={4}
|
||||
borderRadius="md"
|
||||
>
|
||||
<ModalHeader>{item.params.title}</ModalHeader>
|
||||
<ModalCloseButton />
|
||||
<ModalBody>
|
||||
<MarkDown content={item.content} />
|
||||
</ModalBody>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default HelpModal;
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import * as React from "react";
|
||||
import { useState, useEffect } from "react";
|
||||
import { forwardRef, useState, useEffect } from "react";
|
||||
import { Box, Flex } from "@chakra-ui/core";
|
||||
import { useForm } from "react-hook-form";
|
||||
import lodash from "lodash";
|
||||
@@ -53,7 +53,7 @@ const FormRow = ({ children, ...props }) => (
|
||||
</Flex>
|
||||
);
|
||||
|
||||
const HyperglassForm = React.forwardRef(
|
||||
const HyperglassForm = forwardRef(
|
||||
(
|
||||
{
|
||||
isSubmitting,
|
||||
@@ -164,6 +164,8 @@ const HyperglassForm = React.forwardRef(
|
||||
Object.keys(errors).length >= 1 && console.error(errors);
|
||||
return (
|
||||
<Box
|
||||
as="form"
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
maxW={["100%", "100%", "75%", "75%"]}
|
||||
w="100%"
|
||||
p={0}
|
||||
@@ -173,111 +175,108 @@ const HyperglassForm = React.forwardRef(
|
||||
ref={ref}
|
||||
{...props}
|
||||
>
|
||||
<form onSubmit={handleSubmit(onSubmit)}>
|
||||
<FormRow>
|
||||
<FormField
|
||||
<FormRow>
|
||||
<FormField
|
||||
label={config.web.text.query_location}
|
||||
name="query_location"
|
||||
error={errors.query_location}
|
||||
>
|
||||
<QueryLocation
|
||||
onChange={handleChange}
|
||||
locations={config.networks}
|
||||
label={config.web.text.query_location}
|
||||
name="query_location"
|
||||
error={errors.query_location}
|
||||
>
|
||||
<QueryLocation
|
||||
onChange={handleChange}
|
||||
locations={config.networks}
|
||||
label={config.web.text.query_location}
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
/>
|
||||
</FormField>
|
||||
<FormField
|
||||
label={config.web.text.query_type}
|
||||
name="query_type"
|
||||
error={errors.query_type}
|
||||
labelAddOn={
|
||||
vrfContent && <HelpModal item={vrfContent} name="query_type" />
|
||||
}
|
||||
>
|
||||
<QueryType
|
||||
onChange={handleChange}
|
||||
queryTypes={config.queries.list}
|
||||
label={config.web.text.query_type}
|
||||
name="query_type"
|
||||
error={errors.query_type}
|
||||
labelAddOn={
|
||||
vrfContent && <HelpModal item={vrfContent} name="query_type" />
|
||||
}
|
||||
/>
|
||||
</FormField>
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
{availVrfs.length > 1 && (
|
||||
<FormField
|
||||
label={config.web.text.query_vrf}
|
||||
name="query_vrf"
|
||||
error={errors.query_vrf}
|
||||
>
|
||||
<QueryType
|
||||
<QueryVrf
|
||||
label={config.web.text.query_vrf}
|
||||
vrfs={availVrfs}
|
||||
onChange={handleChange}
|
||||
queryTypes={config.queries.list}
|
||||
label={config.web.text.query_type}
|
||||
/>
|
||||
</FormField>
|
||||
</FormRow>
|
||||
<FormRow>
|
||||
{availVrfs.length > 1 && (
|
||||
<FormField
|
||||
label={config.web.text.query_vrf}
|
||||
name="query_vrf"
|
||||
error={errors.query_vrf}
|
||||
>
|
||||
<QueryVrf
|
||||
label={config.web.text.query_vrf}
|
||||
vrfs={availVrfs}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</FormField>
|
||||
)}
|
||||
<FormField
|
||||
label={config.web.text.query_target}
|
||||
name="query_target"
|
||||
error={errors.query_target}
|
||||
fieldAddOn={
|
||||
queryLocation.length !== 0 &&
|
||||
validFqdnQueryType && (
|
||||
<ResolvedTarget
|
||||
queryTarget={queryTarget}
|
||||
fqdnTarget={validFqdnQueryType}
|
||||
setTarget={handleChange}
|
||||
families={families}
|
||||
availVrfs={availVrfs}
|
||||
/>
|
||||
)
|
||||
}
|
||||
>
|
||||
{queryType === "bgp_community" &&
|
||||
config.queries.bgp_community.mode === "select" ? (
|
||||
<CommunitySelect
|
||||
label={config.queries.bgp_community.display_name}
|
||||
name="query_target"
|
||||
register={register}
|
||||
unregister={unregister}
|
||||
onChange={handleChange}
|
||||
communities={config.queries.bgp_community.communities}
|
||||
/>
|
||||
) : (
|
||||
<QueryTarget
|
||||
name="query_target"
|
||||
placeholder={config.web.text.query_target}
|
||||
register={register}
|
||||
unregister={unregister}
|
||||
resolveTarget={["ping", "traceroute", "bgp_route"].includes(
|
||||
queryType
|
||||
)}
|
||||
value={queryTarget}
|
||||
setFqdn={setFqdnTarget}
|
||||
)}
|
||||
<FormField
|
||||
label={config.web.text.query_target}
|
||||
name="query_target"
|
||||
error={errors.query_target}
|
||||
fieldAddOn={
|
||||
queryLocation.length !== 0 &&
|
||||
validFqdnQueryType && (
|
||||
<ResolvedTarget
|
||||
queryTarget={queryTarget}
|
||||
fqdnTarget={validFqdnQueryType}
|
||||
setTarget={handleChange}
|
||||
displayValue={displayTarget}
|
||||
setDisplayValue={setDisplayTarget}
|
||||
families={families}
|
||||
availVrfs={availVrfs}
|
||||
/>
|
||||
)}
|
||||
</FormField>
|
||||
</FormRow>
|
||||
<FormRow mt={0} justifyContent="flex-end">
|
||||
<Flex
|
||||
w="100%"
|
||||
maxW="100%"
|
||||
ml="auto"
|
||||
my={2}
|
||||
mr={[0, 0, 2, 2]}
|
||||
flexDirection="column"
|
||||
flex="0 0 0"
|
||||
>
|
||||
<SubmitButton isLoading={isSubmitting} />
|
||||
</Flex>
|
||||
</FormRow>
|
||||
</form>
|
||||
)
|
||||
}
|
||||
>
|
||||
{queryType === "bgp_community" &&
|
||||
config.queries.bgp_community.mode === "select" ? (
|
||||
<CommunitySelect
|
||||
label={config.queries.bgp_community.display_name}
|
||||
name="query_target"
|
||||
register={register}
|
||||
unregister={unregister}
|
||||
onChange={handleChange}
|
||||
communities={config.queries.bgp_community.communities}
|
||||
/>
|
||||
) : (
|
||||
<QueryTarget
|
||||
name="query_target"
|
||||
placeholder={config.web.text.query_target}
|
||||
register={register}
|
||||
unregister={unregister}
|
||||
resolveTarget={["ping", "traceroute", "bgp_route"].includes(
|
||||
queryType
|
||||
)}
|
||||
value={queryTarget}
|
||||
setFqdn={setFqdnTarget}
|
||||
setTarget={handleChange}
|
||||
displayValue={displayTarget}
|
||||
setDisplayValue={setDisplayTarget}
|
||||
/>
|
||||
)}
|
||||
</FormField>
|
||||
</FormRow>
|
||||
<FormRow mt={0} justifyContent="flex-end">
|
||||
<Flex
|
||||
w="100%"
|
||||
maxW="100%"
|
||||
ml="auto"
|
||||
my={2}
|
||||
mr={[0, 0, 2, 2]}
|
||||
flexDirection="column"
|
||||
flex="0 0 0"
|
||||
>
|
||||
<SubmitButton isLoading={isSubmitting} />
|
||||
</Flex>
|
||||
</FormRow>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
HyperglassForm.displayName = "HyperglassForm";
|
||||
export default HyperglassForm;
|
||||
|
@@ -22,16 +22,16 @@ export const HyperglassProvider = ({ config, children }) => {
|
||||
const userTheme = value && makeTheme(value.web.theme);
|
||||
const theme = value ? userTheme : defaultTheme;
|
||||
return (
|
||||
<HyperglassContext.Provider value={value}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ColorModeProvider value={config.web.theme.default_color_mode ?? null}>
|
||||
<CSSReset />
|
||||
<MediaProvider theme={theme}>
|
||||
<ThemeProvider theme={theme}>
|
||||
<ColorModeProvider value={config.web.theme.default_color_mode ?? null}>
|
||||
<CSSReset />
|
||||
<MediaProvider theme={theme}>
|
||||
<HyperglassContext.Provider value={value}>
|
||||
<StateProvider>{children}</StateProvider>
|
||||
</MediaProvider>
|
||||
</ColorModeProvider>
|
||||
</ThemeProvider>
|
||||
</HyperglassContext.Provider>
|
||||
</HyperglassContext.Provider>
|
||||
</MediaProvider>
|
||||
</ColorModeProvider>
|
||||
</ThemeProvider>
|
||||
);
|
||||
};
|
||||
|
||||
|
@@ -1,62 +1,62 @@
|
||||
import React from "react";
|
||||
import { Flex, useColorMode, useTheme } from "@chakra-ui/core";
|
||||
import * as React from "react";
|
||||
import { forwardRef } from "react";
|
||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
export default React.forwardRef(
|
||||
({ value, label, labelColor, valueBg, valueColor, ...props }, ref) => {
|
||||
const theme = useTheme();
|
||||
const { colorMode } = useColorMode();
|
||||
const _labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" };
|
||||
const _valueBg = { light: theme.colors.primary[600], dark: theme.colors.primary[600] };
|
||||
const _valueColor = { light: "white", dark: "white" };
|
||||
return (
|
||||
<Flex
|
||||
ref={ref}
|
||||
flexWrap="nowrap"
|
||||
alignItems="center"
|
||||
justifyContent="flex-start"
|
||||
mx={[1, 2, 2, 2]}
|
||||
my={2}
|
||||
{...props}
|
||||
>
|
||||
<Flex
|
||||
display="inline-flex"
|
||||
justifyContent="center"
|
||||
lineHeight="1.5"
|
||||
px={[1, 3, 3, 3]}
|
||||
whiteSpace="nowrap"
|
||||
mb={2}
|
||||
mr={0}
|
||||
bg={valueBg || _valueBg[colorMode]}
|
||||
color={valueColor || _valueColor[colorMode]}
|
||||
borderBottomLeftRadius={4}
|
||||
borderTopLeftRadius={4}
|
||||
borderBottomRightRadius={0}
|
||||
borderTopRightRadius={0}
|
||||
fontWeight="bold"
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
>
|
||||
{value}
|
||||
</Flex>
|
||||
<Flex
|
||||
display="inline-flex"
|
||||
justifyContent="center"
|
||||
lineHeight="1.5"
|
||||
px={3}
|
||||
whiteSpace="nowrap"
|
||||
mb={2}
|
||||
ml={0}
|
||||
mr={0}
|
||||
boxShadow={`inset 0px 0px 0px 1px ${valueBg || _valueBg[colorMode]}`}
|
||||
color={labelColor || _labelColor[colorMode]}
|
||||
borderBottomRightRadius={4}
|
||||
borderTopRightRadius={4}
|
||||
borderBottomLeftRadius={0}
|
||||
borderTopLeftRadius={0}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
>
|
||||
{label}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
const Label = forwardRef(
|
||||
({ value, label, labelColor, valueBg, valueColor, ...props }, ref) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const _labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" };
|
||||
return (
|
||||
<Flex
|
||||
ref={ref}
|
||||
flexWrap="nowrap"
|
||||
alignItems="center"
|
||||
justifyContent="flex-start"
|
||||
mx={[1, 2, 2, 2]}
|
||||
my={2}
|
||||
{...props}
|
||||
>
|
||||
<Flex
|
||||
display="inline-flex"
|
||||
justifyContent="center"
|
||||
lineHeight="1.5"
|
||||
px={[1, 3, 3, 3]}
|
||||
whiteSpace="nowrap"
|
||||
mb={2}
|
||||
mr={0}
|
||||
bg={valueBg || "primary.600"}
|
||||
color={valueColor || "white"}
|
||||
borderBottomLeftRadius={4}
|
||||
borderTopLeftRadius={4}
|
||||
borderBottomRightRadius={0}
|
||||
borderTopRightRadius={0}
|
||||
fontWeight="bold"
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
>
|
||||
{value}
|
||||
</Flex>
|
||||
<Flex
|
||||
display="inline-flex"
|
||||
justifyContent="center"
|
||||
lineHeight="1.5"
|
||||
px={3}
|
||||
whiteSpace="nowrap"
|
||||
mb={2}
|
||||
ml={0}
|
||||
mr={0}
|
||||
boxShadow={`inset 0px 0px 0px 1px ${valueBg || "primary.600"}`}
|
||||
color={labelColor || _labelColor[colorMode]}
|
||||
borderBottomRightRadius={4}
|
||||
borderTopRightRadius={4}
|
||||
borderBottomLeftRadius={0}
|
||||
borderTopLeftRadius={0}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
>
|
||||
{label}
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default Label;
|
||||
|
@@ -1,37 +1,36 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Flex, Spinner, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
const Loading = () => {
|
||||
const { colorMode } = useColorMode();
|
||||
const bg = { light: "white", dark: "black" };
|
||||
const color = { light: "black", dark: "white" };
|
||||
return (
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
minHeight="100vh"
|
||||
w="100%"
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
>
|
||||
<Flex
|
||||
as="main"
|
||||
w="100%"
|
||||
flexGrow={1}
|
||||
flexShrink={1}
|
||||
flexBasis="auto"
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
textAlign="center"
|
||||
flexDirection="column"
|
||||
px={2}
|
||||
py={0}
|
||||
mt={["50%", "50%", "50%", "25%"]}
|
||||
>
|
||||
<Spinner color="primary.500" w="6rem" h="6rem" />
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
const { colorMode } = useColorMode();
|
||||
const bg = { light: "white", dark: "black" };
|
||||
const color = { light: "black", dark: "white" };
|
||||
return (
|
||||
<Flex
|
||||
flexDirection="column"
|
||||
minHeight="100vh"
|
||||
w="100%"
|
||||
bg={bg[colorMode]}
|
||||
color={color[colorMode]}
|
||||
>
|
||||
<Flex
|
||||
as="main"
|
||||
w="100%"
|
||||
flexGrow={1}
|
||||
flexShrink={1}
|
||||
flexBasis="auto"
|
||||
alignItems="center"
|
||||
justifyContent="start"
|
||||
textAlign="center"
|
||||
flexDirection="column"
|
||||
px={2}
|
||||
py={0}
|
||||
mt={["50%", "50%", "50%", "25%"]}
|
||||
>
|
||||
<Spinner color="primary.500" w="6rem" h="6rem" />
|
||||
</Flex>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
Loading.displayName = "Loading";
|
||||
export default Loading;
|
||||
|
@@ -1,75 +0,0 @@
|
||||
import React from "react";
|
||||
import dynamic from "next/dynamic";
|
||||
import {
|
||||
Checkbox as ChakraCheckbox,
|
||||
Divider,
|
||||
Code,
|
||||
Heading as ChakraHeading,
|
||||
Link as ChakraLink,
|
||||
List as ChakraList,
|
||||
ListItem as ChakraListItem,
|
||||
Spinner,
|
||||
Text as ChakraText
|
||||
} from "@chakra-ui/core";
|
||||
import CustomCodeBlock from "~/components/CodeBlock";
|
||||
import { TableCell, TableHeader, Table } from "~/components/Table";
|
||||
|
||||
// Dynaimc Imports
|
||||
const ReactMarkdown = dynamic(() => import("react-markdown"), { loading: Spinner });
|
||||
|
||||
const Checkbox = ({ checked, children }) => (
|
||||
<ChakraCheckbox isChecked={checked}>{children}</ChakraCheckbox>
|
||||
);
|
||||
|
||||
const List = ({ ordered, children }) => (
|
||||
<ChakraList as={ordered ? "ol" : "ul"}>{children}</ChakraList>
|
||||
);
|
||||
|
||||
const ListItem = ({ checked, children }) =>
|
||||
checked ? (
|
||||
<Checkbox checked={checked}>{children}</Checkbox>
|
||||
) : (
|
||||
<ChakraListItem>{children}</ChakraListItem>
|
||||
);
|
||||
|
||||
const Heading = ({ level, children }) => {
|
||||
const levelMap = {
|
||||
1: { as: "h1", size: "lg", fontWeight: "bold" },
|
||||
2: { as: "h2", size: "lg", fontWeight: "normal" },
|
||||
3: { as: "h3", size: "lg", fontWeight: "bold" },
|
||||
4: { as: "h4", size: "md", fontWeight: "normal" },
|
||||
5: { as: "h5", size: "md", fontWeight: "bold" },
|
||||
6: { as: "h6", size: "sm", fontWeight: "bold" }
|
||||
};
|
||||
return <ChakraHeading {...levelMap[level]}>{children}</ChakraHeading>;
|
||||
};
|
||||
|
||||
const Link = ({ children, ...props }) => (
|
||||
<ChakraLink isExternal {...props}>
|
||||
{children}
|
||||
</ChakraLink>
|
||||
);
|
||||
|
||||
const CodeBlock = ({ value }) => <CustomCodeBlock>{value}</CustomCodeBlock>;
|
||||
|
||||
const TableData = ({ isHeader, children, ...props }) => {
|
||||
const Component = isHeader ? TableHeader : TableCell;
|
||||
return <Component {...props}>{children}</Component>;
|
||||
};
|
||||
|
||||
const mdComponents = {
|
||||
paragraph: ChakraText,
|
||||
link: Link,
|
||||
heading: Heading,
|
||||
inlineCode: Code,
|
||||
list: List,
|
||||
listItem: ListItem,
|
||||
thematicBreak: Divider,
|
||||
code: CodeBlock,
|
||||
table: Table,
|
||||
tableCell: TableData
|
||||
};
|
||||
|
||||
export default React.forwardRef(({ content }, ref) => (
|
||||
<ReactMarkdown ref={ref} renderers={mdComponents} source={content} />
|
||||
));
|
66
hyperglass/ui/components/Markdown/MDComponents.js
Normal file
66
hyperglass/ui/components/Markdown/MDComponents.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import * as React from "react";
|
||||
import {
|
||||
Checkbox as ChakraCheckbox,
|
||||
Divider as ChakraDivider,
|
||||
Code as ChakraCode,
|
||||
Heading as ChakraHeading,
|
||||
Link as ChakraLink,
|
||||
List as ChakraList,
|
||||
ListItem as ChakraListItem,
|
||||
Text as ChakraText
|
||||
} from "@chakra-ui/core";
|
||||
|
||||
import {
|
||||
TableCell,
|
||||
TableHeader,
|
||||
Table as ChakraTable
|
||||
} from "~/components/Table";
|
||||
|
||||
import CustomCodeBlock from "~/components/CodeBlock";
|
||||
|
||||
export const Checkbox = ({ checked, children }) => (
|
||||
<ChakraCheckbox isChecked={checked}>{children}</ChakraCheckbox>
|
||||
);
|
||||
|
||||
export const List = ({ ordered, children }) => (
|
||||
<ChakraList as={ordered ? "ol" : "ul"}>{children}</ChakraList>
|
||||
);
|
||||
|
||||
export const ListItem = ({ checked, children }) =>
|
||||
checked ? (
|
||||
<Checkbox checked={checked}>{children}</Checkbox>
|
||||
) : (
|
||||
<ChakraListItem>{children}</ChakraListItem>
|
||||
);
|
||||
|
||||
export const Heading = ({ level, children }) => {
|
||||
const levelMap = {
|
||||
1: { as: "h1", size: "lg", fontWeight: "bold" },
|
||||
2: { as: "h2", size: "lg", fontWeight: "normal" },
|
||||
3: { as: "h3", size: "lg", fontWeight: "bold" },
|
||||
4: { as: "h4", size: "md", fontWeight: "normal" },
|
||||
5: { as: "h5", size: "md", fontWeight: "bold" },
|
||||
6: { as: "h6", size: "sm", fontWeight: "bold" }
|
||||
};
|
||||
return <ChakraHeading {...levelMap[level]}>{children}</ChakraHeading>;
|
||||
};
|
||||
|
||||
export const Link = ({ children, ...props }) => (
|
||||
<ChakraLink isExternal {...props}>
|
||||
{children}
|
||||
</ChakraLink>
|
||||
);
|
||||
|
||||
export const CodeBlock = ({ value }) => (
|
||||
<CustomCodeBlock>{value}</CustomCodeBlock>
|
||||
);
|
||||
|
||||
export const TableData = ({ isHeader, children, ...props }) => {
|
||||
const Component = isHeader ? TableHeader : TableCell;
|
||||
return <Component {...props}>{children}</Component>;
|
||||
};
|
||||
|
||||
export const Paragraph = props => <ChakraText {...props} />;
|
||||
export const InlineCode = props => <ChakraCode {...props} />;
|
||||
export const Divider = props => <ChakraDivider {...props} />;
|
||||
export const Table = props => <ChakraTable {...props} />;
|
34
hyperglass/ui/components/Markdown/index.js
Normal file
34
hyperglass/ui/components/Markdown/index.js
Normal file
@@ -0,0 +1,34 @@
|
||||
import * as React from "react";
|
||||
import { forwardRef } from "react";
|
||||
import ReactMarkdown from "react-markdown";
|
||||
import {
|
||||
List,
|
||||
ListItem,
|
||||
Heading,
|
||||
Link,
|
||||
CodeBlock,
|
||||
TableData,
|
||||
Paragraph,
|
||||
InlineCode,
|
||||
Divider,
|
||||
Table
|
||||
} from "./MDComponents";
|
||||
|
||||
const mdComponents = {
|
||||
paragraph: Paragraph,
|
||||
link: Link,
|
||||
heading: Heading,
|
||||
inlineCode: InlineCode,
|
||||
list: List,
|
||||
listItem: ListItem,
|
||||
thematicBreak: Divider,
|
||||
code: CodeBlock,
|
||||
table: Table,
|
||||
tableCell: TableData
|
||||
};
|
||||
|
||||
const Markdown = forwardRef(({ content }, ref) => (
|
||||
<ReactMarkdown ref={ref} renderers={mdComponents} source={content} />
|
||||
));
|
||||
|
||||
export default Markdown;
|
@@ -1,4 +1,5 @@
|
||||
import React, { createContext, useContext, useMemo } from "react";
|
||||
import * as React from "react";
|
||||
import { createContext, useContext, useMemo } from "react";
|
||||
import { useMediaLayout } from "use-media";
|
||||
|
||||
const MediaContext = createContext(null);
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import * as React from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import Head from "next/head";
|
||||
import { useTheme } from "@chakra-ui/core";
|
||||
import useConfig from "~/components/HyperglassProvider";
|
||||
@@ -9,7 +10,7 @@ const Meta = () => {
|
||||
const theme = useTheme();
|
||||
const [location, setLocation] = useState({});
|
||||
const title = config?.site_title || "hyperglass";
|
||||
const description = config?.site_description || "The modern looking glass.";
|
||||
const description = config?.site_description || "Network Looking Glass";
|
||||
const siteName = `${title} - ${description}`;
|
||||
const keywords = config?.site_keywords || [
|
||||
"hyperglass",
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import ChakraSelect from "~/components/ChakraSelect";
|
||||
|
||||
const buildLocations = networks => {
|
||||
@@ -29,16 +29,15 @@ const QueryLocation = ({ locations, onChange, label }) => {
|
||||
};
|
||||
return (
|
||||
<ChakraSelect
|
||||
isMulti
|
||||
size="lg"
|
||||
options={options}
|
||||
aria-label={label}
|
||||
name="query_location"
|
||||
onChange={handleChange}
|
||||
options={options}
|
||||
isMulti
|
||||
closeMenuOnSelect={false}
|
||||
aria-label={label}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
QueryLocation.displayName = "QueryLocation";
|
||||
export default QueryLocation;
|
||||
|
@@ -68,5 +68,4 @@ const QueryTarget = ({
|
||||
);
|
||||
};
|
||||
|
||||
QueryTarget.displayName = "QueryTarget";
|
||||
export default QueryTarget;
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import ChakraSelect from "~/components/ChakraSelect";
|
||||
|
||||
const QueryType = ({ queryTypes, onChange, label }) => {
|
||||
@@ -18,5 +18,4 @@ const QueryType = ({ queryTypes, onChange, label }) => {
|
||||
);
|
||||
};
|
||||
|
||||
QueryType.displayName = "QueryType";
|
||||
export default QueryType;
|
||||
|
@@ -1,17 +1,14 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import ChakraSelect from "~/components/ChakraSelect";
|
||||
|
||||
const QueryVrf = ({ vrfs, onChange, label }) => {
|
||||
return (
|
||||
<ChakraSelect
|
||||
size="lg"
|
||||
onChange={e => onChange({ field: "query_vrf", value: e.value })}
|
||||
name="query_vrf"
|
||||
options={vrfs}
|
||||
aria-label={label}
|
||||
/>
|
||||
);
|
||||
};
|
||||
const QueryVrf = ({ vrfs, onChange, label }) => (
|
||||
<ChakraSelect
|
||||
size="lg"
|
||||
options={vrfs}
|
||||
name="query_vrf"
|
||||
aria-label={label}
|
||||
onChange={e => onChange({ field: "query_vrf", value: e.value })}
|
||||
/>
|
||||
);
|
||||
|
||||
QueryVrf.displayName = "QueryVrf";
|
||||
export default QueryVrf;
|
||||
|
@@ -1,20 +1,20 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Button, Icon, Tooltip } from "@chakra-ui/core";
|
||||
|
||||
export default ({ requery, bg = "secondary", ...props }) => {
|
||||
return (
|
||||
<Tooltip hasArrow label="Reload Query" placement="top">
|
||||
<Button
|
||||
as="a"
|
||||
size="sm"
|
||||
variantColor={bg}
|
||||
zIndex="1"
|
||||
onClick={requery}
|
||||
mx={1}
|
||||
{...props}
|
||||
>
|
||||
<Icon size="16px" name="repeat" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
};
|
||||
const RequeryButton = ({ requery, bg = "secondary", ...props }) => (
|
||||
<Tooltip hasArrow label="Reload Query" placement="top">
|
||||
<Button
|
||||
mx={1}
|
||||
as="a"
|
||||
size="sm"
|
||||
zIndex="1"
|
||||
variantColor={bg}
|
||||
onClick={requery}
|
||||
{...props}
|
||||
>
|
||||
<Icon size="16px" name="repeat" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
);
|
||||
|
||||
export default RequeryButton;
|
||||
|
@@ -1,19 +1,18 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Button } from "@chakra-ui/core";
|
||||
import { FiChevronLeft } from "react-icons/fi";
|
||||
|
||||
const ResetButton = React.forwardRef(({ isSubmitting, onClick }, ref) => (
|
||||
<Button
|
||||
ref={ref}
|
||||
color="current"
|
||||
variant="ghost"
|
||||
onClick={onClick}
|
||||
aria-label="Reset Form"
|
||||
opacity={isSubmitting ? 1 : 0}
|
||||
variant="ghost"
|
||||
color="current"
|
||||
onClick={onClick}
|
||||
>
|
||||
<FiChevronLeft size={24} />
|
||||
</Button>
|
||||
));
|
||||
|
||||
ResetButton.displayName = "ResetButton";
|
||||
export default ResetButton;
|
||||
|
@@ -1,6 +1,15 @@
|
||||
import React, { useEffect } from "react";
|
||||
import { Button, Icon, Spinner, Stack, Tag, Text, Tooltip, useColorMode } from "@chakra-ui/core";
|
||||
import axios from "axios";
|
||||
import * as React from "react";
|
||||
import { forwardRef, useEffect } from "react";
|
||||
import {
|
||||
Button,
|
||||
Icon,
|
||||
Spinner,
|
||||
Stack,
|
||||
Tag,
|
||||
Text,
|
||||
Tooltip,
|
||||
useColorMode
|
||||
} from "@chakra-ui/core";
|
||||
import useAxios from "axios-hooks";
|
||||
import format from "string-format";
|
||||
import useConfig from "~/components/HyperglassProvider";
|
||||
@@ -10,150 +19,164 @@ format.extend(String.prototype, {});
|
||||
const labelBg = { dark: "secondary", light: "secondary" };
|
||||
const labelBgSuccess = { dark: "success", light: "success" };
|
||||
|
||||
async function containingPrefix(ipAddress) {
|
||||
try {
|
||||
const prefixData = await axios.get("https://stat.ripe.net/data/network-info/data.json", {
|
||||
params: { resource: ipAddress },
|
||||
});
|
||||
return prefixData.data?.data?.prefix;
|
||||
} catch (err) {
|
||||
console.dir(err);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
const ResolvedTarget = forwardRef(
|
||||
({ fqdnTarget, setTarget, queryTarget, families, availVrfs }, ref) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const config = useConfig();
|
||||
const labelBgStatus = {
|
||||
true: labelBgSuccess[colorMode],
|
||||
false: labelBg[colorMode]
|
||||
};
|
||||
const dnsUrl = config.web.dns_provider.url;
|
||||
const query4 = families.includes(4);
|
||||
const query6 = families.includes(6);
|
||||
const params = {
|
||||
4: {
|
||||
url: dnsUrl,
|
||||
params: { name: fqdnTarget, type: "A" },
|
||||
headers: { accept: "application/dns-json" },
|
||||
crossdomain: true,
|
||||
timeout: 1000
|
||||
},
|
||||
6: {
|
||||
url: dnsUrl,
|
||||
params: { name: fqdnTarget, type: "AAAA" },
|
||||
headers: { accept: "application/dns-json" },
|
||||
crossdomain: true,
|
||||
timeout: 1000
|
||||
}
|
||||
};
|
||||
|
||||
const ResolvedTarget = React.forwardRef(
|
||||
({ fqdnTarget, setTarget, queryTarget, families, availVrfs }, ref) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const config = useConfig();
|
||||
const labelBgStatus = { true: labelBgSuccess[colorMode], false: labelBg[colorMode] };
|
||||
const dnsUrl = config.web.dns_provider.url;
|
||||
const query4 = families.includes(4);
|
||||
const query6 = families.includes(6);
|
||||
const params = {
|
||||
4: {
|
||||
url: dnsUrl,
|
||||
params: { name: fqdnTarget, type: "A" },
|
||||
headers: { accept: "application/dns-json" },
|
||||
crossdomain: true,
|
||||
timeout: 1000,
|
||||
},
|
||||
6: {
|
||||
url: dnsUrl,
|
||||
params: { name: fqdnTarget, type: "AAAA" },
|
||||
headers: { accept: "application/dns-json" },
|
||||
crossdomain: true,
|
||||
timeout: 1000,
|
||||
},
|
||||
};
|
||||
const [{ data: data4, loading: loading4, error: error4 }] = useAxios(
|
||||
params[4]
|
||||
);
|
||||
|
||||
const [{ data: data4, loading: loading4, error: error4 }] = useAxios(params[4]);
|
||||
const [{ data: data6, loading: loading6, error: error6 }] = useAxios(
|
||||
params[6]
|
||||
);
|
||||
|
||||
const [{ data: data6, loading: loading6, error: error6 }] = useAxios(params[6]);
|
||||
const handleOverride = overridden => {
|
||||
setTarget({ field: "query_target", value: overridden });
|
||||
};
|
||||
|
||||
const handleOverride = (overridden) => {
|
||||
setTarget({ field: "query_target", value: overridden });
|
||||
};
|
||||
const isSelected = value => {
|
||||
return labelBgStatus[value === queryTarget];
|
||||
};
|
||||
|
||||
const isSelected = (value) => {
|
||||
return labelBgStatus[value === queryTarget];
|
||||
};
|
||||
const findAnswer = data => {
|
||||
return data?.Answer?.filter(
|
||||
answerData => answerData.type === data?.Question[0]?.type
|
||||
)[0]?.data;
|
||||
};
|
||||
|
||||
const findAnswer = (data) => {
|
||||
return data?.Answer?.filter(
|
||||
(answerData) => answerData.type === data?.Question[0]?.type
|
||||
)[0]?.data;
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (query6 && data6?.Answer) {
|
||||
handleOverride(findAnswer(data6));
|
||||
} else if (query4 && data4?.Answer && !query6 && !data6?.Answer) {
|
||||
handleOverride(findAnswer(data4));
|
||||
} else if (query4 && data4?.Answer) {
|
||||
handleOverride(findAnswer(data4));
|
||||
}
|
||||
}, [data4, data6]);
|
||||
return (
|
||||
<Stack
|
||||
ref={ref}
|
||||
isInline
|
||||
w="100%"
|
||||
justifyContent={
|
||||
query4 && data4?.Answer && query6 && data6?.Answer && availVrfs.length > 1
|
||||
? "space-between"
|
||||
: "flex-end"
|
||||
}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
{loading4 ||
|
||||
error4 ||
|
||||
(query4 && findAnswer(data4) && (
|
||||
<Tag my={2}>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
label={config.web.text.fqdn_tooltip.format({ protocol: "IPv4" })}
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
height="unset"
|
||||
minW="unset"
|
||||
fontSize="xs"
|
||||
py="0.1rem"
|
||||
px={2}
|
||||
mr={2}
|
||||
variantColor={labelBgStatus[findAnswer(data4) === queryTarget]}
|
||||
borderRadius="md"
|
||||
onClick={() => handleOverride(findAnswer(data4))}
|
||||
>
|
||||
IPv4
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{loading4 && <Spinner />}
|
||||
{error4 && <Icon name="warning" />}
|
||||
{findAnswer(data4) && (
|
||||
<Text fontSize="xs" fontFamily="mono" as="span" fontWeight={400}>
|
||||
{findAnswer(data4)}
|
||||
</Text>
|
||||
)}
|
||||
</Tag>
|
||||
))}
|
||||
{loading6 ||
|
||||
error6 ||
|
||||
(query6 && findAnswer(data6) && (
|
||||
<Tag my={2}>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
label={config.web.text.fqdn_tooltip.format({ protocol: "IPv6" })}
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
height="unset"
|
||||
minW="unset"
|
||||
fontSize="xs"
|
||||
py="0.1rem"
|
||||
px={2}
|
||||
mr={2}
|
||||
variantColor={isSelected(findAnswer(data6))}
|
||||
borderRadius="md"
|
||||
onClick={() => handleOverride(findAnswer(data6))}
|
||||
>
|
||||
IPv6
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{loading6 && <Spinner />}
|
||||
{error6 && <Icon name="warning" />}
|
||||
{findAnswer(data6) && (
|
||||
<Text fontSize="xs" fontFamily="mono" as="span" fontWeight={400}>
|
||||
{findAnswer(data6)}
|
||||
</Text>
|
||||
)}
|
||||
</Tag>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
useEffect(() => {
|
||||
if (query6 && data6?.Answer) {
|
||||
handleOverride(findAnswer(data6));
|
||||
} else if (query4 && data4?.Answer && !query6 && !data6?.Answer) {
|
||||
handleOverride(findAnswer(data4));
|
||||
} else if (query4 && data4?.Answer) {
|
||||
handleOverride(findAnswer(data4));
|
||||
}
|
||||
}, [data4, data6]);
|
||||
return (
|
||||
<Stack
|
||||
ref={ref}
|
||||
isInline
|
||||
w="100%"
|
||||
justifyContent={
|
||||
query4 &&
|
||||
data4?.Answer &&
|
||||
query6 &&
|
||||
data6?.Answer &&
|
||||
availVrfs.length > 1
|
||||
? "space-between"
|
||||
: "flex-end"
|
||||
}
|
||||
flexWrap="wrap"
|
||||
>
|
||||
{loading4 ||
|
||||
error4 ||
|
||||
(query4 && findAnswer(data4) && (
|
||||
<Tag my={2}>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
label={config.web.text.fqdn_tooltip.format({
|
||||
protocol: "IPv4"
|
||||
})}
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
height="unset"
|
||||
minW="unset"
|
||||
fontSize="xs"
|
||||
py="0.1rem"
|
||||
px={2}
|
||||
mr={2}
|
||||
variantColor={
|
||||
labelBgStatus[findAnswer(data4) === queryTarget]
|
||||
}
|
||||
borderRadius="md"
|
||||
onClick={() => handleOverride(findAnswer(data4))}
|
||||
>
|
||||
IPv4
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{loading4 && <Spinner />}
|
||||
{error4 && <Icon name="warning" />}
|
||||
{findAnswer(data4) && (
|
||||
<Text
|
||||
fontSize="xs"
|
||||
fontFamily="mono"
|
||||
as="span"
|
||||
fontWeight={400}
|
||||
>
|
||||
{findAnswer(data4)}
|
||||
</Text>
|
||||
)}
|
||||
</Tag>
|
||||
))}
|
||||
{loading6 ||
|
||||
error6 ||
|
||||
(query6 && findAnswer(data6) && (
|
||||
<Tag my={2}>
|
||||
<Tooltip
|
||||
hasArrow
|
||||
label={config.web.text.fqdn_tooltip.format({
|
||||
protocol: "IPv6"
|
||||
})}
|
||||
placement="bottom"
|
||||
>
|
||||
<Button
|
||||
height="unset"
|
||||
minW="unset"
|
||||
fontSize="xs"
|
||||
py="0.1rem"
|
||||
px={2}
|
||||
mr={2}
|
||||
variantColor={isSelected(findAnswer(data6))}
|
||||
borderRadius="md"
|
||||
onClick={() => handleOverride(findAnswer(data6))}
|
||||
>
|
||||
IPv6
|
||||
</Button>
|
||||
</Tooltip>
|
||||
{loading6 && <Spinner />}
|
||||
{error6 && <Icon name="warning" />}
|
||||
{findAnswer(data6) && (
|
||||
<Text
|
||||
fontSize="xs"
|
||||
fontFamily="mono"
|
||||
as="span"
|
||||
fontWeight={400}
|
||||
>
|
||||
{findAnswer(data6)}
|
||||
</Text>
|
||||
)}
|
||||
</Tag>
|
||||
))}
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
ResolvedTarget.displayName = "ResolvedTarget";
|
||||
export default ResolvedTarget;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/** @jsx jsx */
|
||||
import { jsx } from "@emotion/core";
|
||||
import { useEffect, useState } from "react";
|
||||
import { forwardRef, useEffect, useState } from "react";
|
||||
import {
|
||||
AccordionItem,
|
||||
AccordionHeader,
|
||||
@@ -78,7 +78,7 @@ 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(
|
||||
const Result = forwardRef(
|
||||
(
|
||||
{
|
||||
device,
|
||||
@@ -276,5 +276,4 @@ const Result = React.forwardRef(
|
||||
}
|
||||
);
|
||||
|
||||
Result.displayName = "HyperglassQueryResult";
|
||||
export default Result;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { forwardRef } from "react";
|
||||
import {
|
||||
AccordionIcon,
|
||||
Icon,
|
||||
@@ -31,7 +32,7 @@ const defaultStatusColor = {
|
||||
light: "success.500"
|
||||
};
|
||||
|
||||
export default React.forwardRef(
|
||||
const ResultHeader = forwardRef(
|
||||
({ title, loading, error, errorMsg, errorLevel, runtime }, ref) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const config = useConfig();
|
||||
@@ -68,3 +69,5 @@ export default React.forwardRef(
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
export default ResultHeader;
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import React, { useState } from "react";
|
||||
import * as React from "react";
|
||||
import { useState } from "react";
|
||||
import { Accordion, Box, Stack, useTheme } from "@chakra-ui/core";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import Label from "~/components/Label";
|
||||
@@ -10,148 +11,155 @@ const AnimatedResult = motion.custom(Result);
|
||||
const AnimatedLabel = motion.custom(Label);
|
||||
|
||||
const labelInitial = {
|
||||
left: {
|
||||
sm: { opacity: 0, x: -100 },
|
||||
md: { opacity: 0, x: -100 },
|
||||
lg: { opacity: 0, x: -100 },
|
||||
xl: { opacity: 0, x: -100 }
|
||||
},
|
||||
center: {
|
||||
sm: { opacity: 0 },
|
||||
md: { opacity: 0 },
|
||||
lg: { opacity: 0 },
|
||||
xl: { opacity: 0 }
|
||||
},
|
||||
right: {
|
||||
sm: { opacity: 0, x: 100 },
|
||||
md: { opacity: 0, x: 100 },
|
||||
lg: { opacity: 0, x: 100 },
|
||||
xl: { opacity: 0, x: 100 }
|
||||
}
|
||||
left: {
|
||||
sm: { opacity: 0, x: -100 },
|
||||
md: { opacity: 0, x: -100 },
|
||||
lg: { opacity: 0, x: -100 },
|
||||
xl: { opacity: 0, x: -100 }
|
||||
},
|
||||
center: {
|
||||
sm: { opacity: 0 },
|
||||
md: { opacity: 0 },
|
||||
lg: { opacity: 0 },
|
||||
xl: { opacity: 0 }
|
||||
},
|
||||
right: {
|
||||
sm: { opacity: 0, x: 100 },
|
||||
md: { opacity: 0, x: 100 },
|
||||
lg: { opacity: 0, x: 100 },
|
||||
xl: { opacity: 0, x: 100 }
|
||||
}
|
||||
};
|
||||
const labelAnimate = {
|
||||
left: {
|
||||
sm: { opacity: 1, x: 0 },
|
||||
md: { opacity: 1, x: 0 },
|
||||
lg: { opacity: 1, x: 0 },
|
||||
xl: { opacity: 1, x: 0 }
|
||||
},
|
||||
center: {
|
||||
sm: { opacity: 1 },
|
||||
md: { opacity: 1 },
|
||||
lg: { opacity: 1 },
|
||||
xl: { opacity: 1 }
|
||||
},
|
||||
right: {
|
||||
sm: { opacity: 1, x: 0 },
|
||||
md: { opacity: 1, x: 0 },
|
||||
lg: { opacity: 1, x: 0 },
|
||||
xl: { opacity: 1, x: 0 }
|
||||
}
|
||||
left: {
|
||||
sm: { opacity: 1, x: 0 },
|
||||
md: { opacity: 1, x: 0 },
|
||||
lg: { opacity: 1, x: 0 },
|
||||
xl: { opacity: 1, x: 0 }
|
||||
},
|
||||
center: {
|
||||
sm: { opacity: 1 },
|
||||
md: { opacity: 1 },
|
||||
lg: { opacity: 1 },
|
||||
xl: { opacity: 1 }
|
||||
},
|
||||
right: {
|
||||
sm: { opacity: 1, x: 0 },
|
||||
md: { opacity: 1, x: 0 },
|
||||
lg: { opacity: 1, x: 0 },
|
||||
xl: { opacity: 1, x: 0 }
|
||||
}
|
||||
};
|
||||
|
||||
const Results = ({ queryLocation, queryType, queryVrf, queryTarget, setSubmitting, ...props }) => {
|
||||
const config = useConfig();
|
||||
const theme = useTheme();
|
||||
const { mediaSize } = useMedia();
|
||||
const matchedVrf =
|
||||
config.vrfs.filter(v => v.id === queryVrf)[0] ??
|
||||
config.vrfs.filter(v => v.id === "default")[0];
|
||||
const [resultsComplete, setComplete] = useState(null);
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
maxW={["100%", "100%", "75%", "50%"]}
|
||||
w="100%"
|
||||
p={0}
|
||||
mx="auto"
|
||||
my={4}
|
||||
textAlign="left"
|
||||
{...props}
|
||||
>
|
||||
<Stack isInline align="center" justify="center" mt={4} flexWrap="wrap">
|
||||
<AnimatePresence>
|
||||
{queryLocation && (
|
||||
<>
|
||||
<AnimatedLabel
|
||||
initial={labelInitial.left[mediaSize]}
|
||||
animate={labelAnimate.left[mediaSize]}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
exit={{ opacity: 0, x: -100 }}
|
||||
label={config.web.text.query_type}
|
||||
value={config.queries[queryType].display_name}
|
||||
valueBg={theme.colors.cyan[500]}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
/>
|
||||
<AnimatedLabel
|
||||
initial={labelInitial.center[mediaSize]}
|
||||
animate={labelAnimate.center[mediaSize]}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
exit={{ opacity: 0, scale: 0.5 }}
|
||||
label={config.web.text.query_target}
|
||||
value={queryTarget}
|
||||
valueBg={theme.colors.teal[600]}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
/>
|
||||
<AnimatedLabel
|
||||
initial={labelInitial.right[mediaSize]}
|
||||
animate={labelAnimate.right[mediaSize]}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
exit={{ opacity: 0, x: 100 }}
|
||||
label={config.web.text.query_vrf}
|
||||
value={matchedVrf.display_name}
|
||||
valueBg={theme.colors.blue[500]}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Box
|
||||
maxW={["100%", "100%", "75%", "75%"]}
|
||||
w="100%"
|
||||
p={0}
|
||||
mx="auto"
|
||||
my={4}
|
||||
textAlign="left"
|
||||
borderWidth="1px"
|
||||
rounded="lg"
|
||||
overflow="hidden"
|
||||
>
|
||||
<Accordion
|
||||
allowMultiple
|
||||
initial={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 300 }}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{queryLocation &&
|
||||
queryLocation.map((loc, i) => (
|
||||
<AnimatedResult
|
||||
initial={{ opacity: 0, y: 300 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, delay: i * 0.3 }}
|
||||
exit={{ opacity: 0, y: 300 }}
|
||||
key={loc}
|
||||
timeout={config.request_timeout * 1000}
|
||||
device={config.devices[loc]}
|
||||
queryLocation={loc}
|
||||
queryType={queryType}
|
||||
queryVrf={queryVrf}
|
||||
queryTarget={queryTarget}
|
||||
setSubmitting={setSubmitting}
|
||||
index={i}
|
||||
resultsComplete={resultsComplete}
|
||||
setComplete={setComplete}
|
||||
/>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</Accordion>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
const Results = ({
|
||||
queryLocation,
|
||||
queryType,
|
||||
queryVrf,
|
||||
queryTarget,
|
||||
setSubmitting,
|
||||
...props
|
||||
}) => {
|
||||
const config = useConfig();
|
||||
const theme = useTheme();
|
||||
const { mediaSize } = useMedia();
|
||||
const matchedVrf =
|
||||
config.vrfs.filter(v => v.id === queryVrf)[0] ??
|
||||
config.vrfs.filter(v => v.id === "default")[0];
|
||||
const [resultsComplete, setComplete] = useState(null);
|
||||
return (
|
||||
<>
|
||||
<Box
|
||||
maxW={["100%", "100%", "75%", "50%"]}
|
||||
w="100%"
|
||||
p={0}
|
||||
mx="auto"
|
||||
my={4}
|
||||
textAlign="left"
|
||||
{...props}
|
||||
>
|
||||
<Stack isInline align="center" justify="center" mt={4} flexWrap="wrap">
|
||||
<AnimatePresence>
|
||||
{queryLocation && (
|
||||
<>
|
||||
<AnimatedLabel
|
||||
initial={labelInitial.left[mediaSize]}
|
||||
animate={labelAnimate.left[mediaSize]}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
exit={{ opacity: 0, x: -100 }}
|
||||
label={config.web.text.query_type}
|
||||
value={config.queries[queryType].display_name}
|
||||
valueBg={theme.colors.cyan[500]}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
/>
|
||||
<AnimatedLabel
|
||||
initial={labelInitial.center[mediaSize]}
|
||||
animate={labelAnimate.center[mediaSize]}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
exit={{ opacity: 0, scale: 0.5 }}
|
||||
label={config.web.text.query_target}
|
||||
value={queryTarget}
|
||||
valueBg={theme.colors.teal[600]}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
/>
|
||||
<AnimatedLabel
|
||||
initial={labelInitial.right[mediaSize]}
|
||||
animate={labelAnimate.right[mediaSize]}
|
||||
transition={{ duration: 0.3, delay: 0.3 }}
|
||||
exit={{ opacity: 0, x: 100 }}
|
||||
label={config.web.text.query_vrf}
|
||||
value={matchedVrf.display_name}
|
||||
valueBg={theme.colors.blue[500]}
|
||||
fontSize={["xs", "sm", "sm", "sm"]}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
</Stack>
|
||||
</Box>
|
||||
<Box
|
||||
maxW={["100%", "100%", "75%", "75%"]}
|
||||
w="100%"
|
||||
p={0}
|
||||
mx="auto"
|
||||
my={4}
|
||||
textAlign="left"
|
||||
borderWidth="1px"
|
||||
rounded="lg"
|
||||
overflow="hidden"
|
||||
>
|
||||
<Accordion
|
||||
allowMultiple
|
||||
initial={{ opacity: 1 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
exit={{ opacity: 0, y: 300 }}
|
||||
>
|
||||
<AnimatePresence>
|
||||
{queryLocation &&
|
||||
queryLocation.map((loc, i) => (
|
||||
<AnimatedResult
|
||||
initial={{ opacity: 0, y: 300 }}
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3, delay: i * 0.3 }}
|
||||
exit={{ opacity: 0, y: 300 }}
|
||||
key={loc}
|
||||
timeout={config.request_timeout * 1000}
|
||||
device={config.devices[loc]}
|
||||
queryLocation={loc}
|
||||
queryType={queryType}
|
||||
queryVrf={queryVrf}
|
||||
queryTarget={queryTarget}
|
||||
setSubmitting={setSubmitting}
|
||||
index={i}
|
||||
resultsComplete={resultsComplete}
|
||||
setComplete={setComplete}
|
||||
/>
|
||||
))}
|
||||
</AnimatePresence>
|
||||
</Accordion>
|
||||
</Box>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
Results.displayName = "HyperglassResults";
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { forwardRef } from "react";
|
||||
import {
|
||||
Box,
|
||||
PseudoBox,
|
||||
@@ -54,7 +55,11 @@ const btnSizeMap = {
|
||||
}
|
||||
};
|
||||
|
||||
const SubmitButton = React.forwardRef(
|
||||
const btnBg = { dark: "primary.300", light: "primary.500" };
|
||||
const btnBgActive = { dark: "primary.400", light: "primary.600" };
|
||||
const btnBgHover = { dark: "primary.200", light: "primary.400" };
|
||||
|
||||
const SubmitButton = forwardRef(
|
||||
(
|
||||
{
|
||||
isLoading = false,
|
||||
@@ -71,18 +76,6 @@ const SubmitButton = React.forwardRef(
|
||||
const _isDisabled = isDisabled || isLoading;
|
||||
const { colorMode } = useColorMode();
|
||||
const theme = useTheme();
|
||||
const btnBg = {
|
||||
dark: theme.colors.primary[300],
|
||||
light: theme.colors.primary[500]
|
||||
};
|
||||
const btnBgActive = {
|
||||
dark: theme.colors.primary[400],
|
||||
light: theme.colors.primary[600]
|
||||
};
|
||||
const btnBgHover = {
|
||||
dark: theme.colors.primary[200],
|
||||
light: theme.colors.primary[400]
|
||||
};
|
||||
const btnColor = opposingColor(theme, btnBg[colorMode]);
|
||||
const btnColorActive = opposingColor(theme, btnBgActive[colorMode]);
|
||||
const btnColorHover = opposingColor(theme, btnBgHover[colorMode]);
|
||||
@@ -126,5 +119,4 @@ const SubmitButton = React.forwardRef(
|
||||
}
|
||||
);
|
||||
|
||||
SubmitButton.displayName = "SubmitButton";
|
||||
export default SubmitButton;
|
||||
|
@@ -1,24 +1,37 @@
|
||||
import React from "react";
|
||||
import * as React from "react";
|
||||
import { Box, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
const Table = props => <Box as="table" textAlign="left" mt={4} width="full" {...props} />;
|
||||
const Table = props => (
|
||||
<Box as="table" textAlign="left" mt={4} width="full" {...props} />
|
||||
);
|
||||
|
||||
const bg = { light: "blackAlpha.50", dark: "whiteAlpha.50" };
|
||||
|
||||
const TableHeader = props => {
|
||||
const { colorMode } = useColorMode();
|
||||
const bg = { light: "blackAlpha.50", dark: "whiteAlpha.50" };
|
||||
return <Box as="th" bg={bg[colorMode]} fontWeight="semibold" p={2} fontSize="sm" {...props} />;
|
||||
const { colorMode } = useColorMode();
|
||||
|
||||
return (
|
||||
<Box
|
||||
as="th"
|
||||
bg={bg[colorMode]}
|
||||
fontWeight="semibold"
|
||||
p={2}
|
||||
fontSize="sm"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const TableCell = ({ isHeader = false, ...props }) => (
|
||||
<Box
|
||||
as={isHeader ? "th" : "td"}
|
||||
p={2}
|
||||
borderTopWidth="1px"
|
||||
borderColor="inherit"
|
||||
fontSize="sm"
|
||||
whiteSpace="normal"
|
||||
{...props}
|
||||
/>
|
||||
<Box
|
||||
as={isHeader ? "th" : "td"}
|
||||
p={2}
|
||||
borderTopWidth="1px"
|
||||
borderColor="inherit"
|
||||
fontSize="sm"
|
||||
whiteSpace="normal"
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
|
||||
export { TableCell, TableHeader, Table };
|
||||
|
@@ -2,23 +2,19 @@
|
||||
import { jsx } from "@emotion/core";
|
||||
import { Box, css } from "@chakra-ui/core";
|
||||
|
||||
const TableBody = ({ children, ...props }) => {
|
||||
return (
|
||||
<Box
|
||||
as="tbody"
|
||||
overflowY="scroll"
|
||||
css={css({
|
||||
"&::-webkit-scrollbar": { display: "none" },
|
||||
"&": { msOverflowStyle: "none" }
|
||||
})}
|
||||
overflowX="hidden"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
TableBody.displayName = "TableBody";
|
||||
const TableBody = ({ children, ...props }) => (
|
||||
<Box
|
||||
as="tbody"
|
||||
overflowY="scroll"
|
||||
css={css({
|
||||
"&::-webkit-scrollbar": { display: "none" },
|
||||
"&": { msOverflowStyle: "none" }
|
||||
})}
|
||||
overflowX="hidden"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</Box>
|
||||
);
|
||||
|
||||
export default TableBody;
|
||||
|
@@ -1,19 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { Box, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
// export const TableCell = styled("div")`
|
||||
// ${space};
|
||||
// ${color};
|
||||
// ${justifyContent};
|
||||
// flex: 1;
|
||||
// display: flex;
|
||||
// min-width: 150px;
|
||||
// align-items: center;
|
||||
// border-bottom-width: 1px;
|
||||
// overflow: hidden;
|
||||
// text-overflow: ellipsis;
|
||||
// `;
|
||||
|
||||
const cellBorder = {
|
||||
dark: { borderLeft: "1px", borderLeftColor: "whiteAlpha.100" },
|
||||
light: { borderLeft: "1px", borderLeftColor: "blackAlpha.100" }
|
||||
@@ -48,6 +35,4 @@ const TableCell = ({
|
||||
);
|
||||
};
|
||||
|
||||
TableCell.displayName = "TableCell";
|
||||
|
||||
export default TableCell;
|
||||
|
@@ -1,12 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { Box, useColorMode } from "@chakra-ui/core";
|
||||
|
||||
// export const TableHead = styled.div`
|
||||
// ${space};
|
||||
// display: flex;
|
||||
// flex-direction: row;
|
||||
// `;
|
||||
|
||||
const bg = { dark: "whiteAlpha.100", light: "blackAlpha.100" };
|
||||
|
||||
const TableHead = ({ children, ...props }) => {
|
||||
@@ -24,6 +18,4 @@ const TableHead = ({ children, ...props }) => {
|
||||
);
|
||||
};
|
||||
|
||||
TableHead.displayName = "TableHead";
|
||||
|
||||
export default TableHead;
|
||||
|
@@ -1,27 +1,6 @@
|
||||
import * as React from "react";
|
||||
import { IconButton } from "@chakra-ui/core";
|
||||
|
||||
// export const TableIconButton = ({ icon, onClick, isDisabled, children, variantColor, ...rest }) => {
|
||||
// return (
|
||||
// <IconButton
|
||||
// size="sm"
|
||||
// {...rest}
|
||||
// icon={icon}
|
||||
// borderWidth={1}
|
||||
// onClick={onClick}
|
||||
// variantColor={variantColor}
|
||||
// isDisabled={isDisabled}
|
||||
// aria-label="Table Icon button"
|
||||
// >
|
||||
// {children}
|
||||
// </IconButton>
|
||||
// );
|
||||
// };
|
||||
|
||||
// TableIconButton.defaultProps = {
|
||||
// variantColor: "gray",
|
||||
// };
|
||||
|
||||
const TableIconButton = ({
|
||||
icon,
|
||||
onClick,
|
||||
@@ -29,23 +8,19 @@ const TableIconButton = ({
|
||||
color,
|
||||
children,
|
||||
...props
|
||||
}) => {
|
||||
return (
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon={icon}
|
||||
borderWidth={1}
|
||||
onClick={onClick}
|
||||
variantColor={color}
|
||||
isDisabled={isDisabled}
|
||||
aria-label="Table Icon Button"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
TableIconButton.displayName = "TableIconButton";
|
||||
}) => (
|
||||
<IconButton
|
||||
size="sm"
|
||||
icon={icon}
|
||||
borderWidth={1}
|
||||
onClick={onClick}
|
||||
variantColor={color}
|
||||
isDisabled={isDisabled}
|
||||
aria-label="Table Icon Button"
|
||||
{...props}
|
||||
>
|
||||
{children}
|
||||
</IconButton>
|
||||
);
|
||||
|
||||
export default TableIconButton;
|
||||
|
@@ -37,5 +37,4 @@ const MainTable = ({ children, ...props }) => {
|
||||
);
|
||||
};
|
||||
|
||||
MainTable.displayName = "MainTable";
|
||||
export default MainTable;
|
||||
|
@@ -2,13 +2,6 @@ import * as React from "react";
|
||||
import { PseudoBox, useColorMode, useTheme } from "@chakra-ui/core";
|
||||
import { opposingColor } from "~/util";
|
||||
|
||||
// export const TableRow = styled(Flex)`
|
||||
// &:hover {
|
||||
// cursor: pointer;
|
||||
// background-color: rgba(0, 0, 0, 0.01);
|
||||
// }
|
||||
// `;
|
||||
|
||||
const hoverBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
||||
const bgStripe = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
||||
const rowBorder = {
|
||||
@@ -60,6 +53,4 @@ const TableRow = ({
|
||||
);
|
||||
};
|
||||
|
||||
TableRow.displayName = "TableRow";
|
||||
|
||||
export default TableRow;
|
||||
|
@@ -1,32 +1,15 @@
|
||||
import * as React from "react";
|
||||
import { Select } from "@chakra-ui/core";
|
||||
|
||||
{
|
||||
/* <select
|
||||
value={pageSize}
|
||||
onChange={e => {setPageSize(Number(e.target.value))}}
|
||||
>
|
||||
{[5, 10, 20, 30, 40, 50].map(pageSize => (
|
||||
<option key={pageSize} value={pageSize}>
|
||||
Show {pageSize}
|
||||
</option>
|
||||
const TableSelectShow = ({ value, onChange, children, ...props }) => (
|
||||
<Select size="sm" onChange={onChange} {...props}>
|
||||
{[5, 10, 20, 30, 40, 50].map(value => (
|
||||
<option key={value} value={value}>
|
||||
Show {value}
|
||||
</option>
|
||||
))}
|
||||
</select> */
|
||||
}
|
||||
|
||||
const TableSelectShow = ({ value, onChange, children, ...props }) => {
|
||||
return (
|
||||
<Select size="sm" onChange={onChange} {...props}>
|
||||
{[5, 10, 20, 30, 40, 50].map(value => (
|
||||
<option key={value} value={value}>
|
||||
Show {value}
|
||||
</option>
|
||||
))}
|
||||
{children}
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
TableSelectShow.displayName = "TableSelectShow";
|
||||
{children}
|
||||
</Select>
|
||||
);
|
||||
|
||||
export default TableSelectShow;
|
||||
|
@@ -194,6 +194,4 @@ const Table = ({
|
||||
);
|
||||
};
|
||||
|
||||
Table.displayName = "Table";
|
||||
|
||||
export default Table;
|
||||
|
@@ -40,5 +40,4 @@ const TextOutput = ({ children, ...props }) => {
|
||||
);
|
||||
};
|
||||
|
||||
TextOutput.displayName = "TextOutput";
|
||||
export default TextOutput;
|
||||
|
@@ -1,49 +1,48 @@
|
||||
import React from "react";
|
||||
/** @jsx jsx */
|
||||
import { jsx } from "@emotion/core";
|
||||
import { forwardRef } from "react";
|
||||
import { Button, Heading, Image, Stack, useColorMode } from "@chakra-ui/core";
|
||||
import { Textfit } from "react-textfit";
|
||||
import { motion, AnimatePresence } from "framer-motion";
|
||||
import useConfig from "~/components/HyperglassProvider";
|
||||
import useMedia from "~/components/MediaProvider";
|
||||
|
||||
const subtitleAnimation = {
|
||||
transition: { duration: 0.2, type: "tween" },
|
||||
initial: { opacity: 1, scale: 1 },
|
||||
animate: { opacity: 1, scale: 1 },
|
||||
exit: { opacity: 0, scale: 0.3 }
|
||||
};
|
||||
const titleSize = { true: "2xl", false: "lg" };
|
||||
const titleSize = { true: ["2xl", "2xl", "5xl", "5xl"], false: "2xl" };
|
||||
const titleMargin = { true: 2, false: 0 };
|
||||
const textAlignment = { false: ["right", "center"], true: ["left", "center"] };
|
||||
const logoName = { light: "dark", dark: "light" };
|
||||
const justifyMap = {
|
||||
true: ["flex-end", "center", "center", "center"],
|
||||
false: ["flex-start", "center", "center", "center"]
|
||||
};
|
||||
|
||||
const logoFallback = {
|
||||
light:
|
||||
"https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-dark.svg",
|
||||
dark:
|
||||
"https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-light.svg"
|
||||
};
|
||||
|
||||
const TitleOnly = ({ text, showSubtitle }) => (
|
||||
<Heading
|
||||
as="h1"
|
||||
mb={titleMargin[showSubtitle]}
|
||||
size={titleSize[showSubtitle]}
|
||||
fontSize={titleSize[showSubtitle]}
|
||||
>
|
||||
<Textfit mode="single">{text}</Textfit>
|
||||
{text}
|
||||
</Heading>
|
||||
);
|
||||
|
||||
const SubtitleOnly = React.forwardRef(
|
||||
({ text, mediaSize, size = "md", ...props }, ref) => (
|
||||
<Heading
|
||||
ref={ref}
|
||||
as="h3"
|
||||
size={size}
|
||||
whiteSpace="break-spaces"
|
||||
textAlign={["left", "left", "center", "center"]}
|
||||
{...props}
|
||||
>
|
||||
<Textfit mode="multi" max={mediaSize === "sm" ? 13 : 25}>
|
||||
{text}
|
||||
</Textfit>
|
||||
</Heading>
|
||||
)
|
||||
const SubtitleOnly = ({ text, mediaSize, ...props }) => (
|
||||
<Heading
|
||||
as="h3"
|
||||
fontSize={["md", "md", "xl", "xl"]}
|
||||
whiteSpace="break-spaces"
|
||||
textAlign={["left", "left", "center", "center"]}
|
||||
{...props}
|
||||
>
|
||||
{text}
|
||||
</Heading>
|
||||
);
|
||||
|
||||
const AnimatedSubtitle = motion.custom(SubtitleOnly);
|
||||
|
||||
const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => (
|
||||
<Stack
|
||||
spacing={2}
|
||||
@@ -51,42 +50,39 @@ const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => (
|
||||
textAlign={textAlignment[showSubtitle]}
|
||||
{...props}
|
||||
>
|
||||
<Textfit mode="single" max={20}>
|
||||
<TitleOnly text={text.title} showSubtitle={showSubtitle} />
|
||||
</Textfit>
|
||||
<AnimatePresence>
|
||||
{showSubtitle && (
|
||||
<AnimatedSubtitle
|
||||
text={text.subtitle}
|
||||
mediaSize={mediaSize}
|
||||
{...subtitleAnimation}
|
||||
/>
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<TitleOnly text={text.title} showSubtitle={showSubtitle} />
|
||||
{showSubtitle && (
|
||||
<SubtitleOnly text={text.subtitle} mediaSize={mediaSize} />
|
||||
)}
|
||||
</Stack>
|
||||
);
|
||||
|
||||
const Logo = ({ text, logo }) => {
|
||||
const { colorMode } = useColorMode();
|
||||
const logoExt = { light: logo.dark_format, dark: logo.light_format };
|
||||
const logoName = { light: "dark", dark: "light" };
|
||||
const { width, dark_format, light_format } = logo;
|
||||
const logoExt = { light: dark_format, dark: light_format };
|
||||
return (
|
||||
<Image
|
||||
css={{
|
||||
userDrag: "none",
|
||||
userSelect: "none",
|
||||
msUserSelect: "none",
|
||||
MozUserSelect: "none",
|
||||
WebkitUserDrag: "none",
|
||||
WebkitUserSelect: "none"
|
||||
}}
|
||||
alt={text.title}
|
||||
width={logo.width ?? "auto"}
|
||||
width={width ?? "auto"}
|
||||
fallbackSrc={logoFallback[colorMode]}
|
||||
src={`/images/${logoName[colorMode]}${logoExt[colorMode]}`}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const LogoSubtitle = ({ text, logo, showSubtitle, mediaSize }) => (
|
||||
const LogoSubtitle = ({ text, logo, mediaSize }) => (
|
||||
<>
|
||||
<Logo text={text} logo={logo} mediaSize={mediaSize} />
|
||||
<AnimatePresence>
|
||||
{showSubtitle && (
|
||||
<AnimatedSubtitle mt={6} text={text.subtitle} {...subtitleAnimation} />
|
||||
)}
|
||||
</AnimatePresence>
|
||||
<SubtitleOnly mt={6} text={text.subtitle} />
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -108,12 +104,8 @@ const modeMap = {
|
||||
logo_subtitle: LogoSubtitle,
|
||||
all: All
|
||||
};
|
||||
const justifyMap = {
|
||||
true: ["flex-end", "center", "center", "center"],
|
||||
false: ["flex-start", "center", "center", "center"]
|
||||
};
|
||||
|
||||
const Title = React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
||||
const Title = forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
||||
const { web } = useConfig();
|
||||
const { mediaSize } = useMedia();
|
||||
const titleMode = web.text.title_mode;
|
||||
@@ -143,5 +135,4 @@ const Title = React.forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
||||
);
|
||||
});
|
||||
|
||||
Title.displayName = "Title";
|
||||
export default Title;
|
||||
|
@@ -2,24 +2,22 @@ import * as React from "react";
|
||||
import { useTheme } from "@chakra-ui/core";
|
||||
|
||||
const LightningBolt = ({ size = 4, color = "currentColor" }) => {
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<svg
|
||||
width={theme.space[size]}
|
||||
height={theme.space[size]}
|
||||
viewBox="0 0 16 16"
|
||||
fill={theme.colors[color]}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M11.251.068a.5.5 0 0 1 .227.58L9.677 6.5H13a.5.5 0 0 1 .364.843l-8 8.5a.5.5 0 0 1-.842-.49L6.323 9.5H3a.5.5 0 0 1-.364-.843l8-8.5a.5.5 0 0 1 .615-.09z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<svg
|
||||
width={theme.space[size]}
|
||||
height={theme.space[size]}
|
||||
viewBox="0 0 16 16"
|
||||
fill={theme.colors[color]}
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
d="M11.251.068a.5.5 0 0 1 .227.58L9.677 6.5H13a.5.5 0 0 1 .364.843l-8 8.5a.5.5 0 0 1-.842-.49L6.323 9.5H3a.5.5 0 0 1-.364-.843l8-8.5a.5.5 0 0 1 .615-.09z"
|
||||
clipRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
LightningBolt.displayName = "LightningBolt";
|
||||
|
||||
export default LightningBolt;
|
||||
|
@@ -1,6 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
import config from "~/frontend.json";
|
||||
|
||||
export default () => useMemo(() => config);
|
||||
|
||||
export const useConfig = cfg => useMemo(() => cfg);
|
@@ -1,4 +0,0 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
export default (mode = "light", light = "black", dark = "white") =>
|
||||
useMemo(() => (mode ? light : dark));
|
7
hyperglass/ui/package.json
vendored
7
hyperglass/ui/package.json
vendored
@@ -15,7 +15,7 @@
|
||||
},
|
||||
"browserslist": "> 0.25%, not dead",
|
||||
"dependencies": {
|
||||
"@chakra-ui/core": "^0.7.0",
|
||||
"@chakra-ui/core": "^0.8",
|
||||
"@emotion/core": "^10.0.28",
|
||||
"@emotion/styled": "^10.0.27",
|
||||
"@styled-system/should-forward-prop": "^5.1.5",
|
||||
@@ -28,17 +28,16 @@
|
||||
"framer-motion": "^1.10.0",
|
||||
"html-to-react": "^1.4.3",
|
||||
"lodash": "^4.17.15",
|
||||
"next": "^9.3.1",
|
||||
"next": "^9.4",
|
||||
"react": "^16.13.1",
|
||||
"react-countdown": "^2.2.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-hook-form": "^5.1.1",
|
||||
"react-hook-form": "^5.7",
|
||||
"react-icons": "^3.9.0",
|
||||
"react-markdown": "^4.3.1",
|
||||
"react-select": "^3.0.8",
|
||||
"react-string-replace": "^0.4.4",
|
||||
"react-table": "^7.0.4",
|
||||
"react-textfit": "^1.1.0",
|
||||
"string-format": "^2.0.0",
|
||||
"styled-system": "^5.1.5",
|
||||
"tempy": "^0.5.0",
|
||||
|
81
hyperglass/ui/yarn.lock
vendored
81
hyperglass/ui/yarn.lock
vendored
@@ -1015,22 +1015,22 @@
|
||||
lodash "^4.17.13"
|
||||
to-fast-properties "^2.0.0"
|
||||
|
||||
"@chakra-ui/core@^0.7.0":
|
||||
version "0.7.0"
|
||||
resolved "https://registry.yarnpkg.com/@chakra-ui/core/-/core-0.7.0.tgz#5066201cecacc6c48993c8d655f5d85f5da10c2e"
|
||||
integrity sha512-Ph6y9ds7ejuAom7imEwEEhYqTz3EM23mYuRu5qtZxF6b2tvAVbTZ2CjecaUbwZbCVxxiAVCkC2O+cWokeqBEDA==
|
||||
"@chakra-ui/core@^0.8":
|
||||
version "0.8.0"
|
||||
resolved "https://registry.yarnpkg.com/@chakra-ui/core/-/core-0.8.0.tgz#a377286becd86008448ec8cf29ceb8fc301ac2dc"
|
||||
integrity sha512-il1I1nEWOmWJSspnC+WyArLHbHvs82hvKTNDd24wr6spa/7v2jaXFZeWDNenY35ay1NHV7Ya2StcBwQRGHMWYA==
|
||||
dependencies:
|
||||
"@reach/auto-id" "0.9.0"
|
||||
"@reach/auto-id" "0.10.2"
|
||||
"@styled-system/css" "5.1.5"
|
||||
"@styled-system/should-forward-prop" "5.1.5"
|
||||
"@types/styled-system" "5.1.9"
|
||||
aria-hidden "^1.1.1"
|
||||
body-scroll-lock "^2.6.4"
|
||||
body-scroll-lock "^3.0.1"
|
||||
color "3.1.2"
|
||||
copy-to-clipboard "3.3.1"
|
||||
exenv "^1.2.2"
|
||||
popper.js "^1.15.0"
|
||||
react-animate-height "2.0.20"
|
||||
react-animate-height "2.0.21"
|
||||
react-focus-lock "^2.2.1"
|
||||
react-spring "^8.0.27"
|
||||
styled-system "5.1.5"
|
||||
@@ -1504,25 +1504,26 @@
|
||||
"@reach/component-component" "^0.1.3"
|
||||
"@reach/visually-hidden" "^0.1.4"
|
||||
|
||||
"@reach/auto-id@0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.9.0.tgz#73b5d34bcf432f3e73b235b9dcaa89ea05a0d4db"
|
||||
integrity sha512-9/aXl+dT0pOenvpkB2kkmQnpMDlmSk8ZkBYmYFzFz3eA4PZFNuXcHVzQevFRhc0HVlskPjxwPNf92EkI9rdFOw==
|
||||
"@reach/auto-id@0.10.2":
|
||||
version "0.10.2"
|
||||
resolved "https://registry.yarnpkg.com/@reach/auto-id/-/auto-id-0.10.2.tgz#a447af67241123dcb701ecd61931a2c786ed111e"
|
||||
integrity sha512-PWFZevkHshiJV/z0L/5WQkWhe9QRzdZqC7N/JHRCoYo+odvCz9izXVRsxJf7p4sCuOCvnc8zNzAokFk2E1ZzDg==
|
||||
dependencies:
|
||||
"@reach/utils" "^0.9.0"
|
||||
tslib "^1.10.0"
|
||||
"@reach/utils" "^0.10.2"
|
||||
tslib "^1.11.2"
|
||||
|
||||
"@reach/component-component@^0.1.3":
|
||||
version "0.1.3"
|
||||
resolved "https://registry.yarnpkg.com/@reach/component-component/-/component-component-0.1.3.tgz#5d156319572dc38995b246f81878bc2577c517e5"
|
||||
integrity sha512-a1USH7L3bEfDdPN4iNZGvMEFuBfkdG+QNybeyDv8RloVFgZYRoM+KGXyy2KOfEnTUM8QWDRSROwaL3+ts5Angg==
|
||||
|
||||
"@reach/utils@^0.9.0":
|
||||
version "0.9.0"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.9.0.tgz#ee47c25c79eb2f98e6c0e728a2672075cc9991d5"
|
||||
integrity sha512-cmiykRaxuCysVTsSY3PgrLjySnEIt1PLiSYKh5rAH8nYyEmaOCtw0vaNItFAiqQIjfrxkixmcUE8dyD8kqVuJA==
|
||||
"@reach/utils@^0.10.2":
|
||||
version "0.10.5"
|
||||
resolved "https://registry.yarnpkg.com/@reach/utils/-/utils-0.10.5.tgz#fbac944d29565f6dd7abd0e1b13950e99b1e470b"
|
||||
integrity sha512-5E/xxQnUbmpI/LrufBAOXjunl96DnqX6B4zC2MO2KH/dRzLug5gM5VuOwV26egsp0jvsSPxojwciOhS43px3qw==
|
||||
dependencies:
|
||||
tslib "^1.10.0"
|
||||
"@types/warning" "^3.0.0"
|
||||
tslib "^2.0.0"
|
||||
warning "^4.0.3"
|
||||
|
||||
"@reach/visually-hidden@^0.1.4":
|
||||
@@ -1691,6 +1692,11 @@
|
||||
dependencies:
|
||||
csstype "^2.6.9"
|
||||
|
||||
"@types/warning@^3.0.0":
|
||||
version "3.0.0"
|
||||
resolved "https://registry.yarnpkg.com/@types/warning/-/warning-3.0.0.tgz#0d2501268ad8f9962b740d387c4654f5f8e23e52"
|
||||
integrity sha1-DSUBJorY+ZYrdA04fEZU9fjiPlI=
|
||||
|
||||
"@typescript-eslint/eslint-plugin@^2.24.0":
|
||||
version "2.34.0"
|
||||
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-2.34.0.tgz#6f8ce8a46c7dea4a6f1d171d2bb8fbae6dac2be9"
|
||||
@@ -2438,10 +2444,10 @@ body-parser@1.19.0:
|
||||
raw-body "2.4.0"
|
||||
type-is "~1.6.17"
|
||||
|
||||
body-scroll-lock@^2.6.4:
|
||||
version "2.7.1"
|
||||
resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-2.7.1.tgz#caf3f9c91773af1ffb684cd66ed9137b5b737014"
|
||||
integrity sha512-hS53SQ8RhM0e4DsQ3PKz6Gr2O7Kpdh59TWU98GHjaQznL7y4dFycEPk7pFQAikqBaUSCArkc5E3pe7CWIt2fZA==
|
||||
body-scroll-lock@^3.0.1:
|
||||
version "3.0.3"
|
||||
resolved "https://registry.yarnpkg.com/body-scroll-lock/-/body-scroll-lock-3.0.3.tgz#221d87435bcfb50e27ab5d4508735f622aed11a2"
|
||||
integrity sha512-EUryImgD6Gv87HOjJB/yB2WIGECiZMhmcUK+DrqVRFDDa64xR+FsK0LgvLPnBxZDTxIl+W80/KJ8i6gp2IwOHQ==
|
||||
|
||||
boolbase@^1.0.0, boolbase@~1.0.0:
|
||||
version "1.0.0"
|
||||
@@ -6232,7 +6238,7 @@ next-tick@~1.0.0:
|
||||
resolved "https://registry.yarnpkg.com/next-tick/-/next-tick-1.0.0.tgz#ca86d1fe8828169b0120208e3dc8424b9db8342c"
|
||||
integrity sha1-yobR/ogoFpsBICCOPchCS524NCw=
|
||||
|
||||
next@^9.3.1:
|
||||
next@^9.4:
|
||||
version "9.4.4"
|
||||
resolved "https://registry.yarnpkg.com/next/-/next-9.4.4.tgz#02ad9fea7f7016b6b42fc83b67835e4a0dd0c99a"
|
||||
integrity sha512-ZT8bU2SAv5jkFQ+y8py+Rl5RJRJ6DnZDS+VUnB1cIscmtmUhDi7LYED7pYm4MCKkYhPbEEM1Lbpo7fnoZJGWNQ==
|
||||
@@ -7320,7 +7326,7 @@ process-nextick-args@^2.0.0, process-nextick-args@~2.0.0:
|
||||
resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2"
|
||||
integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==
|
||||
|
||||
process@^0.11.10, process@^0.11.9:
|
||||
process@^0.11.10:
|
||||
version "0.11.10"
|
||||
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
|
||||
integrity sha1-czIwDoQBYb2j5podHZGn1LwW8YI=
|
||||
@@ -7349,7 +7355,7 @@ prop-types-exact@1.2.0:
|
||||
object.assign "^4.1.0"
|
||||
reflect.ownkeys "^0.2.0"
|
||||
|
||||
prop-types@15.7.2, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
prop-types@15.7.2, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
|
||||
version "15.7.2"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
|
||||
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
|
||||
@@ -7518,10 +7524,10 @@ rc@^1.2.7:
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-animate-height@2.0.20:
|
||||
version "2.0.20"
|
||||
resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.0.20.tgz#e519c33a41cb39c071e8115bb3c4f9daad6c703f"
|
||||
integrity sha512-gs6j9oSiWNAnquEVpPMdTe/kwsdVORkRYsgPju4VfM1wKwai7pdmwob//1ECmCQTD8S0NfRDDBk0l7MJGFNmbw==
|
||||
react-animate-height@2.0.21:
|
||||
version "2.0.21"
|
||||
resolved "https://registry.yarnpkg.com/react-animate-height/-/react-animate-height-2.0.21.tgz#da9223eb0e74457d52f72da477c8626550df2ce6"
|
||||
integrity sha512-CZHdjMD8qqp10tYtWmauWYASXxxv9vYeljxFGFtbcrbNXhsUv0w3IjxVK+0yCnyfk7769WfMZKHra4vRcbMnQg==
|
||||
dependencies:
|
||||
classnames "^2.2.5"
|
||||
prop-types "^15.6.1"
|
||||
@@ -7562,7 +7568,7 @@ react-focus-lock@^2.2.1:
|
||||
use-callback-ref "^1.2.1"
|
||||
use-sidecar "^1.0.1"
|
||||
|
||||
react-hook-form@^5.1.1:
|
||||
react-hook-form@^5.7:
|
||||
version "5.7.2"
|
||||
resolved "https://registry.yarnpkg.com/react-hook-form/-/react-hook-form-5.7.2.tgz#a84e259e5d37dd30949af4f79c4dac31101b79ac"
|
||||
integrity sha512-bJvY348vayIvEUmSK7Fvea/NgqbT2racA2IbnJz/aPlQ3GBtaTeDITH6rtCa6y++obZzG6E3Q8VuoXPir7QYUg==
|
||||
@@ -7641,14 +7647,6 @@ react-table@^7.0.4:
|
||||
dependencies:
|
||||
"@scarf/scarf" "^1.0.4"
|
||||
|
||||
react-textfit@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/react-textfit/-/react-textfit-1.1.0.tgz#088855580f2e7aad269efc81b734bf636877d0e1"
|
||||
integrity sha512-iznFbj7fCizuo3Xof9iv57I8GZFiYp8vUFj+4qihHJZpzNwxWad7JZu7ALTAnwaiq/H0p60g8G4ifeEJYmfJuw==
|
||||
dependencies:
|
||||
process "^0.11.9"
|
||||
prop-types "^15.5.10"
|
||||
|
||||
react-transition-group@^4.3.0:
|
||||
version "4.4.1"
|
||||
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9"
|
||||
@@ -9109,11 +9107,16 @@ tsconfig-paths@^3.9.0:
|
||||
minimist "^1.2.0"
|
||||
strip-bom "^3.0.0"
|
||||
|
||||
tslib@^1.0.0, tslib@^1.10.0, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
tslib@^1.0.0, tslib@^1.10.0, tslib@^1.11.2, tslib@^1.8.1, tslib@^1.9.0, tslib@^1.9.3:
|
||||
version "1.13.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.13.0.tgz#c881e13cc7015894ed914862d276436fa9a47043"
|
||||
integrity sha512-i/6DQjL8Xf3be4K/E6Wgpekn5Qasl1usyw++dAA35Ue5orEn65VIxOA+YvNNl9HV3qv70T7CNwjODHZrLwvd1Q==
|
||||
|
||||
tslib@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.0.0.tgz#18d13fc2dce04051e20f074cc8387fd8089ce4f3"
|
||||
integrity sha512-lTqkx847PI7xEDYJntxZH89L2/aXInsyF2luSafe/+0fHOMjlBNXdH6th7f70qxLDhul7KZK0zC8V5ZIyHl0/g==
|
||||
|
||||
tsutils@^3.17.1:
|
||||
version "3.17.1"
|
||||
resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.17.1.tgz#ed719917f11ca0dee586272b2ac49e015a2dd759"
|
||||
|
Reference in New Issue
Block a user