mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
JS style updates [skip ci]
This commit is contained in:
9
hyperglass/ui/.eslintrc
Normal file
9
hyperglass/ui/.eslintrc
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"extends": "@upstatement/eslint-config/react",
|
||||||
|
"plugins": ["react-hooks"],
|
||||||
|
"settings": { "import/resolver": { "typescript": {} } },
|
||||||
|
"rules": {
|
||||||
|
"react-hooks/rules-of-hooks": "error",
|
||||||
|
"react-hooks/exhaustive-deps": ["warn"]
|
||||||
|
}
|
||||||
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
Flex,
|
Flex,
|
||||||
Icon,
|
Icon,
|
||||||
@@ -8,39 +8,39 @@ import {
|
|||||||
PopoverTrigger,
|
PopoverTrigger,
|
||||||
Text,
|
Text,
|
||||||
Tooltip,
|
Tooltip,
|
||||||
useColorMode
|
useColorMode,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
import { MdLastPage } from "@meronex/icons/md";
|
import { MdLastPage } from '@meronex/icons/md';
|
||||||
import dayjs from "dayjs";
|
import dayjs from 'dayjs';
|
||||||
import relativeTimePlugin from "dayjs/plugin/relativeTime";
|
import relativeTimePlugin from 'dayjs/plugin/relativeTime';
|
||||||
import utcPlugin from "dayjs/plugin/utc";
|
import utcPlugin from 'dayjs/plugin/utc';
|
||||||
import { useConfig } from "app/context";
|
import { useConfig } from 'app/context';
|
||||||
import { Table } from "app/components";
|
import { Table } from 'app/components';
|
||||||
|
|
||||||
dayjs.extend(relativeTimePlugin);
|
dayjs.extend(relativeTimePlugin);
|
||||||
dayjs.extend(utcPlugin);
|
dayjs.extend(utcPlugin);
|
||||||
|
|
||||||
const isActiveColor = {
|
const isActiveColor = {
|
||||||
true: { dark: "green.300", light: "green.500" },
|
true: { dark: 'green.300', light: 'green.500' },
|
||||||
false: { dark: "gray.300", light: "gray.500" }
|
false: { dark: 'gray.300', light: 'gray.500' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const arrowColor = {
|
const arrowColor = {
|
||||||
true: { dark: "blackAlpha.500", light: "blackAlpha.500" },
|
true: { dark: 'blackAlpha.500', light: 'blackAlpha.500' },
|
||||||
false: { dark: "whiteAlpha.300", light: "blackAlpha.500" }
|
false: { dark: 'whiteAlpha.300', light: 'blackAlpha.500' },
|
||||||
};
|
};
|
||||||
|
|
||||||
const rpkiIcon = ["not-allowed", "check-circle", "warning", "question"];
|
const rpkiIcon = ['not-allowed', 'check-circle', 'warning', 'question'];
|
||||||
|
|
||||||
const rpkiColor = {
|
const rpkiColor = {
|
||||||
true: {
|
true: {
|
||||||
dark: ["red.500", "green.600", "yellow.500", "gray.800"],
|
dark: ['red.500', 'green.600', 'yellow.500', 'gray.800'],
|
||||||
light: ["red.500", "green.500", "yellow.500", "gray.600"]
|
light: ['red.500', 'green.500', 'yellow.500', 'gray.600'],
|
||||||
},
|
},
|
||||||
false: {
|
false: {
|
||||||
dark: ["red.300", "green.300", "yellow.300", "gray.300"],
|
dark: ['red.300', 'green.300', 'yellow.300', 'gray.300'],
|
||||||
light: ["red.400", "green.500", "yellow.400", "gray.500"]
|
light: ['red.400', 'green.500', 'yellow.400', 'gray.500'],
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const makeColumns = fields => {
|
const makeColumns = fields => {
|
||||||
@@ -50,7 +50,7 @@ const makeColumns = fields => {
|
|||||||
Header: header,
|
Header: header,
|
||||||
accessor: accessor,
|
accessor: accessor,
|
||||||
align: align,
|
align: align,
|
||||||
hidden: false
|
hidden: false,
|
||||||
};
|
};
|
||||||
if (align === null) {
|
if (align === null) {
|
||||||
columnConfig.hidden = true;
|
columnConfig.hidden = true;
|
||||||
@@ -68,22 +68,15 @@ const MonoField = ({ v, ...props }) => (
|
|||||||
const Active = ({ isActive }) => {
|
const Active = ({ isActive }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
return (
|
return (
|
||||||
<Icon
|
<Icon name={isActive ? 'check-circle' : 'warning'} color={isActiveColor[isActive][colorMode]} />
|
||||||
name={isActive ? "check-circle" : "warning"}
|
|
||||||
color={isActiveColor[isActive][colorMode]}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Age = ({ inSeconds }) => {
|
const Age = ({ inSeconds }) => {
|
||||||
const now = dayjs.utc();
|
const now = dayjs.utc();
|
||||||
const then = now.subtract(inSeconds, "seconds");
|
const then = now.subtract(inSeconds, 'seconds');
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip hasArrow label={then.toString().replace('GMT', 'UTC')} placement="right">
|
||||||
hasArrow
|
|
||||||
label={then.toString().replace("GMT", "UTC")}
|
|
||||||
placement="right"
|
|
||||||
>
|
|
||||||
<Text fontSize="sm">{now.to(then, true)}</Text>
|
<Text fontSize="sm">{now.to(then, true)}</Text>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
@@ -91,9 +84,7 @@ const Age = ({ inSeconds }) => {
|
|||||||
|
|
||||||
const Weight = ({ weight, winningWeight }) => {
|
const Weight = ({ weight, winningWeight }) => {
|
||||||
const fixMeText =
|
const fixMeText =
|
||||||
winningWeight === "low"
|
winningWeight === 'low' ? 'Lower Weight is Preferred' : 'Higher Weight is Preferred';
|
||||||
? "Lower Weight is Preferred"
|
|
||||||
: "Higher Weight is Preferred";
|
|
||||||
return (
|
return (
|
||||||
<Tooltip hasArrow label={fixMeText} placement="right">
|
<Tooltip hasArrow label={fixMeText} placement="right">
|
||||||
<Text fontSize="sm" fontFamily="mono">
|
<Text fontSize="sm" fontFamily="mono">
|
||||||
@@ -113,22 +104,12 @@ const ASPath = ({ path, active }) => {
|
|||||||
const asnStr = String(asn);
|
const asnStr = String(asn);
|
||||||
i !== 0 &&
|
i !== 0 &&
|
||||||
paths.push(
|
paths.push(
|
||||||
<Icon
|
<Icon name="chevron-right" key={`separator-${i}`} color={arrowColor[active][colorMode]} />,
|
||||||
name="chevron-right"
|
|
||||||
key={`separator-${i}`}
|
|
||||||
color={arrowColor[active][colorMode]}
|
|
||||||
/>
|
|
||||||
);
|
);
|
||||||
paths.push(
|
paths.push(
|
||||||
<Text
|
<Text fontSize="sm" as="span" whiteSpace="pre" fontFamily="mono" key={`as-${asnStr}-${i}`}>
|
||||||
fontSize="sm"
|
|
||||||
as="span"
|
|
||||||
whiteSpace="pre"
|
|
||||||
fontFamily="mono"
|
|
||||||
key={`as-${asnStr}-${i}`}
|
|
||||||
>
|
|
||||||
{asnStr}
|
{asnStr}
|
||||||
</Text>
|
</Text>,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
return paths;
|
return paths;
|
||||||
@@ -152,13 +133,12 @@ const Communities = ({ communities }) => {
|
|||||||
textAlign="left"
|
textAlign="left"
|
||||||
p={4}
|
p={4}
|
||||||
width="unset"
|
width="unset"
|
||||||
color={colorMode === "dark" ? "white" : "black"}
|
color={colorMode === 'dark' ? 'white' : 'black'}
|
||||||
fontFamily="mono"
|
fontFamily="mono"
|
||||||
fontWeight="normal"
|
fontWeight="normal"
|
||||||
whiteSpace="pre-wrap"
|
whiteSpace="pre-wrap">
|
||||||
>
|
|
||||||
<PopoverArrow />
|
<PopoverArrow />
|
||||||
{communities.join("\n")}
|
{communities.join('\n')}
|
||||||
</PopoverContent>
|
</PopoverContent>
|
||||||
</Popover>
|
</Popover>
|
||||||
));
|
));
|
||||||
@@ -172,18 +152,11 @@ const RPKIState = ({ state, active }) => {
|
|||||||
web.text.rpki_invalid,
|
web.text.rpki_invalid,
|
||||||
web.text.rpki_valid,
|
web.text.rpki_valid,
|
||||||
web.text.rpki_unknown,
|
web.text.rpki_unknown,
|
||||||
web.text.rpki_unverified
|
web.text.rpki_unverified,
|
||||||
];
|
];
|
||||||
return (
|
return (
|
||||||
<Tooltip
|
<Tooltip hasArrow placement="right" label={stateText[state] ?? stateText[3]}>
|
||||||
hasArrow
|
<Icon name={rpkiIcon[state]} color={rpkiColor[active][colorMode][state]} />
|
||||||
placement="right"
|
|
||||||
label={stateText[state] ?? stateText[3]}
|
|
||||||
>
|
|
||||||
<Icon
|
|
||||||
name={rpkiIcon[state]}
|
|
||||||
color={rpkiColor[active][colorMode][state]}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@@ -193,24 +166,16 @@ const Cell = ({ data, rawData, longestASN }) => {
|
|||||||
prefix: <MonoField v={data.value} />,
|
prefix: <MonoField v={data.value} />,
|
||||||
active: <Active isActive={data.value} />,
|
active: <Active isActive={data.value} />,
|
||||||
age: <Age inSeconds={data.value} />,
|
age: <Age inSeconds={data.value} />,
|
||||||
weight: (
|
weight: <Weight weight={data.value} winningWeight={rawData.winning_weight} />,
|
||||||
<Weight weight={data.value} winningWeight={rawData.winning_weight} />
|
|
||||||
),
|
|
||||||
med: <MonoField v={data.value} />,
|
med: <MonoField v={data.value} />,
|
||||||
local_preference: <MonoField v={data.value} />,
|
local_preference: <MonoField v={data.value} />,
|
||||||
as_path: (
|
as_path: <ASPath path={data.value} active={data.row.values.active} longestASN={longestASN} />,
|
||||||
<ASPath
|
|
||||||
path={data.value}
|
|
||||||
active={data.row.values.active}
|
|
||||||
longestASN={longestASN}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
communities: <Communities communities={data.value} />,
|
communities: <Communities communities={data.value} />,
|
||||||
next_hop: <MonoField v={data.value} />,
|
next_hop: <MonoField v={data.value} />,
|
||||||
source_as: <MonoField v={data.value} />,
|
source_as: <MonoField v={data.value} />,
|
||||||
source_rid: <MonoField v={data.value} />,
|
source_rid: <MonoField v={data.value} />,
|
||||||
peer_rid: <MonoField v={data.value} />,
|
peer_rid: <MonoField v={data.value} />,
|
||||||
rpki_state: <RPKIState state={data.value} active={data.row.values.active} />
|
rpki_state: <RPKIState state={data.value} active={data.row.values.active} />,
|
||||||
};
|
};
|
||||||
return component[data.column.id] ?? <> </>;
|
return component[data.column.id] ?? <> </>;
|
||||||
};
|
};
|
||||||
@@ -220,7 +185,7 @@ export const BGPTable = ({ children: data, ...props }) => {
|
|||||||
const columns = makeColumns(config.parsed_data_fields);
|
const columns = makeColumns(config.parsed_data_fields);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Flex my={8} maxW={["100%", "100%", "100%", "100%"]} w="100%" {...props}>
|
<Flex my={8} maxW={['100%', '100%', '100%', '100%']} w="100%" {...props}>
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
data={data.routes}
|
data={data.routes}
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import Countdown, { zeroPad } from "react-countdown";
|
import Countdown, { zeroPad } from 'react-countdown';
|
||||||
import { Text, useColorMode } from "@chakra-ui/core";
|
import { Text, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const bg = { dark: "white", light: "black" };
|
const bg = { dark: 'white', light: 'black' };
|
||||||
|
|
||||||
const Renderer = ({ hours, minutes, seconds, completed, props }) => {
|
const Renderer = ({ hours, minutes, seconds, completed, props }) => {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
@@ -15,7 +15,7 @@ const Renderer = ({ hours, minutes, seconds, completed, props }) => {
|
|||||||
<Text fontSize="xs" color="gray.500">
|
<Text fontSize="xs" color="gray.500">
|
||||||
{props.text}
|
{props.text}
|
||||||
<Text as="span" fontSize="xs" color={bg[props.colorMode]}>
|
<Text as="span" fontSize="xs" color={bg[props.colorMode]}>
|
||||||
{time.join(":")}
|
{time.join(':')}
|
||||||
</Text>
|
</Text>
|
||||||
</Text>
|
</Text>
|
||||||
);
|
);
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
import { Flex, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const bg = { light: "white", dark: "original.dark" };
|
const bg = { light: 'white', dark: 'original.dark' };
|
||||||
const color = { light: "original.dark", dark: "white" };
|
const color = { light: 'original.dark', dark: 'white' };
|
||||||
|
|
||||||
export const CardBody = ({ onClick = () => false, children, ...props }) => {
|
export const CardBody = ({ onClick = () => false, children, ...props }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
@@ -17,8 +17,7 @@ export const CardBody = ({ onClick = () => false, children, ...props }) => {
|
|||||||
bg={bg[colorMode]}
|
bg={bg[colorMode]}
|
||||||
color={color[colorMode]}
|
color={color[colorMode]}
|
||||||
overflow="hidden"
|
overflow="hidden"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Flex } from "@chakra-ui/core";
|
import { Flex } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const CardFooter = ({ children, ...props }) => (
|
export const CardFooter = ({ children, ...props }) => (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -12,8 +12,7 @@ export const CardFooter = ({ children, ...props }) => (
|
|||||||
overflowY="hidden"
|
overflowY="hidden"
|
||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Flex, Text, useColorMode } from "@chakra-ui/core";
|
import { Flex, Text, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const bg = { light: "blackAlpha.50", dark: "whiteAlpha.100" };
|
const bg = { light: 'blackAlpha.50', dark: 'whiteAlpha.100' };
|
||||||
|
|
||||||
export const CardHeader = ({ children, ...props }) => {
|
export const CardHeader = ({ children, ...props }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
@@ -13,8 +13,7 @@ export const CardHeader = ({ children, ...props }) => {
|
|||||||
roundedTopLeft={4}
|
roundedTopLeft={4}
|
||||||
roundedTopRight={4}
|
roundedTopRight={4}
|
||||||
borderBottomWidth="1px"
|
borderBottomWidth="1px"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<Text fontWeight="bold">{children}</Text>
|
<Text fontWeight="bold">{children}</Text>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
export * from "./CardBody";
|
export * from './CardBody';
|
||||||
export * from "./CardFooter";
|
export * from './CardFooter';
|
||||||
export * from "./CardHeader";
|
export * from './CardHeader';
|
||||||
|
@@ -1,85 +1,76 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Text, useColorMode, useTheme } from "@chakra-ui/core";
|
import { Text, useColorMode, useTheme } from '@chakra-ui/core';
|
||||||
import Select from "react-select";
|
import Select from 'react-select';
|
||||||
import { opposingColor } from "app/util";
|
import { opposingColor } from 'app/util';
|
||||||
|
|
||||||
export const ChakraSelect = React.forwardRef(
|
export const ChakraSelect = React.forwardRef(
|
||||||
(
|
({ placeholder = 'Select...', isFullWidth, size, children, ...props }, ref) => {
|
||||||
{ placeholder = "Select...", isFullWidth, size, children, ...props },
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const sizeMap = {
|
const sizeMap = {
|
||||||
lg: { height: theme.space[12] },
|
lg: { height: theme.space[12] },
|
||||||
md: { height: theme.space[10] },
|
md: { height: theme.space[10] },
|
||||||
sm: { height: theme.space[8] }
|
sm: { height: theme.space[8] },
|
||||||
};
|
};
|
||||||
const colorSetPrimaryBg = {
|
const colorSetPrimaryBg = {
|
||||||
dark: theme.colors.primary[300],
|
dark: theme.colors.primary[300],
|
||||||
light: theme.colors.primary[500]
|
light: theme.colors.primary[500],
|
||||||
};
|
};
|
||||||
const colorSetPrimaryColor = opposingColor(
|
const colorSetPrimaryColor = opposingColor(theme, colorSetPrimaryBg[colorMode]);
|
||||||
theme,
|
|
||||||
colorSetPrimaryBg[colorMode]
|
|
||||||
);
|
|
||||||
const bg = {
|
const bg = {
|
||||||
dark: theme.colors.whiteAlpha[100],
|
dark: theme.colors.whiteAlpha[100],
|
||||||
light: theme.colors.white
|
light: theme.colors.white,
|
||||||
};
|
};
|
||||||
const color = {
|
const color = {
|
||||||
dark: theme.colors.whiteAlpha[800],
|
dark: theme.colors.whiteAlpha[800],
|
||||||
light: theme.colors.black
|
light: theme.colors.black,
|
||||||
};
|
};
|
||||||
const borderFocused = theme.colors.secondary[500];
|
const borderFocused = theme.colors.secondary[500];
|
||||||
const borderDisabled = theme.colors.whiteAlpha[100];
|
const borderDisabled = theme.colors.whiteAlpha[100];
|
||||||
const border = {
|
const border = {
|
||||||
dark: theme.colors.whiteAlpha[50],
|
dark: theme.colors.whiteAlpha[50],
|
||||||
light: theme.colors.gray[100]
|
light: theme.colors.gray[100],
|
||||||
};
|
};
|
||||||
const borderRadius = theme.space[1];
|
const borderRadius = theme.space[1];
|
||||||
const hoverColor = {
|
const hoverColor = {
|
||||||
dark: theme.colors.whiteAlpha[200],
|
dark: theme.colors.whiteAlpha[200],
|
||||||
light: theme.colors.gray[300]
|
light: theme.colors.gray[300],
|
||||||
};
|
};
|
||||||
const { height } = sizeMap[size];
|
const { height } = sizeMap[size];
|
||||||
const optionBgActive = {
|
const optionBgActive = {
|
||||||
dark: theme.colors.primary[400],
|
dark: theme.colors.primary[400],
|
||||||
light: theme.colors.primary[600]
|
light: theme.colors.primary[600],
|
||||||
};
|
};
|
||||||
const optionBgColor = opposingColor(theme, optionBgActive[colorMode]);
|
const optionBgColor = opposingColor(theme, optionBgActive[colorMode]);
|
||||||
const optionSelectedBg = {
|
const optionSelectedBg = {
|
||||||
dark: theme.colors.whiteAlpha[400],
|
dark: theme.colors.whiteAlpha[400],
|
||||||
light: theme.colors.blackAlpha[400]
|
light: theme.colors.blackAlpha[400],
|
||||||
};
|
};
|
||||||
const optionSelectedColor = opposingColor(
|
const optionSelectedColor = opposingColor(theme, optionSelectedBg[colorMode]);
|
||||||
theme,
|
|
||||||
optionSelectedBg[colorMode]
|
|
||||||
);
|
|
||||||
const selectedDisabled = theme.colors.whiteAlpha[400];
|
const selectedDisabled = theme.colors.whiteAlpha[400];
|
||||||
const placeholderColor = {
|
const placeholderColor = {
|
||||||
dark: theme.colors.whiteAlpha[700],
|
dark: theme.colors.whiteAlpha[700],
|
||||||
light: theme.colors.gray[600]
|
light: theme.colors.gray[600],
|
||||||
};
|
};
|
||||||
const menuBg = {
|
const menuBg = {
|
||||||
dark: theme.colors.blackFaded[800],
|
dark: theme.colors.blackFaded[800],
|
||||||
light: theme.colors.whiteFaded[50]
|
light: theme.colors.whiteFaded[50],
|
||||||
};
|
};
|
||||||
const menuColor = {
|
const menuColor = {
|
||||||
dark: theme.colors.white,
|
dark: theme.colors.white,
|
||||||
light: theme.colors.blackAlpha[800]
|
light: theme.colors.blackAlpha[800],
|
||||||
};
|
};
|
||||||
const scrollbar = {
|
const scrollbar = {
|
||||||
dark: theme.colors.whiteAlpha[300],
|
dark: theme.colors.whiteAlpha[300],
|
||||||
light: theme.colors.blackAlpha[300]
|
light: theme.colors.blackAlpha[300],
|
||||||
};
|
};
|
||||||
const scrollbarHover = {
|
const scrollbarHover = {
|
||||||
dark: theme.colors.whiteAlpha[400],
|
dark: theme.colors.whiteAlpha[400],
|
||||||
light: theme.colors.blackAlpha[400]
|
light: theme.colors.blackAlpha[400],
|
||||||
};
|
};
|
||||||
const scrollbarBg = {
|
const scrollbarBg = {
|
||||||
dark: theme.colors.whiteAlpha[50],
|
dark: theme.colors.whiteAlpha[50],
|
||||||
light: theme.colors.blackAlpha[50]
|
light: theme.colors.blackAlpha[50],
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Select
|
<Select
|
||||||
@@ -89,7 +80,7 @@ export const ChakraSelect = React.forwardRef(
|
|||||||
...base,
|
...base,
|
||||||
minHeight: height,
|
minHeight: height,
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
width: "100%"
|
width: '100%',
|
||||||
}),
|
}),
|
||||||
control: (base, state) => ({
|
control: (base, state) => ({
|
||||||
...base,
|
...base,
|
||||||
@@ -102,29 +93,29 @@ export const ChakraSelect = React.forwardRef(
|
|||||||
? borderFocused
|
? borderFocused
|
||||||
: border[colorMode],
|
: border[colorMode],
|
||||||
borderRadius: borderRadius,
|
borderRadius: borderRadius,
|
||||||
"&:hover": {
|
'&:hover': {
|
||||||
borderColor: hoverColor[colorMode]
|
borderColor: hoverColor[colorMode],
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
menu: base => ({
|
menu: base => ({
|
||||||
...base,
|
...base,
|
||||||
backgroundColor: menuBg[colorMode],
|
backgroundColor: menuBg[colorMode],
|
||||||
borderRadius: borderRadius
|
borderRadius: borderRadius,
|
||||||
}),
|
}),
|
||||||
menuList: base => ({
|
menuList: base => ({
|
||||||
...base,
|
...base,
|
||||||
"&::-webkit-scrollbar": { width: "5px" },
|
'&::-webkit-scrollbar': { width: '5px' },
|
||||||
"&::-webkit-scrollbar-track": {
|
'&::-webkit-scrollbar-track': {
|
||||||
backgroundColor: scrollbarBg[colorMode]
|
backgroundColor: scrollbarBg[colorMode],
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb": {
|
'&::-webkit-scrollbar-thumb': {
|
||||||
backgroundColor: scrollbar[colorMode]
|
backgroundColor: scrollbar[colorMode],
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb:hover": {
|
'&::-webkit-scrollbar-thumb:hover': {
|
||||||
backgroundColor: scrollbarHover[colorMode]
|
backgroundColor: scrollbarHover[colorMode],
|
||||||
},
|
},
|
||||||
|
|
||||||
"-ms-overflow-style": { display: "none" }
|
'-ms-overflow-style': { display: 'none' },
|
||||||
}),
|
}),
|
||||||
option: (base, state) => ({
|
option: (base, state) => ({
|
||||||
...base,
|
...base,
|
||||||
@@ -134,7 +125,7 @@ export const ChakraSelect = React.forwardRef(
|
|||||||
? optionSelectedBg[colorMode]
|
? optionSelectedBg[colorMode]
|
||||||
: state.isFocused
|
: state.isFocused
|
||||||
? colorSetPrimaryBg[colorMode]
|
? colorSetPrimaryBg[colorMode]
|
||||||
: "transparent",
|
: 'transparent',
|
||||||
color: state.isDisabled
|
color: state.isDisabled
|
||||||
? selectedDisabled
|
? selectedDisabled
|
||||||
: state.isFocused
|
: state.isFocused
|
||||||
@@ -143,62 +134,57 @@ export const ChakraSelect = React.forwardRef(
|
|||||||
? optionSelectedColor
|
? optionSelectedColor
|
||||||
: menuColor[colorMode],
|
: menuColor[colorMode],
|
||||||
fontSize: theme.fontSizes[size],
|
fontSize: theme.fontSizes[size],
|
||||||
"&:active": {
|
'&:active': {
|
||||||
backgroundColor: optionBgActive[colorMode],
|
backgroundColor: optionBgActive[colorMode],
|
||||||
color: optionBgColor
|
color: optionBgColor,
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
indicatorSeparator: base => ({
|
indicatorSeparator: base => ({
|
||||||
...base,
|
...base,
|
||||||
backgroundColor: placeholderColor[colorMode]
|
backgroundColor: placeholderColor[colorMode],
|
||||||
}),
|
}),
|
||||||
dropdownIndicator: base => ({
|
dropdownIndicator: base => ({
|
||||||
...base,
|
...base,
|
||||||
color: placeholderColor[colorMode],
|
color: placeholderColor[colorMode],
|
||||||
"&:hover": {
|
'&:hover': {
|
||||||
color: color[colorMode]
|
color: color[colorMode],
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
valueContainer: base => ({
|
valueContainer: base => ({
|
||||||
...base,
|
...base,
|
||||||
paddingLeft: theme.space[4],
|
paddingLeft: theme.space[4],
|
||||||
paddingRight: theme.space[4]
|
paddingRight: theme.space[4],
|
||||||
}),
|
}),
|
||||||
multiValue: base => ({
|
multiValue: base => ({
|
||||||
...base,
|
...base,
|
||||||
backgroundColor: colorSetPrimaryBg[colorMode]
|
backgroundColor: colorSetPrimaryBg[colorMode],
|
||||||
}),
|
}),
|
||||||
multiValueLabel: base => ({
|
multiValueLabel: base => ({
|
||||||
...base,
|
...base,
|
||||||
color: colorSetPrimaryColor
|
color: colorSetPrimaryColor,
|
||||||
}),
|
}),
|
||||||
multiValueRemove: base => ({
|
multiValueRemove: base => ({
|
||||||
...base,
|
...base,
|
||||||
color: colorSetPrimaryColor,
|
color: colorSetPrimaryColor,
|
||||||
"&:hover": {
|
'&:hover': {
|
||||||
color: colorSetPrimaryColor,
|
color: colorSetPrimaryColor,
|
||||||
backgroundColor: "inherit"
|
backgroundColor: 'inherit',
|
||||||
}
|
},
|
||||||
}),
|
}),
|
||||||
singleValue: base => ({
|
singleValue: base => ({
|
||||||
...base,
|
...base,
|
||||||
color: color[colorMode],
|
color: color[colorMode],
|
||||||
fontSize: theme.fontSizes[size]
|
fontSize: theme.fontSizes[size],
|
||||||
})
|
}),
|
||||||
}}
|
}}
|
||||||
placeholder={
|
placeholder={
|
||||||
<Text
|
<Text color={placeholderColor[colorMode]} fontSize={size} fontFamily={theme.fonts.body}>
|
||||||
color={placeholderColor[colorMode]}
|
|
||||||
fontSize={size}
|
|
||||||
fontFamily={theme.fonts.body}
|
|
||||||
>
|
|
||||||
{placeholder}
|
{placeholder}
|
||||||
</Text>
|
</Text>
|
||||||
}
|
}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Select>
|
</Select>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Box, useColorMode } from "@chakra-ui/core";
|
import { Box, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const CodeBlock = ({ children }) => {
|
export const CodeBlock = ({ children }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const bg = { dark: "gray.800", light: "blackAlpha.100" };
|
const bg = { dark: 'gray.800', light: 'blackAlpha.100' };
|
||||||
const color = { dark: "white", light: "black" };
|
const color = { dark: 'white', light: 'black' };
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
fontFamily="mono"
|
fontFamily="mono"
|
||||||
@@ -17,8 +17,7 @@ export const CodeBlock = ({ children }) => {
|
|||||||
color={color[colorMode]}
|
color={color[colorMode]}
|
||||||
fontSize="sm"
|
fontSize="sm"
|
||||||
whiteSpace="pre-wrap"
|
whiteSpace="pre-wrap"
|
||||||
as="pre"
|
as="pre">
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@@ -1,43 +1,41 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import { Button, useColorMode } from "@chakra-ui/core";
|
import { Button, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const Sun = ({ color, size = "1.5rem", ...props }) => (
|
const Sun = ({ color, size = '1.5rem', ...props }) => (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 512 512"
|
viewBox="0 0 512 512"
|
||||||
style={{
|
style={{
|
||||||
height: size,
|
height: size,
|
||||||
width: size
|
width: size,
|
||||||
}}
|
}}
|
||||||
strokeWidth={0}
|
strokeWidth={0}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M256 32a224 224 0 00-161.393 69.035h323.045A224 224 0 00256 32zM79.148 118.965a224 224 0 00-16.976 25.16H449.74a224 224 0 00-16.699-25.16H79.148zm-27.222 45.16A224 224 0 0043.3 186.25h425.271a224 224 0 00-8.586-22.125H51.926zM36.783 210.25a224 224 0 00-3.02 19.125h444.368a224 224 0 00-3.113-19.125H36.783zm-4.752 45.125A224 224 0 0032 256a224 224 0 00.64 16.5h446.534A224 224 0 00480 256a224 224 0 00-.021-.625H32.03zm4.67 45.125a224 224 0 003.395 15.125h431.578a224 224 0 003.861-15.125H36.701zm14.307 45.125a224 224 0 006.017 13.125H454.82a224 224 0 006.342-13.125H51.008zm26.316 45.125a224 224 0 009.04 11.125H425.86a224 224 0 008.727-11.125H77.324zm45.62 45.125A224 224 0 00136.247 445h239.89a224 224 0 0012.936-9.125h-266.13z"
|
d="M256 32a224 224 0 00-161.393 69.035h323.045A224 224 0 00256 32zM79.148 118.965a224 224 0 00-16.976 25.16H449.74a224 224 0 00-16.699-25.16H79.148zm-27.222 45.16A224 224 0 0043.3 186.25h425.271a224 224 0 00-8.586-22.125H51.926zM36.783 210.25a224 224 0 00-3.02 19.125h444.368a224 224 0 00-3.113-19.125H36.783zm-4.752 45.125A224 224 0 0032 256a224 224 0 00.64 16.5h446.534A224 224 0 00480 256a224 224 0 00-.021-.625H32.03zm4.67 45.125a224 224 0 003.395 15.125h431.578a224 224 0 003.861-15.125H36.701zm14.307 45.125a224 224 0 006.017 13.125H454.82a224 224 0 006.342-13.125H51.008zm26.316 45.125a224 224 0 009.04 11.125H425.86a224 224 0 008.727-11.125H77.324zm45.62 45.125A224 224 0 00136.247 445h239.89a224 224 0 0012.936-9.125h-266.13z"
|
||||||
fill={color || "currentColor"}
|
fill={color || 'currentColor'}
|
||||||
/>
|
/>
|
||||||
</svg>
|
</svg>
|
||||||
);
|
);
|
||||||
|
|
||||||
const Moon = ({ color, size = "1.5rem", ...props }) => (
|
const Moon = ({ color, size = '1.5rem', ...props }) => (
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 16 16"
|
viewBox="0 0 16 16"
|
||||||
style={{
|
style={{
|
||||||
height: size,
|
height: size,
|
||||||
width: size
|
width: size,
|
||||||
}}
|
}}
|
||||||
strokeWidth={0}
|
strokeWidth={0}
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<path
|
<path
|
||||||
d="M14.53 10.53a7 7 0 01-9.058-9.058A7.003 7.003 0 008 15a7.002 7.002 0 006.53-4.47z"
|
d="M14.53 10.53a7 7 0 01-9.058-9.058A7.003 7.003 0 008 15a7.002 7.002 0 006.53-4.47z"
|
||||||
fill={color || "currentColor"}
|
fill={color || 'currentColor'}
|
||||||
fillRule="evenodd"
|
fillRule="evenodd"
|
||||||
clipRule="evenodd"
|
clipRule="evenodd"
|
||||||
/>
|
/>
|
||||||
@@ -45,13 +43,13 @@ const Moon = ({ color, size = "1.5rem", ...props }) => (
|
|||||||
);
|
);
|
||||||
|
|
||||||
const iconMap = { dark: Moon, light: Sun };
|
const iconMap = { dark: Moon, light: Sun };
|
||||||
const outlineColor = { dark: "primary.300", light: "primary.600" };
|
const outlineColor = { dark: 'primary.300', light: 'primary.600' };
|
||||||
|
|
||||||
export const ColorModeToggle = forwardRef((props, ref) => {
|
export const ColorModeToggle = forwardRef((props, ref) => {
|
||||||
const { colorMode, toggleColorMode } = useColorMode();
|
const { colorMode, toggleColorMode } = useColorMode();
|
||||||
const Icon = iconMap[colorMode];
|
const Icon = iconMap[colorMode];
|
||||||
|
|
||||||
const label = `Switch to ${colorMode === "light" ? "dark" : "light"} mode`;
|
const label = `Switch to ${colorMode === 'light' ? 'dark' : 'light'} mode`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Button
|
<Button
|
||||||
@@ -63,13 +61,12 @@ export const ColorModeToggle = forwardRef((props, ref) => {
|
|||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
borderColor="transparent"
|
borderColor="transparent"
|
||||||
_hover={{
|
_hover={{
|
||||||
backgroundColor: "unset",
|
backgroundColor: 'unset',
|
||||||
borderColor: outlineColor[colorMode]
|
borderColor: outlineColor[colorMode],
|
||||||
}}
|
}}
|
||||||
color="current"
|
color="current"
|
||||||
px={4}
|
px={4}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<Icon />
|
<Icon />
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
|
@@ -1,21 +1,15 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useEffect } from "react";
|
import { useEffect } from 'react';
|
||||||
import { Text } from "@chakra-ui/core";
|
import { Text } from '@chakra-ui/core';
|
||||||
import { components } from "react-select";
|
import { components } from 'react-select';
|
||||||
import { ChakraSelect } from "app/components";
|
import { ChakraSelect } from 'app/components';
|
||||||
|
|
||||||
export const CommunitySelect = ({
|
export const CommunitySelect = ({ name, communities, onChange, register, unregister }) => {
|
||||||
name,
|
|
||||||
communities,
|
|
||||||
onChange,
|
|
||||||
register,
|
|
||||||
unregister
|
|
||||||
}) => {
|
|
||||||
const communitySelections = communities.map(c => {
|
const communitySelections = communities.map(c => {
|
||||||
return {
|
return {
|
||||||
value: c.community,
|
value: c.community,
|
||||||
label: c.display_name,
|
label: c.display_name,
|
||||||
description: c.description
|
description: c.description,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const Option = ({ label, data, ...props }) => {
|
const Option = ({ label, data, ...props }) => {
|
||||||
@@ -38,7 +32,7 @@ export const CommunitySelect = ({
|
|||||||
size="lg"
|
size="lg"
|
||||||
name={name}
|
name={name}
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
onChange({ field: name, value: e.value || "" });
|
onChange({ field: name, value: e.value || '' });
|
||||||
}}
|
}}
|
||||||
options={communitySelections}
|
options={communitySelections}
|
||||||
components={{ Option }}
|
components={{ Option }}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Button, Icon, Tooltip, useClipboard } from "@chakra-ui/core";
|
import { Button, Icon, Tooltip, useClipboard } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const CopyButton = ({ bg = "secondary", copyValue, ...props }) => {
|
export const CopyButton = ({ bg = 'secondary', copyValue, ...props }) => {
|
||||||
const { onCopy, hasCopied } = useClipboard(copyValue);
|
const { onCopy, hasCopied } = useClipboard(copyValue);
|
||||||
return (
|
return (
|
||||||
<Tooltip hasArrow label="Copy Output" placement="top">
|
<Tooltip hasArrow label="Copy Output" placement="top">
|
||||||
@@ -12,13 +12,8 @@ export const CopyButton = ({ bg = "secondary", copyValue, ...props }) => {
|
|||||||
zIndex="dropdown"
|
zIndex="dropdown"
|
||||||
onClick={onCopy}
|
onClick={onCopy}
|
||||||
mx={1}
|
mx={1}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
{hasCopied ? <Icon name="check" size="16px" /> : <Icon name="copy" size="16px" />}
|
||||||
{hasCopied ? (
|
|
||||||
<Icon name="check" size="16px" />
|
|
||||||
) : (
|
|
||||||
<Icon name="copy" size="16px" />
|
|
||||||
)}
|
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
);
|
);
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -11,36 +11,28 @@ import {
|
|||||||
Tag,
|
Tag,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useColorMode,
|
useColorMode,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
import { useConfig, useMedia } from "app/context";
|
import { useConfig, useMedia } from 'app/context';
|
||||||
import { CodeBlock } from "app/components";
|
import { CodeBlock } from 'app/components';
|
||||||
|
|
||||||
const prettyMediaSize = {
|
const prettyMediaSize = {
|
||||||
sm: "SMALL",
|
sm: 'SMALL',
|
||||||
md: "MEDIUM",
|
md: 'MEDIUM',
|
||||||
lg: "LARGE",
|
lg: 'LARGE',
|
||||||
xl: "X-LARGE"
|
xl: 'X-LARGE',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Debugger = () => {
|
export const Debugger = () => {
|
||||||
const {
|
const { isOpen: configOpen, onOpen: onConfigOpen, onClose: configClose } = useDisclosure();
|
||||||
isOpen: configOpen,
|
const { isOpen: themeOpen, onOpen: onThemeOpen, onClose: themeClose } = useDisclosure();
|
||||||
onOpen: onConfigOpen,
|
|
||||||
onClose: configClose
|
|
||||||
} = useDisclosure();
|
|
||||||
const {
|
|
||||||
isOpen: themeOpen,
|
|
||||||
onOpen: onThemeOpen,
|
|
||||||
onClose: themeClose
|
|
||||||
} = useDisclosure();
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const bg = { light: "white", dark: "black" };
|
const bg = { light: 'white', dark: 'black' };
|
||||||
const color = { light: "black", dark: "white" };
|
const color = { light: 'black', dark: 'white' };
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const { mediaSize } = useMedia();
|
const { mediaSize } = useMedia();
|
||||||
const borderColor = { light: "gray.100", dark: "gray.600" };
|
const borderColor = { light: 'gray.100', dark: 'gray.600' };
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Stack
|
<Stack
|
||||||
@@ -55,8 +47,7 @@ export const Debugger = () => {
|
|||||||
bottom={0}
|
bottom={0}
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
zIndex={1000}
|
zIndex={1000}
|
||||||
maxW="100%"
|
maxW="100%">
|
||||||
>
|
|
||||||
<Tag variantColor="gray">{colorMode.toUpperCase()}</Tag>
|
<Tag variantColor="gray">{colorMode.toUpperCase()}</Tag>
|
||||||
<Tag variantColor="teal">{prettyMediaSize[mediaSize]}</Tag>
|
<Tag variantColor="teal">{prettyMediaSize[mediaSize]}</Tag>
|
||||||
<Button size="sm" variantColor="cyan" onClick={onConfigOpen}>
|
<Button size="sm" variantColor="cyan" onClick={onConfigOpen}>
|
||||||
@@ -73,8 +64,7 @@ export const Debugger = () => {
|
|||||||
color={color[colorMode]}
|
color={color[colorMode]}
|
||||||
py={4}
|
py={4}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
maxW="90%"
|
maxW="90%">
|
||||||
>
|
|
||||||
<ModalHeader>Loaded Configuration</ModalHeader>
|
<ModalHeader>Loaded Configuration</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
@@ -89,8 +79,7 @@ export const Debugger = () => {
|
|||||||
color={color[colorMode]}
|
color={color[colorMode]}
|
||||||
py={4}
|
py={4}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
maxW="90%"
|
maxW="90%">
|
||||||
>
|
|
||||||
<ModalHeader>Loaded Theme</ModalHeader>
|
<ModalHeader>Loaded Theme</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@@ -1,18 +1,18 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useState } from "react";
|
import { useState } from 'react';
|
||||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
import { Flex, useColorMode } from '@chakra-ui/core';
|
||||||
import { FiCode } from "@meronex/icons/fi";
|
import { FiCode } from '@meronex/icons/fi';
|
||||||
import { GoLinkExternal } from "@meronex/icons/go";
|
import { GoLinkExternal } from '@meronex/icons/go';
|
||||||
import format from "string-format";
|
import format from 'string-format';
|
||||||
import { useConfig } from "app/context";
|
import { useConfig } from 'app/context';
|
||||||
import { FooterButton } from "./FooterButton";
|
import { FooterButton } from './FooterButton';
|
||||||
import { FooterContent } from "./FooterContent";
|
import { FooterContent } from './FooterContent';
|
||||||
|
|
||||||
format.extend(String.prototype, {});
|
format.extend(String.prototype, {});
|
||||||
|
|
||||||
const footerBg = { light: "blackAlpha.50", dark: "whiteAlpha.100" };
|
const footerBg = { light: 'blackAlpha.50', dark: 'whiteAlpha.100' };
|
||||||
const footerColor = { light: "black", dark: "white" };
|
const footerColor = { light: 'black', dark: 'white' };
|
||||||
const contentBorder = { light: "blackAlpha.100", dark: "whiteAlpha.200" };
|
const contentBorder = { light: 'blackAlpha.100', dark: 'whiteAlpha.200' };
|
||||||
|
|
||||||
export const Footer = () => {
|
export const Footer = () => {
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
@@ -21,23 +21,23 @@ export const Footer = () => {
|
|||||||
const [termsVisible, showTerms] = useState(false);
|
const [termsVisible, showTerms] = useState(false);
|
||||||
const [creditVisible, showCredit] = useState(false);
|
const [creditVisible, showCredit] = useState(false);
|
||||||
const handleCollapse = i => {
|
const handleCollapse = i => {
|
||||||
if (i === "help") {
|
if (i === 'help') {
|
||||||
showTerms(false);
|
showTerms(false);
|
||||||
showCredit(false);
|
showCredit(false);
|
||||||
showHelp(!helpVisible);
|
showHelp(!helpVisible);
|
||||||
} else if (i === "credit") {
|
} else if (i === 'credit') {
|
||||||
showTerms(false);
|
showTerms(false);
|
||||||
showHelp(false);
|
showHelp(false);
|
||||||
showCredit(!creditVisible);
|
showCredit(!creditVisible);
|
||||||
} else if (i === "terms") {
|
} else if (i === 'terms') {
|
||||||
showHelp(false);
|
showHelp(false);
|
||||||
showCredit(false);
|
showCredit(false);
|
||||||
showTerms(!termsVisible);
|
showTerms(!termsVisible);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const extUrl = config.web.external_link.url.includes("{primary_asn}")
|
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.format({ primary_asn: config.primary_asn })
|
||||||
: config.web.external_link.url || "/";
|
: config.web.external_link.url || '/';
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{config.web.help_menu.enable && (
|
{config.web.help_menu.enable && (
|
||||||
@@ -80,23 +80,20 @@ export const Footer = () => {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
bg={footerBg[colorMode]}
|
bg={footerBg[colorMode]}
|
||||||
color={footerColor[colorMode]}
|
color={footerColor[colorMode]}
|
||||||
justifyContent="space-between"
|
justifyContent="space-between">
|
||||||
>
|
|
||||||
{config.web.terms.enable && (
|
{config.web.terms.enable && (
|
||||||
<FooterButton
|
<FooterButton
|
||||||
side="left"
|
side="left"
|
||||||
onClick={() => handleCollapse("terms")}
|
onClick={() => handleCollapse('terms')}
|
||||||
aria-label={config.web.terms.title}
|
aria-label={config.web.terms.title}>
|
||||||
>
|
|
||||||
{config.web.terms.title}
|
{config.web.terms.title}
|
||||||
</FooterButton>
|
</FooterButton>
|
||||||
)}
|
)}
|
||||||
{config.web.help_menu.enable && (
|
{config.web.help_menu.enable && (
|
||||||
<FooterButton
|
<FooterButton
|
||||||
side="left"
|
side="left"
|
||||||
onClick={() => handleCollapse("help")}
|
onClick={() => handleCollapse('help')}
|
||||||
aria-label={config.web.help_menu.title}
|
aria-label={config.web.help_menu.title}>
|
||||||
>
|
|
||||||
{config.web.help_menu.title}
|
{config.web.help_menu.title}
|
||||||
</FooterButton>
|
</FooterButton>
|
||||||
)}
|
)}
|
||||||
@@ -111,9 +108,8 @@ export const Footer = () => {
|
|||||||
{config.web.credit.enable && (
|
{config.web.credit.enable && (
|
||||||
<FooterButton
|
<FooterButton
|
||||||
side="right"
|
side="right"
|
||||||
onClick={() => handleCollapse("credit")}
|
onClick={() => handleCollapse('credit')}
|
||||||
aria-label="Powered by hyperglass"
|
aria-label="Powered by hyperglass">
|
||||||
>
|
|
||||||
<FiCode />
|
<FiCode />
|
||||||
</FooterButton>
|
</FooterButton>
|
||||||
)}
|
)}
|
||||||
@@ -126,8 +122,7 @@ export const Footer = () => {
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
rightIcon={GoLinkExternal}
|
rightIcon={GoLinkExternal}
|
||||||
size="xs"
|
size="xs">
|
||||||
>
|
|
||||||
{config.web.external_link.title}
|
{config.web.external_link.title}
|
||||||
</FooterButton>
|
</FooterButton>
|
||||||
)}
|
)}
|
||||||
|
@@ -1,29 +1,26 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Button, Flex } from "@chakra-ui/core";
|
import { Button, Flex } from '@chakra-ui/core';
|
||||||
import { motion } from "framer-motion";
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
const AnimatedFlex = motion.custom(Flex);
|
const AnimatedFlex = motion.custom(Flex);
|
||||||
|
|
||||||
export const FooterButton = React.forwardRef(
|
export const FooterButton = React.forwardRef(({ onClick, side, children, ...props }, ref) => {
|
||||||
({ onClick, side, children, ...props }, ref) => {
|
return (
|
||||||
return (
|
<AnimatedFlex
|
||||||
<AnimatedFlex
|
p={0}
|
||||||
p={0}
|
w="auto"
|
||||||
w="auto"
|
ref={ref}
|
||||||
ref={ref}
|
flexGrow={0}
|
||||||
flexGrow={0}
|
float={side}
|
||||||
float={side}
|
flexShrink={0}
|
||||||
flexShrink={0}
|
maxWidth="100%"
|
||||||
maxWidth="100%"
|
flexBasis="auto"
|
||||||
flexBasis="auto"
|
initial={{ opacity: 0 }}
|
||||||
initial={{ opacity: 0 }}
|
animate={{ opacity: 1 }}
|
||||||
animate={{ opacity: 1 }}
|
transition={{ duration: 0.6 }}>
|
||||||
transition={{ duration: 0.6 }}
|
<Button size="xs" variant="ghost" onClick={onClick} {...props}>
|
||||||
>
|
{children}
|
||||||
<Button size="xs" variant="ghost" onClick={onClick} {...props}>
|
</Button>
|
||||||
{children}
|
</AnimatedFlex>
|
||||||
</Button>
|
);
|
||||||
</AnimatedFlex>
|
});
|
||||||
);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import { Box, Collapse } from "@chakra-ui/core";
|
import { Box, Collapse } from '@chakra-ui/core';
|
||||||
import { Markdown } from "app/components/Markdown";
|
import { Markdown } from 'app/components/Markdown';
|
||||||
|
|
||||||
export const FooterContent = forwardRef(
|
export const FooterContent = forwardRef(
|
||||||
({ isOpen = false, content, side = "left", title, ...props }, ref) => {
|
({ isOpen = false, content, side = 'left', title, ...props }, ref) => {
|
||||||
return (
|
return (
|
||||||
<Collapse
|
<Collapse
|
||||||
px={6}
|
px={6}
|
||||||
@@ -16,13 +16,12 @@ export const FooterContent = forwardRef(
|
|||||||
maxWidth="100%"
|
maxWidth="100%"
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
flexBasis="auto"
|
flexBasis="auto"
|
||||||
justifyContent={side === "left" ? "flex-start" : "flex-end"}
|
justifyContent={side === 'left' ? 'flex-start' : 'flex-end'}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<Box textAlign={side}>
|
<Box textAlign={side}>
|
||||||
<Markdown content={content} />
|
<Markdown content={content} />
|
||||||
</Box>
|
</Box>
|
||||||
</Collapse>
|
</Collapse>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1 +1 @@
|
|||||||
export * from "./Footer";
|
export * from './Footer';
|
||||||
|
@@ -1,13 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import {
|
import { Flex, FormControl, FormLabel, FormErrorMessage, useColorMode } from '@chakra-ui/core';
|
||||||
Flex,
|
|
||||||
FormControl,
|
|
||||||
FormLabel,
|
|
||||||
FormErrorMessage,
|
|
||||||
useColorMode
|
|
||||||
} from "@chakra-ui/core";
|
|
||||||
|
|
||||||
const labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" };
|
const labelColor = { dark: 'whiteAlpha.700', light: 'blackAlpha.700' };
|
||||||
|
|
||||||
export const FormField = ({
|
export const FormField = ({
|
||||||
label,
|
label,
|
||||||
@@ -28,14 +22,13 @@ export const FormField = ({
|
|||||||
<FormControl
|
<FormControl
|
||||||
as={Flex}
|
as={Flex}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
flex={["1 0 100%", "1 0 100%", "1 0 33.33%", "1 0 33.33%"]}
|
flex={['1 0 100%', '1 0 100%', '1 0 33.33%', '1 0 33.33%']}
|
||||||
w="100%"
|
w="100%"
|
||||||
maxW="100%"
|
maxW="100%"
|
||||||
mx={2}
|
mx={2}
|
||||||
my={[2, 2, 4, 4]}
|
my={[2, 2, 4, 4]}
|
||||||
isInvalid={error && error.message}
|
isInvalid={error && error.message}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<FormLabel
|
<FormLabel
|
||||||
htmlFor={name}
|
htmlFor={name}
|
||||||
color={labelColor[colorMode]}
|
color={labelColor[colorMode]}
|
||||||
@@ -44,8 +37,7 @@ export const FormField = ({
|
|||||||
display="flex"
|
display="flex"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="space-between"
|
justifyContent="space-between"
|
||||||
pr={0}
|
pr={0}>
|
||||||
>
|
|
||||||
{label}
|
{label}
|
||||||
{labelAddOn || null}
|
{labelAddOn || null}
|
||||||
</FormLabel>
|
</FormLabel>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -9,13 +9,13 @@ import {
|
|||||||
ModalBody,
|
ModalBody,
|
||||||
ModalCloseButton,
|
ModalCloseButton,
|
||||||
useColorMode,
|
useColorMode,
|
||||||
useDisclosure
|
useDisclosure,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
import { Markdown } from "app/components";
|
import { Markdown } from 'app/components';
|
||||||
import { motion } from "framer-motion";
|
import { motion } from 'framer-motion';
|
||||||
|
|
||||||
const bg = { light: "white", dark: "black" };
|
const bg = { light: 'white', dark: 'black' };
|
||||||
const color = { light: "black", dark: "white" };
|
const color = { light: 'black', dark: 'white' };
|
||||||
|
|
||||||
const AnimatedModalContent = motion.custom(ModalContent);
|
const AnimatedModalContent = motion.custom(ModalContent);
|
||||||
const AnimatedModalOverlay = motion.custom(ModalOverlay);
|
const AnimatedModalOverlay = motion.custom(ModalOverlay);
|
||||||
@@ -36,8 +36,7 @@ export const Greeting = ({ greetingConfig, content, onClickThrough }) => {
|
|||||||
size="full"
|
size="full"
|
||||||
isCentered
|
isCentered
|
||||||
closeOnOverlayClick={!greetingConfig.required}
|
closeOnOverlayClick={!greetingConfig.required}
|
||||||
closeOnEsc={!greetingConfig.required}
|
closeOnEsc={!greetingConfig.required}>
|
||||||
>
|
|
||||||
<AnimatedModalOverlay
|
<AnimatedModalOverlay
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
@@ -51,8 +50,7 @@ export const Greeting = ({ greetingConfig, content, onClickThrough }) => {
|
|||||||
color={color[colorMode]}
|
color={color[colorMode]}
|
||||||
py={4}
|
py={4}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
maxW={["95%", "75%", "75%", "75%"]}
|
maxW={['95%', '75%', '75%', '75%']}>
|
||||||
>
|
|
||||||
<ModalHeader>{greetingConfig.title}</ModalHeader>
|
<ModalHeader>{greetingConfig.title}</ModalHeader>
|
||||||
{!greetingConfig.required && <ModalCloseButton />}
|
{!greetingConfig.required && <ModalCloseButton />}
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@@ -1,54 +1,54 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
import { Flex, useColorMode } from '@chakra-ui/core';
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { useConfig, useHyperglassState, useMedia } from "app/context";
|
import { useConfig, useHyperglassState, useMedia } from 'app/context';
|
||||||
import { Title, ResetButton, ColorModeToggle } from "app/components";
|
import { Title, ResetButton, ColorModeToggle } from 'app/components';
|
||||||
|
|
||||||
const titleVariants = {
|
const titleVariants = {
|
||||||
sm: {
|
sm: {
|
||||||
fullSize: { scale: 1, marginLeft: 0 },
|
fullSize: { scale: 1, marginLeft: 0 },
|
||||||
smallLogo: { marginLeft: "auto" },
|
smallLogo: { marginLeft: 'auto' },
|
||||||
smallText: { marginLeft: "auto" }
|
smallText: { marginLeft: 'auto' },
|
||||||
},
|
},
|
||||||
md: {
|
md: {
|
||||||
fullSize: { scale: 1 },
|
fullSize: { scale: 1 },
|
||||||
smallLogo: { scale: 0.5 },
|
smallLogo: { scale: 0.5 },
|
||||||
smallText: { scale: 0.8 }
|
smallText: { scale: 0.8 },
|
||||||
},
|
},
|
||||||
lg: {
|
lg: {
|
||||||
fullSize: { scale: 1 },
|
fullSize: { scale: 1 },
|
||||||
smallLogo: { scale: 0.5 },
|
smallLogo: { scale: 0.5 },
|
||||||
smallText: { scale: 0.8 }
|
smallText: { scale: 0.8 },
|
||||||
},
|
},
|
||||||
xl: {
|
xl: {
|
||||||
fullSize: { scale: 1 },
|
fullSize: { scale: 1 },
|
||||||
smallLogo: { scale: 0.5 },
|
smallLogo: { scale: 0.5 },
|
||||||
smallText: { scale: 0.8 }
|
smallText: { scale: 0.8 },
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const bg = { light: "white", dark: "black" };
|
const bg = { light: 'white', dark: 'black' };
|
||||||
const headerTransition = {
|
const headerTransition = {
|
||||||
type: "spring",
|
type: 'spring',
|
||||||
ease: "anticipate",
|
ease: 'anticipate',
|
||||||
damping: 15,
|
damping: 15,
|
||||||
stiffness: 100
|
stiffness: 100,
|
||||||
};
|
};
|
||||||
const titleJustify = {
|
const titleJustify = {
|
||||||
true: ["flex-end", "flex-end", "center", "center"],
|
true: ['flex-end', 'flex-end', 'center', 'center'],
|
||||||
false: ["flex-start", "flex-start", "center", "center"]
|
false: ['flex-start', 'flex-start', 'center', 'center'],
|
||||||
};
|
};
|
||||||
const titleHeight = {
|
const titleHeight = {
|
||||||
true: null,
|
true: null,
|
||||||
false: [null, "20vh", "20vh", "20vh"]
|
false: [null, '20vh', '20vh', '20vh'],
|
||||||
};
|
};
|
||||||
const resetButtonMl = { true: [null, 2, 2, 2], false: null };
|
const resetButtonMl = { true: [null, 2, 2, 2], false: null };
|
||||||
|
|
||||||
const widthMap = {
|
const widthMap = {
|
||||||
text_only: "100%",
|
text_only: '100%',
|
||||||
logo_only: ["90%", "90%", "50%", "50%"],
|
logo_only: ['90%', '90%', '50%', '50%'],
|
||||||
logo_subtitle: ["90%", "90%", "50%", "50%"],
|
logo_subtitle: ['90%', '90%', '50%', '50%'],
|
||||||
all: ["90%", "90%", "50%", "50%"]
|
all: ['90%', '90%', '50%', '50%'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Header = ({ layoutRef, ...props }) => {
|
export const Header = ({ layoutRef, ...props }) => {
|
||||||
@@ -66,17 +66,13 @@ export const Header = ({ layoutRef, ...props }) => {
|
|||||||
<AnimatedFlex
|
<AnimatedFlex
|
||||||
layoutTransition={headerTransition}
|
layoutTransition={headerTransition}
|
||||||
initial={{ opacity: 0, x: -50 }}
|
initial={{ opacity: 0, x: -50 }}
|
||||||
animate={{ opacity: 1, x: 0, width: "unset" }}
|
animate={{ opacity: 1, x: 0, width: 'unset' }}
|
||||||
exit={{ opacity: 0, x: -50 }}
|
exit={{ opacity: 0, x: -50 }}
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
mb={[null, "auto"]}
|
mb={[null, 'auto']}
|
||||||
ml={resetButtonMl[isSubmitting]}
|
ml={resetButtonMl[isSubmitting]}
|
||||||
display={isSubmitting ? "flex" : "none"}
|
display={isSubmitting ? 'flex' : 'none'}>
|
||||||
>
|
<AnimatedResetButton isSubmitting={isSubmitting} onClick={handleFormReset} />
|
||||||
<AnimatedResetButton
|
|
||||||
isSubmitting={isSubmitting}
|
|
||||||
onClick={handleFormReset}
|
|
||||||
/>
|
|
||||||
</AnimatedFlex>
|
</AnimatedFlex>
|
||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
);
|
);
|
||||||
@@ -84,25 +80,22 @@ export const Header = ({ layoutRef, ...props }) => {
|
|||||||
<AnimatedFlex
|
<AnimatedFlex
|
||||||
key="title"
|
key="title"
|
||||||
px={1}
|
px={1}
|
||||||
alignItems={
|
alignItems={isSubmitting ? 'center' : ['center', 'center', 'flex-end', 'flex-end']}
|
||||||
isSubmitting ? "center" : ["center", "center", "flex-end", "flex-end"]
|
|
||||||
}
|
|
||||||
positionTransition={headerTransition}
|
positionTransition={headerTransition}
|
||||||
initial={{ scale: 0.5 }}
|
initial={{ scale: 0.5 }}
|
||||||
animate={
|
animate={
|
||||||
isSubmitting && web.text.title_mode === "text_only"
|
isSubmitting && web.text.title_mode === 'text_only'
|
||||||
? "smallText"
|
? 'smallText'
|
||||||
: isSubmitting && web.text.title_mode !== "text_only"
|
: isSubmitting && web.text.title_mode !== 'text_only'
|
||||||
? "smallLogo"
|
? 'smallLogo'
|
||||||
: "fullSize"
|
: 'fullSize'
|
||||||
}
|
}
|
||||||
variants={titleVariants[mediaSize]}
|
variants={titleVariants[mediaSize]}
|
||||||
justifyContent={titleJustify[isSubmitting]}
|
justifyContent={titleJustify[isSubmitting]}
|
||||||
mt={[null, isSubmitting ? null : "auto"]}
|
mt={[null, isSubmitting ? null : 'auto']}
|
||||||
maxW={widthMap[web.text.title_mode]}
|
maxW={widthMap[web.text.title_mode]}
|
||||||
flex="1 0 0"
|
flex="1 0 0"
|
||||||
minH={titleHeight[isSubmitting]}
|
minH={titleHeight[isSubmitting]}>
|
||||||
>
|
|
||||||
<Title isSubmitting={isSubmitting} onClick={handleFormReset} />
|
<Title isSubmitting={isSubmitting} onClick={handleFormReset} />
|
||||||
</AnimatedFlex>
|
</AnimatedFlex>
|
||||||
);
|
);
|
||||||
@@ -113,9 +106,8 @@ export const Header = ({ layoutRef, ...props }) => {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
initial={{ opacity: 0 }}
|
initial={{ opacity: 0 }}
|
||||||
animate={{ opacity: 1 }}
|
animate={{ opacity: 1 }}
|
||||||
mb={[null, "auto"]}
|
mb={[null, 'auto']}
|
||||||
mr={isSubmitting ? null : 2}
|
mr={isSubmitting ? null : 2}>
|
||||||
>
|
|
||||||
<ColorModeToggle />
|
<ColorModeToggle />
|
||||||
</AnimatedFlex>
|
</AnimatedFlex>
|
||||||
);
|
);
|
||||||
@@ -124,14 +116,14 @@ export const Header = ({ layoutRef, ...props }) => {
|
|||||||
sm: [title, resetButton, colorModeToggle],
|
sm: [title, resetButton, colorModeToggle],
|
||||||
md: [resetButton, title, colorModeToggle],
|
md: [resetButton, title, colorModeToggle],
|
||||||
lg: [resetButton, title, colorModeToggle],
|
lg: [resetButton, title, colorModeToggle],
|
||||||
xl: [resetButton, title, colorModeToggle]
|
xl: [resetButton, title, colorModeToggle],
|
||||||
},
|
},
|
||||||
true: {
|
true: {
|
||||||
sm: [resetButton, colorModeToggle, title],
|
sm: [resetButton, colorModeToggle, title],
|
||||||
md: [resetButton, title, colorModeToggle],
|
md: [resetButton, title, colorModeToggle],
|
||||||
lg: [resetButton, title, colorModeToggle],
|
lg: [resetButton, title, colorModeToggle],
|
||||||
xl: [resetButton, title, colorModeToggle]
|
xl: [resetButton, title, colorModeToggle],
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
@@ -142,16 +134,14 @@ export const Header = ({ layoutRef, ...props }) => {
|
|||||||
flex="0 1 auto"
|
flex="0 1 auto"
|
||||||
bg={bg[colorMode]}
|
bg={bg[colorMode]}
|
||||||
color="gray.500"
|
color="gray.500"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
w="100%"
|
w="100%"
|
||||||
mx="auto"
|
mx="auto"
|
||||||
pt={6}
|
pt={6}
|
||||||
justify="space-between"
|
justify="space-between"
|
||||||
flex="1 0 auto"
|
flex="1 0 auto"
|
||||||
alignItems={isSubmitting ? "center" : "flex-start"}
|
alignItems={isSubmitting ? 'center' : 'flex-start'}>
|
||||||
>
|
|
||||||
{layout[isSubmitting][mediaSize]}
|
{layout[isSubmitting][mediaSize]}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
IconButton,
|
IconButton,
|
||||||
Modal,
|
Modal,
|
||||||
@@ -9,10 +9,10 @@ import {
|
|||||||
ModalCloseButton,
|
ModalCloseButton,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
useColorMode,
|
useColorMode,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { Markdown } from "app/components";
|
import { Markdown } from 'app/components';
|
||||||
|
|
||||||
const AnimatedIcon = motion.custom(IconButton);
|
const AnimatedIcon = motion.custom(IconButton);
|
||||||
|
|
||||||
@@ -20,11 +20,11 @@ export const HelpModal = ({ item, name }) => {
|
|||||||
const { isOpen, onOpen, onClose } = useDisclosure();
|
const { isOpen, onOpen, onClose } = useDisclosure();
|
||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const bg = { light: "whiteFaded.50", dark: "blackFaded.800" };
|
const bg = { light: 'whiteFaded.50', dark: 'blackFaded.800' };
|
||||||
const color = { light: "black", dark: "white" };
|
const color = { light: 'black', dark: 'white' };
|
||||||
const iconColor = {
|
const iconColor = {
|
||||||
light: colors.primary[500],
|
light: colors.primary[500],
|
||||||
dark: colors.primary[300]
|
dark: colors.primary[300],
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -53,12 +53,7 @@ export const HelpModal = ({ item, name }) => {
|
|||||||
</AnimatePresence>
|
</AnimatePresence>
|
||||||
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
<Modal isOpen={isOpen} onClose={onClose} size="xl">
|
||||||
<ModalOverlay />
|
<ModalOverlay />
|
||||||
<ModalContent
|
<ModalContent bg={bg[colorMode]} color={color[colorMode]} py={4} borderRadius="md">
|
||||||
bg={bg[colorMode]}
|
|
||||||
color={color[colorMode]}
|
|
||||||
py={4}
|
|
||||||
borderRadius="md"
|
|
||||||
>
|
|
||||||
<ModalHeader>{item.params.title}</ModalHeader>
|
<ModalHeader>{item.params.title}</ModalHeader>
|
||||||
<ModalCloseButton />
|
<ModalCloseButton />
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef, useState, useEffect } from "react";
|
import { forwardRef, useState, useEffect } from 'react';
|
||||||
import { Box, Flex } from "@chakra-ui/core";
|
import { Box, Flex } from '@chakra-ui/core';
|
||||||
import { useForm } from "react-hook-form";
|
import { useForm } from 'react-hook-form';
|
||||||
import { intersectionWith, isEqual } from "lodash";
|
import { intersectionWith, isEqual } from 'lodash';
|
||||||
import * as yup from "yup";
|
import * as yup from 'yup';
|
||||||
import format from "string-format";
|
import format from 'string-format';
|
||||||
import {
|
import {
|
||||||
FormField,
|
FormField,
|
||||||
HelpModal,
|
HelpModal,
|
||||||
@@ -14,9 +14,9 @@ import {
|
|||||||
CommunitySelect,
|
CommunitySelect,
|
||||||
QueryVrf,
|
QueryVrf,
|
||||||
ResolvedTarget,
|
ResolvedTarget,
|
||||||
SubmitButton
|
SubmitButton,
|
||||||
} from "app/components";
|
} from 'app/components';
|
||||||
import { useConfig } from "app/context";
|
import { useConfig } from 'app/context';
|
||||||
|
|
||||||
format.extend(String.prototype, {});
|
format.extend(String.prototype, {});
|
||||||
|
|
||||||
@@ -27,20 +27,16 @@ const formSchema = config =>
|
|||||||
.of(yup.string())
|
.of(yup.string())
|
||||||
.required(
|
.required(
|
||||||
config.messages.no_input.format({
|
config.messages.no_input.format({
|
||||||
field: config.web.text.query_location
|
field: config.web.text.query_location,
|
||||||
})
|
}),
|
||||||
),
|
),
|
||||||
query_type: yup
|
query_type: yup
|
||||||
.string()
|
.string()
|
||||||
.required(
|
.required(config.messages.no_input.format({ field: config.web.text.query_type })),
|
||||||
config.messages.no_input.format({ field: config.web.text.query_type })
|
|
||||||
),
|
|
||||||
query_vrf: yup.string(),
|
query_vrf: yup.string(),
|
||||||
query_target: yup
|
query_target: yup
|
||||||
.string()
|
.string()
|
||||||
.required(
|
.required(config.messages.no_input.format({ field: config.web.text.query_target })),
|
||||||
config.messages.no_input.format({ field: config.web.text.query_target })
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const FormRow = ({ children, ...props }) => (
|
const FormRow = ({ children, ...props }) => (
|
||||||
@@ -48,38 +44,27 @@ const FormRow = ({ children, ...props }) => (
|
|||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
flexWrap="wrap"
|
flexWrap="wrap"
|
||||||
w="100%"
|
w="100%"
|
||||||
justifyContent={["center", "center", "space-between", "space-between"]}
|
justifyContent={['center', 'center', 'space-between', 'space-between']}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const HyperglassForm = forwardRef(
|
export const HyperglassForm = forwardRef(
|
||||||
(
|
({ isSubmitting, setSubmitting, setFormData, greetingAck, setGreetingAck, ...props }, ref) => {
|
||||||
{
|
|
||||||
isSubmitting,
|
|
||||||
setSubmitting,
|
|
||||||
setFormData,
|
|
||||||
greetingAck,
|
|
||||||
setGreetingAck,
|
|
||||||
...props
|
|
||||||
},
|
|
||||||
ref
|
|
||||||
) => {
|
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const { handleSubmit, register, unregister, setValue, errors } = useForm({
|
const { handleSubmit, register, unregister, setValue, errors } = useForm({
|
||||||
validationSchema: formSchema(config),
|
validationSchema: formSchema(config),
|
||||||
defaultValues: { query_vrf: "default", query_target: "" }
|
defaultValues: { query_vrf: 'default', query_target: '' },
|
||||||
});
|
});
|
||||||
|
|
||||||
const [queryLocation, setQueryLocation] = useState([]);
|
const [queryLocation, setQueryLocation] = useState([]);
|
||||||
const [queryType, setQueryType] = useState("");
|
const [queryType, setQueryType] = useState('');
|
||||||
const [queryVrf, setQueryVrf] = useState("");
|
const [queryVrf, setQueryVrf] = useState('');
|
||||||
const [queryTarget, setQueryTarget] = useState("");
|
const [queryTarget, setQueryTarget] = useState('');
|
||||||
const [availVrfs, setAvailVrfs] = useState([]);
|
const [availVrfs, setAvailVrfs] = useState([]);
|
||||||
const [fqdnTarget, setFqdnTarget] = useState("");
|
const [fqdnTarget, setFqdnTarget] = useState('');
|
||||||
const [displayTarget, setDisplayTarget] = useState("");
|
const [displayTarget, setDisplayTarget] = useState('');
|
||||||
const [families, setFamilies] = useState([]);
|
const [families, setFamilies] = useState([]);
|
||||||
const onSubmit = values => {
|
const onSubmit = values => {
|
||||||
if (!greetingAck && config.web.greeting.required) {
|
if (!greetingAck && config.web.greeting.required) {
|
||||||
@@ -100,7 +85,7 @@ export const HyperglassForm = forwardRef(
|
|||||||
config.devices[loc].vrfs.map(vrf => {
|
config.devices[loc].vrfs.map(vrf => {
|
||||||
locVrfs.push({
|
locVrfs.push({
|
||||||
label: vrf.display_name,
|
label: vrf.display_name,
|
||||||
value: vrf.id
|
value: vrf.id,
|
||||||
});
|
});
|
||||||
deviceVrfs.push([{ id: vrf.id, ipv4: vrf.ipv4, ipv6: vrf.ipv6 }]);
|
deviceVrfs.push([{ id: vrf.id, ipv4: vrf.ipv4, ipv6: vrf.ipv6 }]);
|
||||||
});
|
});
|
||||||
@@ -109,9 +94,7 @@ export const HyperglassForm = forwardRef(
|
|||||||
|
|
||||||
const intersecting = intersectionWith(...allVrfs, isEqual);
|
const intersecting = intersectionWith(...allVrfs, isEqual);
|
||||||
setAvailVrfs(intersecting);
|
setAvailVrfs(intersecting);
|
||||||
!intersecting.includes(queryVrf) &&
|
!intersecting.includes(queryVrf) && queryVrf !== 'default' && setQueryVrf('default');
|
||||||
queryVrf !== "default" &&
|
|
||||||
setQueryVrf("default");
|
|
||||||
|
|
||||||
let ipv4 = 0;
|
let ipv4 = 0;
|
||||||
let ipv6 = 0;
|
let ipv6 = 0;
|
||||||
@@ -120,7 +103,7 @@ export const HyperglassForm = forwardRef(
|
|||||||
deviceVrfs
|
deviceVrfs
|
||||||
.filter(v => intersecting.every(i => i.id === v.id))
|
.filter(v => intersecting.every(i => i.id === v.id))
|
||||||
.reduce((a, b) => a.concat(b))
|
.reduce((a, b) => a.concat(b))
|
||||||
.filter(v => v.id === "default")
|
.filter(v => v.id === 'default')
|
||||||
.map(v => {
|
.map(v => {
|
||||||
v.ipv4 === true && ipv4++;
|
v.ipv4 === true && ipv4++;
|
||||||
v.ipv6 === true && ipv6++;
|
v.ipv6 === true && ipv6++;
|
||||||
@@ -138,13 +121,13 @@ export const HyperglassForm = forwardRef(
|
|||||||
|
|
||||||
const handleChange = e => {
|
const handleChange = e => {
|
||||||
setValue(e.field, e.value);
|
setValue(e.field, e.value);
|
||||||
e.field === "query_location"
|
e.field === 'query_location'
|
||||||
? handleLocChange(e)
|
? handleLocChange(e)
|
||||||
: e.field === "query_type"
|
: e.field === 'query_type'
|
||||||
? setQueryType(e.value)
|
? setQueryType(e.value)
|
||||||
: e.field === "query_vrf"
|
: e.field === 'query_vrf'
|
||||||
? setQueryVrf(e.value)
|
? setQueryVrf(e.value)
|
||||||
: e.field === "query_target"
|
: e.field === 'query_target'
|
||||||
? setQueryTarget(e.value)
|
? setQueryTarget(e.value)
|
||||||
: null;
|
: null;
|
||||||
};
|
};
|
||||||
@@ -152,37 +135,35 @@ export const HyperglassForm = forwardRef(
|
|||||||
const vrfContent = config.content.vrf[queryVrf]?.[queryType];
|
const vrfContent = config.content.vrf[queryVrf]?.[queryType];
|
||||||
|
|
||||||
const validFqdnQueryType =
|
const validFqdnQueryType =
|
||||||
["ping", "traceroute", "bgp_route"].includes(queryType) &&
|
['ping', 'traceroute', 'bgp_route'].includes(queryType) &&
|
||||||
fqdnTarget &&
|
fqdnTarget &&
|
||||||
queryVrf === "default"
|
queryVrf === 'default'
|
||||||
? fqdnTarget
|
? fqdnTarget
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
register({ name: "query_location" });
|
register({ name: 'query_location' });
|
||||||
register({ name: "query_type" });
|
register({ name: 'query_type' });
|
||||||
register({ name: "query_vrf" });
|
register({ name: 'query_vrf' });
|
||||||
}, [register]);
|
}, [register]);
|
||||||
Object.keys(errors).length >= 1 && console.error(errors);
|
Object.keys(errors).length >= 1 && console.error(errors);
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box
|
||||||
as="form"
|
as="form"
|
||||||
onSubmit={handleSubmit(onSubmit)}
|
onSubmit={handleSubmit(onSubmit)}
|
||||||
maxW={["100%", "100%", "75%", "75%"]}
|
maxW={['100%', '100%', '75%', '75%']}
|
||||||
w="100%"
|
w="100%"
|
||||||
p={0}
|
p={0}
|
||||||
mx="auto"
|
mx="auto"
|
||||||
my={4}
|
my={4}
|
||||||
textAlign="left"
|
textAlign="left"
|
||||||
ref={ref}
|
ref={ref}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<FormRow>
|
<FormRow>
|
||||||
<FormField
|
<FormField
|
||||||
label={config.web.text.query_location}
|
label={config.web.text.query_location}
|
||||||
name="query_location"
|
name="query_location"
|
||||||
error={errors.query_location}
|
error={errors.query_location}>
|
||||||
>
|
|
||||||
<QueryLocation
|
<QueryLocation
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
locations={config.networks}
|
locations={config.networks}
|
||||||
@@ -193,10 +174,7 @@ export const HyperglassForm = forwardRef(
|
|||||||
label={config.web.text.query_type}
|
label={config.web.text.query_type}
|
||||||
name="query_type"
|
name="query_type"
|
||||||
error={errors.query_type}
|
error={errors.query_type}
|
||||||
labelAddOn={
|
labelAddOn={vrfContent && <HelpModal item={vrfContent} name="query_type" />}>
|
||||||
vrfContent && <HelpModal item={vrfContent} name="query_type" />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<QueryType
|
<QueryType
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
queryTypes={config.queries.list}
|
queryTypes={config.queries.list}
|
||||||
@@ -206,11 +184,7 @@ export const HyperglassForm = forwardRef(
|
|||||||
</FormRow>
|
</FormRow>
|
||||||
<FormRow>
|
<FormRow>
|
||||||
{availVrfs.length > 1 && (
|
{availVrfs.length > 1 && (
|
||||||
<FormField
|
<FormField label={config.web.text.query_vrf} name="query_vrf" error={errors.query_vrf}>
|
||||||
label={config.web.text.query_vrf}
|
|
||||||
name="query_vrf"
|
|
||||||
error={errors.query_vrf}
|
|
||||||
>
|
|
||||||
<QueryVrf
|
<QueryVrf
|
||||||
label={config.web.text.query_vrf}
|
label={config.web.text.query_vrf}
|
||||||
vrfs={availVrfs}
|
vrfs={availVrfs}
|
||||||
@@ -233,10 +207,8 @@ export const HyperglassForm = forwardRef(
|
|||||||
availVrfs={availVrfs}
|
availVrfs={availVrfs}
|
||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
}
|
}>
|
||||||
>
|
{queryType === 'bgp_community' && config.queries.bgp_community.mode === 'select' ? (
|
||||||
{queryType === "bgp_community" &&
|
|
||||||
config.queries.bgp_community.mode === "select" ? (
|
|
||||||
<CommunitySelect
|
<CommunitySelect
|
||||||
label={config.queries.bgp_community.display_name}
|
label={config.queries.bgp_community.display_name}
|
||||||
name="query_target"
|
name="query_target"
|
||||||
@@ -251,9 +223,7 @@ export const HyperglassForm = forwardRef(
|
|||||||
placeholder={config.web.text.query_target}
|
placeholder={config.web.text.query_target}
|
||||||
register={register}
|
register={register}
|
||||||
unregister={unregister}
|
unregister={unregister}
|
||||||
resolveTarget={["ping", "traceroute", "bgp_route"].includes(
|
resolveTarget={['ping', 'traceroute', 'bgp_route'].includes(queryType)}
|
||||||
queryType
|
|
||||||
)}
|
|
||||||
value={queryTarget}
|
value={queryTarget}
|
||||||
setFqdn={setFqdnTarget}
|
setFqdn={setFqdnTarget}
|
||||||
setTarget={handleChange}
|
setTarget={handleChange}
|
||||||
@@ -271,12 +241,11 @@ export const HyperglassForm = forwardRef(
|
|||||||
my={2}
|
my={2}
|
||||||
mr={[0, 0, 2, 2]}
|
mr={[0, 0, 2, 2]}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
flex="0 0 0"
|
flex="0 0 0">
|
||||||
>
|
|
||||||
<SubmitButton isLoading={isSubmitting} />
|
<SubmitButton isLoading={isSubmitting} />
|
||||||
</Flex>
|
</Flex>
|
||||||
</FormRow>
|
</FormRow>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
import { Flex, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const Label = forwardRef(
|
export const Label = forwardRef(
|
||||||
({ value, label, labelColor, valueBg, valueColor, ...props }, ref) => {
|
({ value, label, labelColor, valueBg, valueColor, ...props }, ref) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const _labelColor = { dark: "whiteAlpha.700", light: "blackAlpha.700" };
|
const _labelColor = { dark: 'whiteAlpha.700', light: 'blackAlpha.700' };
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -14,8 +14,7 @@ export const Label = forwardRef(
|
|||||||
justifyContent="flex-start"
|
justifyContent="flex-start"
|
||||||
mx={[1, 2, 2, 2]}
|
mx={[1, 2, 2, 2]}
|
||||||
my={2}
|
my={2}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
display="inline-flex"
|
display="inline-flex"
|
||||||
justifyContent="center"
|
justifyContent="center"
|
||||||
@@ -24,15 +23,14 @@ export const Label = forwardRef(
|
|||||||
whiteSpace="nowrap"
|
whiteSpace="nowrap"
|
||||||
mb={2}
|
mb={2}
|
||||||
mr={0}
|
mr={0}
|
||||||
bg={valueBg || "primary.600"}
|
bg={valueBg || 'primary.600'}
|
||||||
color={valueColor || "white"}
|
color={valueColor || 'white'}
|
||||||
borderBottomLeftRadius={4}
|
borderBottomLeftRadius={4}
|
||||||
borderTopLeftRadius={4}
|
borderTopLeftRadius={4}
|
||||||
borderBottomRightRadius={0}
|
borderBottomRightRadius={0}
|
||||||
borderTopRightRadius={0}
|
borderTopRightRadius={0}
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
fontSize={["xs", "sm", "sm", "sm"]}
|
fontSize={['xs', 'sm', 'sm', 'sm']}>
|
||||||
>
|
|
||||||
{value}
|
{value}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex
|
<Flex
|
||||||
@@ -44,17 +42,16 @@ export const Label = forwardRef(
|
|||||||
mb={2}
|
mb={2}
|
||||||
ml={0}
|
ml={0}
|
||||||
mr={0}
|
mr={0}
|
||||||
boxShadow={`inset 0px 0px 0px 1px ${valueBg || "primary.600"}`}
|
boxShadow={`inset 0px 0px 0px 1px ${valueBg || 'primary.600'}`}
|
||||||
color={labelColor || _labelColor[colorMode]}
|
color={labelColor || _labelColor[colorMode]}
|
||||||
borderBottomRightRadius={4}
|
borderBottomRightRadius={4}
|
||||||
borderTopRightRadius={4}
|
borderTopRightRadius={4}
|
||||||
borderBottomLeftRadius={0}
|
borderBottomLeftRadius={0}
|
||||||
borderTopLeftRadius={0}
|
borderTopLeftRadius={0}
|
||||||
fontSize={["xs", "sm", "sm", "sm"]}
|
fontSize={['xs', 'sm', 'sm', 'sm']}>
|
||||||
>
|
|
||||||
{label}
|
{label}
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useRef } from "react";
|
import { useRef } from 'react';
|
||||||
import { Flex, useColorMode } from "@chakra-ui/core";
|
import { Flex, useColorMode } from '@chakra-ui/core';
|
||||||
import { useConfig, useHyperglassState } from "app/context";
|
import { useConfig, useHyperglassState } from 'app/context';
|
||||||
import { Debugger, Greeting, Footer, Header } from "app/components";
|
import { Debugger, Greeting, Footer, Header } from 'app/components';
|
||||||
|
|
||||||
const bg = { light: "white", dark: "black" };
|
const bg = { light: 'white', dark: 'black' };
|
||||||
const color = { light: "black", dark: "white" };
|
const color = { light: 'black', dark: 'white' };
|
||||||
|
|
||||||
export const Layout = ({ children }) => {
|
export const Layout = ({ children }) => {
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
@@ -21,8 +21,7 @@ export const Layout = ({ children }) => {
|
|||||||
minHeight="100vh"
|
minHeight="100vh"
|
||||||
bg={bg[colorMode]}
|
bg={bg[colorMode]}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
color={color[colorMode]}
|
color={color[colorMode]}>
|
||||||
>
|
|
||||||
<Flex px={2} flex="0 1 auto" flexDirection="column">
|
<Flex px={2} flex="0 1 auto" flexDirection="column">
|
||||||
<Header layoutRef={containerRef} />
|
<Header layoutRef={containerRef} />
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -35,8 +34,7 @@ export const Layout = ({ children }) => {
|
|||||||
textAlign="center"
|
textAlign="center"
|
||||||
alignItems="center"
|
alignItems="center"
|
||||||
justifyContent="start"
|
justifyContent="start"
|
||||||
flexDirection="column"
|
flexDirection="column">
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Flex>
|
</Flex>
|
||||||
<Footer />
|
<Footer />
|
||||||
|
@@ -1,18 +1,17 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Flex, Spinner, useColorMode } from "@chakra-ui/core";
|
import { Flex, Spinner, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const Loading = () => {
|
export const Loading = () => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const bg = { light: "white", dark: "black" };
|
const bg = { light: 'white', dark: 'black' };
|
||||||
const color = { light: "black", dark: "white" };
|
const color = { light: 'black', dark: 'white' };
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
minHeight="100vh"
|
minHeight="100vh"
|
||||||
w="100%"
|
w="100%"
|
||||||
bg={bg[colorMode]}
|
bg={bg[colorMode]}
|
||||||
color={color[colorMode]}
|
color={color[colorMode]}>
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
as="main"
|
as="main"
|
||||||
w="100%"
|
w="100%"
|
||||||
@@ -25,8 +24,7 @@ export const Loading = () => {
|
|||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
px={2}
|
px={2}
|
||||||
py={0}
|
py={0}
|
||||||
mt={["50%", "50%", "50%", "25%"]}
|
mt={['50%', '50%', '50%', '25%']}>
|
||||||
>
|
|
||||||
<Spinner color="primary.500" w="6rem" h="6rem" />
|
<Spinner color="primary.500" w="6rem" h="6rem" />
|
||||||
</Flex>
|
</Flex>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { Layout, HyperglassForm, Results } from "app/components";
|
import { Layout, HyperglassForm, Results } from 'app/components';
|
||||||
import { useHyperglassState } from "app/context";
|
import { useHyperglassState } from 'app/context';
|
||||||
|
|
||||||
const AnimatedForm = motion.custom(HyperglassForm);
|
const AnimatedForm = motion.custom(HyperglassForm);
|
||||||
|
|
||||||
@@ -12,7 +12,7 @@ export const LookingGlass = () => {
|
|||||||
formData,
|
formData,
|
||||||
setFormData,
|
setFormData,
|
||||||
greetingAck,
|
greetingAck,
|
||||||
setGreetingAck
|
setGreetingAck,
|
||||||
} = useHyperglassState();
|
} = useHyperglassState();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import {
|
import {
|
||||||
Checkbox as ChakraCheckbox,
|
Checkbox as ChakraCheckbox,
|
||||||
Divider as ChakraDivider,
|
Divider as ChakraDivider,
|
||||||
@@ -7,19 +7,19 @@ import {
|
|||||||
Link as ChakraLink,
|
Link as ChakraLink,
|
||||||
List as ChakraList,
|
List as ChakraList,
|
||||||
ListItem as ChakraListItem,
|
ListItem as ChakraListItem,
|
||||||
Text as ChakraText
|
Text as ChakraText,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
|
|
||||||
import { TableCell, TableHeader, Table as ChakraTable } from "./MDTable";
|
import { TableCell, TableHeader, Table as ChakraTable } from './MDTable';
|
||||||
|
|
||||||
import { CodeBlock as CustomCodeBlock } from "app/components";
|
import { CodeBlock as CustomCodeBlock } from 'app/components';
|
||||||
|
|
||||||
export const Checkbox = ({ checked, children }) => (
|
export const Checkbox = ({ checked, children }) => (
|
||||||
<ChakraCheckbox isChecked={checked}>{children}</ChakraCheckbox>
|
<ChakraCheckbox isChecked={checked}>{children}</ChakraCheckbox>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const List = ({ ordered, children }) => (
|
export const List = ({ ordered, children }) => (
|
||||||
<ChakraList as={ordered ? "ol" : "ul"}>{children}</ChakraList>
|
<ChakraList as={ordered ? 'ol' : 'ul'}>{children}</ChakraList>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const ListItem = ({ checked, children }) =>
|
export const ListItem = ({ checked, children }) =>
|
||||||
@@ -31,12 +31,12 @@ export const ListItem = ({ checked, children }) =>
|
|||||||
|
|
||||||
export const Heading = ({ level, children }) => {
|
export const Heading = ({ level, children }) => {
|
||||||
const levelMap = {
|
const levelMap = {
|
||||||
1: { as: "h1", size: "lg", fontWeight: "bold" },
|
1: { as: 'h1', size: 'lg', fontWeight: 'bold' },
|
||||||
2: { as: "h2", size: "lg", fontWeight: "normal" },
|
2: { as: 'h2', size: 'lg', fontWeight: 'normal' },
|
||||||
3: { as: "h3", size: "lg", fontWeight: "bold" },
|
3: { as: 'h3', size: 'lg', fontWeight: 'bold' },
|
||||||
4: { as: "h4", size: "md", fontWeight: "normal" },
|
4: { as: 'h4', size: 'md', fontWeight: 'normal' },
|
||||||
5: { as: "h5", size: "md", fontWeight: "bold" },
|
5: { as: 'h5', size: 'md', fontWeight: 'bold' },
|
||||||
6: { as: "h6", size: "sm", fontWeight: "bold" }
|
6: { as: 'h6', size: 'sm', fontWeight: 'bold' },
|
||||||
};
|
};
|
||||||
return <ChakraHeading {...levelMap[level]}>{children}</ChakraHeading>;
|
return <ChakraHeading {...levelMap[level]}>{children}</ChakraHeading>;
|
||||||
};
|
};
|
||||||
@@ -47,9 +47,7 @@ export const Link = ({ children, ...props }) => (
|
|||||||
</ChakraLink>
|
</ChakraLink>
|
||||||
);
|
);
|
||||||
|
|
||||||
export const CodeBlock = ({ value }) => (
|
export const CodeBlock = ({ value }) => <CustomCodeBlock>{value}</CustomCodeBlock>;
|
||||||
<CustomCodeBlock>{value}</CustomCodeBlock>
|
|
||||||
);
|
|
||||||
|
|
||||||
export const TableData = ({ isHeader, children, ...props }) => {
|
export const TableData = ({ isHeader, children, ...props }) => {
|
||||||
const Component = isHeader ? TableHeader : TableCell;
|
const Component = isHeader ? TableHeader : TableCell;
|
||||||
|
@@ -1,30 +1,19 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Box, useColorMode } from "@chakra-ui/core";
|
import { Box, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const Table = props => (
|
export const Table = props => <Box as="table" textAlign="left" mt={4} width="full" {...props} />;
|
||||||
<Box as="table" textAlign="left" mt={4} width="full" {...props} />
|
|
||||||
);
|
|
||||||
|
|
||||||
const bg = { light: "blackAlpha.50", dark: "whiteAlpha.50" };
|
const bg = { light: 'blackAlpha.50', dark: 'whiteAlpha.50' };
|
||||||
|
|
||||||
export const TableHeader = props => {
|
export const TableHeader = props => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
|
|
||||||
return (
|
return <Box as="th" bg={bg[colorMode]} fontWeight="semibold" p={2} fontSize="sm" {...props} />;
|
||||||
<Box
|
|
||||||
as="th"
|
|
||||||
bg={bg[colorMode]}
|
|
||||||
fontWeight="semibold"
|
|
||||||
p={2}
|
|
||||||
fontSize="sm"
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TableCell = ({ isHeader = false, ...props }) => (
|
export const TableCell = ({ isHeader = false, ...props }) => (
|
||||||
<Box
|
<Box
|
||||||
as={isHeader ? "th" : "td"}
|
as={isHeader ? 'th' : 'td'}
|
||||||
p={2}
|
p={2}
|
||||||
borderTopWidth="1px"
|
borderTopWidth="1px"
|
||||||
borderColor="inherit"
|
borderColor="inherit"
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import ReactMarkdown from "react-markdown";
|
import ReactMarkdown from 'react-markdown';
|
||||||
import {
|
import {
|
||||||
List,
|
List,
|
||||||
ListItem,
|
ListItem,
|
||||||
@@ -11,8 +11,8 @@ import {
|
|||||||
Paragraph,
|
Paragraph,
|
||||||
InlineCode,
|
InlineCode,
|
||||||
Divider,
|
Divider,
|
||||||
Table
|
Table,
|
||||||
} from "./MDComponents";
|
} from './MDComponents';
|
||||||
|
|
||||||
const mdComponents = {
|
const mdComponents = {
|
||||||
paragraph: Paragraph,
|
paragraph: Paragraph,
|
||||||
@@ -24,7 +24,7 @@ const mdComponents = {
|
|||||||
thematicBreak: Divider,
|
thematicBreak: Divider,
|
||||||
code: CodeBlock,
|
code: CodeBlock,
|
||||||
table: Table,
|
table: Table,
|
||||||
tableCell: TableData
|
tableCell: TableData,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Markdown = forwardRef(({ content }, ref) => (
|
export const Markdown = forwardRef(({ content }, ref) => (
|
||||||
|
@@ -1 +1 @@
|
|||||||
export * from "./Markdown";
|
export * from './Markdown';
|
||||||
|
@@ -1,38 +1,38 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
import Head from "next/head";
|
import Head from 'next/head';
|
||||||
import { useTheme } from "@chakra-ui/core";
|
import { useTheme } from '@chakra-ui/core';
|
||||||
import { useConfig } from "app/context";
|
import { useConfig } from 'app/context';
|
||||||
import { googleFontUrl } from "app/util";
|
import { googleFontUrl } from 'app/util';
|
||||||
|
|
||||||
export const Meta = () => {
|
export const Meta = () => {
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [location, setLocation] = useState({});
|
const [location, setLocation] = useState({});
|
||||||
const title = config?.site_title || "hyperglass";
|
const title = config?.site_title || 'hyperglass';
|
||||||
const description = config?.site_description || "Network Looking Glass";
|
const description = config?.site_description || 'Network Looking Glass';
|
||||||
const siteName = `${title} - ${description}`;
|
const siteName = `${title} - ${description}`;
|
||||||
const keywords = config?.site_keywords || [
|
const keywords = config?.site_keywords || [
|
||||||
"hyperglass",
|
'hyperglass',
|
||||||
"looking glass",
|
'looking glass',
|
||||||
"lg",
|
'lg',
|
||||||
"peer",
|
'peer',
|
||||||
"peering",
|
'peering',
|
||||||
"ipv4",
|
'ipv4',
|
||||||
"ipv6",
|
'ipv6',
|
||||||
"transit",
|
'transit',
|
||||||
"community",
|
'community',
|
||||||
"communities",
|
'communities',
|
||||||
"bgp",
|
'bgp',
|
||||||
"routing",
|
'routing',
|
||||||
"network",
|
'network',
|
||||||
"isp"
|
'isp',
|
||||||
];
|
];
|
||||||
const language = config?.language ?? "en";
|
const language = config?.language ?? 'en';
|
||||||
const primaryFont = googleFontUrl(theme.fonts.body);
|
const primaryFont = googleFontUrl(theme.fonts.body);
|
||||||
const monoFont = googleFontUrl(theme.fonts.mono);
|
const monoFont = googleFontUrl(theme.fonts.mono);
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (typeof window !== "undefined" && location === {}) {
|
if (typeof window !== 'undefined' && location === {}) {
|
||||||
setLocation(window.location);
|
setLocation(window.location);
|
||||||
}
|
}
|
||||||
}, [location]);
|
}, [location]);
|
||||||
@@ -41,7 +41,7 @@ export const Meta = () => {
|
|||||||
<title>{title}</title>
|
<title>{title}</title>
|
||||||
<meta name="hg-version" content={config.hyperglass_version} />
|
<meta name="hg-version" content={config.hyperglass_version} />
|
||||||
<meta name="description" content={description} />
|
<meta name="description" content={description} />
|
||||||
<meta name="keywords" content={keywords.join(", ")} />
|
<meta name="keywords" content={keywords.join(', ')} />
|
||||||
<meta name="language" content={language} />
|
<meta name="language" content={language} />
|
||||||
<meta name="url" content={location.href} />
|
<meta name="url" content={location.href} />
|
||||||
<meta name="og:title" content={title} />
|
<meta name="og:title" content={title} />
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { ChakraSelect } from "app/components";
|
import { ChakraSelect } from 'app/components';
|
||||||
|
|
||||||
const buildLocations = networks => {
|
const buildLocations = networks => {
|
||||||
const locations = [];
|
const locations = [];
|
||||||
@@ -9,7 +9,7 @@ const buildLocations = networks => {
|
|||||||
netLocations.push({
|
netLocations.push({
|
||||||
label: loc.display_name,
|
label: loc.display_name,
|
||||||
value: loc.name,
|
value: loc.name,
|
||||||
group: net.display_name
|
group: net.display_name,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
locations.push({ label: net.display_name, options: netLocations });
|
locations.push({ label: net.display_name, options: netLocations });
|
||||||
@@ -25,7 +25,7 @@ export const QueryLocation = ({ locations, onChange, label }) => {
|
|||||||
e.map(sel => {
|
e.map(sel => {
|
||||||
selected.push(sel.value);
|
selected.push(sel.value);
|
||||||
});
|
});
|
||||||
onChange({ field: "query_location", value: selected });
|
onChange({ field: 'query_location', value: selected });
|
||||||
};
|
};
|
||||||
return (
|
return (
|
||||||
<ChakraSelect
|
<ChakraSelect
|
||||||
|
@@ -1,13 +1,13 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useEffect } from "react";
|
import { useEffect } from 'react';
|
||||||
import { Input, useColorMode } from "@chakra-ui/core";
|
import { Input, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const fqdnPattern = /^(?!:\/\/)([a-zA-Z0-9-]+\.)?[a-zA-Z0-9-][a-zA-Z0-9-]+\.[a-zA-Z-]{2,6}?$/gim;
|
const fqdnPattern = /^(?!:\/\/)([a-zA-Z0-9-]+\.)?[a-zA-Z0-9-][a-zA-Z0-9-]+\.[a-zA-Z-]{2,6}?$/gim;
|
||||||
|
|
||||||
const bg = { dark: "whiteAlpha.100", light: "white" };
|
const bg = { dark: 'whiteAlpha.100', light: 'white' };
|
||||||
const color = { dark: "whiteAlpha.800", light: "gray.400" };
|
const color = { dark: 'whiteAlpha.800', light: 'gray.400' };
|
||||||
const border = { dark: "whiteAlpha.50", light: "gray.100" };
|
const border = { dark: 'whiteAlpha.50', light: 'gray.100' };
|
||||||
const placeholderColor = { dark: "whiteAlpha.700", light: "gray.600" };
|
const placeholderColor = { dark: 'whiteAlpha.700', light: 'gray.600' };
|
||||||
|
|
||||||
export const QueryTarget = ({
|
export const QueryTarget = ({
|
||||||
placeholder,
|
placeholder,
|
||||||
@@ -19,7 +19,7 @@ export const QueryTarget = ({
|
|||||||
setTarget,
|
setTarget,
|
||||||
resolveTarget,
|
resolveTarget,
|
||||||
displayValue,
|
displayValue,
|
||||||
setDisplayValue
|
setDisplayValue,
|
||||||
}) => {
|
}) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
|
|
||||||
@@ -61,7 +61,7 @@ export const QueryTarget = ({
|
|||||||
placeholder={placeholder}
|
placeholder={placeholder}
|
||||||
borderColor={border[colorMode]}
|
borderColor={border[colorMode]}
|
||||||
_placeholder={{
|
_placeholder={{
|
||||||
color: placeholderColor[colorMode]
|
color: placeholderColor[colorMode],
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { ChakraSelect } from "app/components";
|
import { ChakraSelect } from 'app/components';
|
||||||
|
|
||||||
export const QueryType = ({ queryTypes, onChange, label }) => {
|
export const QueryType = ({ queryTypes, onChange, label }) => {
|
||||||
const queries = queryTypes
|
const queries = queryTypes
|
||||||
@@ -11,7 +11,7 @@ export const QueryType = ({ queryTypes, onChange, label }) => {
|
|||||||
<ChakraSelect
|
<ChakraSelect
|
||||||
size="lg"
|
size="lg"
|
||||||
name="query_type"
|
name="query_type"
|
||||||
onChange={e => onChange({ field: "query_type", value: e.value })}
|
onChange={e => onChange({ field: 'query_type', value: e.value })}
|
||||||
options={queries}
|
options={queries}
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
/>
|
/>
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { ChakraSelect } from "app/components";
|
import { ChakraSelect } from 'app/components';
|
||||||
|
|
||||||
export const QueryVrf = ({ vrfs, onChange, label }) => (
|
export const QueryVrf = ({ vrfs, onChange, label }) => (
|
||||||
<ChakraSelect
|
<ChakraSelect
|
||||||
@@ -7,6 +7,6 @@ export const QueryVrf = ({ vrfs, onChange, label }) => (
|
|||||||
options={vrfs}
|
options={vrfs}
|
||||||
name="query_vrf"
|
name="query_vrf"
|
||||||
aria-label={label}
|
aria-label={label}
|
||||||
onChange={e => onChange({ field: "query_vrf", value: e.value })}
|
onChange={e => onChange({ field: 'query_vrf', value: e.value })}
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
@@ -1,17 +1,9 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Button, Icon, Tooltip } from "@chakra-ui/core";
|
import { Button, Icon, Tooltip } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const RequeryButton = ({ requery, bg = "secondary", ...props }) => (
|
export const RequeryButton = ({ requery, bg = 'secondary', ...props }) => (
|
||||||
<Tooltip hasArrow label="Reload Query" placement="top">
|
<Tooltip hasArrow label="Reload Query" placement="top">
|
||||||
<Button
|
<Button mx={1} as="a" size="sm" zIndex="1" variantColor={bg} onClick={requery} {...props}>
|
||||||
mx={1}
|
|
||||||
as="a"
|
|
||||||
size="sm"
|
|
||||||
zIndex="1"
|
|
||||||
variantColor={bg}
|
|
||||||
onClick={requery}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<Icon size="16px" name="repeat" />
|
<Icon size="16px" name="repeat" />
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
@@ -1,18 +1,15 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Button } from "@chakra-ui/core";
|
import { Button } from '@chakra-ui/core';
|
||||||
import { FiChevronLeft } from "@meronex/icons/fi";
|
import { FiChevronLeft } from '@meronex/icons/fi';
|
||||||
|
|
||||||
export const ResetButton = React.forwardRef(
|
export const ResetButton = React.forwardRef(({ isSubmitting, onClick }, ref) => (
|
||||||
({ isSubmitting, onClick }, ref) => (
|
<Button
|
||||||
<Button
|
ref={ref}
|
||||||
ref={ref}
|
color="current"
|
||||||
color="current"
|
variant="ghost"
|
||||||
variant="ghost"
|
onClick={onClick}
|
||||||
onClick={onClick}
|
aria-label="Reset Form"
|
||||||
aria-label="Reset Form"
|
opacity={isSubmitting ? 1 : 0}>
|
||||||
opacity={isSubmitting ? 1 : 0}
|
<FiChevronLeft size={24} />
|
||||||
>
|
</Button>
|
||||||
<FiChevronLeft size={24} />
|
));
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
@@ -1,23 +1,14 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef, useEffect } from "react";
|
import { forwardRef, useEffect } from 'react';
|
||||||
import {
|
import { Button, Icon, Spinner, Stack, Tag, Text, Tooltip, useColorMode } from '@chakra-ui/core';
|
||||||
Button,
|
import useAxios from 'axios-hooks';
|
||||||
Icon,
|
import format from 'string-format';
|
||||||
Spinner,
|
import { useConfig } from 'app/context';
|
||||||
Stack,
|
|
||||||
Tag,
|
|
||||||
Text,
|
|
||||||
Tooltip,
|
|
||||||
useColorMode
|
|
||||||
} from "@chakra-ui/core";
|
|
||||||
import useAxios from "axios-hooks";
|
|
||||||
import format from "string-format";
|
|
||||||
import { useConfig } from "app/context";
|
|
||||||
|
|
||||||
format.extend(String.prototype, {});
|
format.extend(String.prototype, {});
|
||||||
|
|
||||||
const labelBg = { dark: "secondary", light: "secondary" };
|
const labelBg = { dark: 'secondary', light: 'secondary' };
|
||||||
const labelBgSuccess = { dark: "success", light: "success" };
|
const labelBgSuccess = { dark: 'success', light: 'success' };
|
||||||
|
|
||||||
export const ResolvedTarget = forwardRef(
|
export const ResolvedTarget = forwardRef(
|
||||||
({ fqdnTarget, setTarget, queryTarget, families, availVrfs }, ref) => {
|
({ fqdnTarget, setTarget, queryTarget, families, availVrfs }, ref) => {
|
||||||
@@ -25,7 +16,7 @@ export const ResolvedTarget = forwardRef(
|
|||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const labelBgStatus = {
|
const labelBgStatus = {
|
||||||
true: labelBgSuccess[colorMode],
|
true: labelBgSuccess[colorMode],
|
||||||
false: labelBg[colorMode]
|
false: labelBg[colorMode],
|
||||||
};
|
};
|
||||||
const dnsUrl = config.web.dns_provider.url;
|
const dnsUrl = config.web.dns_provider.url;
|
||||||
const query4 = families.includes(4);
|
const query4 = families.includes(4);
|
||||||
@@ -33,30 +24,26 @@ export const ResolvedTarget = forwardRef(
|
|||||||
const params = {
|
const params = {
|
||||||
4: {
|
4: {
|
||||||
url: dnsUrl,
|
url: dnsUrl,
|
||||||
params: { name: fqdnTarget, type: "A" },
|
params: { name: fqdnTarget, type: 'A' },
|
||||||
headers: { accept: "application/dns-json" },
|
headers: { accept: 'application/dns-json' },
|
||||||
crossdomain: true,
|
crossdomain: true,
|
||||||
timeout: 1000
|
timeout: 1000,
|
||||||
},
|
},
|
||||||
6: {
|
6: {
|
||||||
url: dnsUrl,
|
url: dnsUrl,
|
||||||
params: { name: fqdnTarget, type: "AAAA" },
|
params: { name: fqdnTarget, type: 'AAAA' },
|
||||||
headers: { accept: "application/dns-json" },
|
headers: { accept: 'application/dns-json' },
|
||||||
crossdomain: true,
|
crossdomain: true,
|
||||||
timeout: 1000
|
timeout: 1000,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const [{ data: data4, loading: loading4, error: error4 }] = useAxios(
|
const [{ data: data4, loading: loading4, error: error4 }] = useAxios(params[4]);
|
||||||
params[4]
|
|
||||||
);
|
|
||||||
|
|
||||||
const [{ data: data6, loading: loading6, error: error6 }] = useAxios(
|
const [{ data: data6, loading: loading6, error: error6 }] = useAxios(params[6]);
|
||||||
params[6]
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleOverride = overridden => {
|
const handleOverride = overridden => {
|
||||||
setTarget({ field: "query_target", value: overridden });
|
setTarget({ field: 'query_target', value: overridden });
|
||||||
};
|
};
|
||||||
|
|
||||||
const isSelected = value => {
|
const isSelected = value => {
|
||||||
@@ -64,9 +51,8 @@ export const ResolvedTarget = forwardRef(
|
|||||||
};
|
};
|
||||||
|
|
||||||
const findAnswer = data => {
|
const findAnswer = data => {
|
||||||
return data?.Answer?.filter(
|
return data?.Answer?.filter(answerData => answerData.type === data?.Question[0]?.type)[0]
|
||||||
answerData => answerData.type === data?.Question[0]?.type
|
?.data;
|
||||||
)[0]?.data;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -84,16 +70,11 @@ export const ResolvedTarget = forwardRef(
|
|||||||
isInline
|
isInline
|
||||||
w="100%"
|
w="100%"
|
||||||
justifyContent={
|
justifyContent={
|
||||||
query4 &&
|
query4 && data4?.Answer && query6 && data6?.Answer && availVrfs.length > 1
|
||||||
data4?.Answer &&
|
? 'space-between'
|
||||||
query6 &&
|
: 'flex-end'
|
||||||
data6?.Answer &&
|
|
||||||
availVrfs.length > 1
|
|
||||||
? "space-between"
|
|
||||||
: "flex-end"
|
|
||||||
}
|
}
|
||||||
flexWrap="wrap"
|
flexWrap="wrap">
|
||||||
>
|
|
||||||
{loading4 ||
|
{loading4 ||
|
||||||
error4 ||
|
error4 ||
|
||||||
(query4 && findAnswer(data4) && (
|
(query4 && findAnswer(data4) && (
|
||||||
@@ -101,10 +82,9 @@ export const ResolvedTarget = forwardRef(
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
hasArrow
|
hasArrow
|
||||||
label={config.web.text.fqdn_tooltip.format({
|
label={config.web.text.fqdn_tooltip.format({
|
||||||
protocol: "IPv4"
|
protocol: 'IPv4',
|
||||||
})}
|
})}
|
||||||
placement="bottom"
|
placement="bottom">
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
height="unset"
|
height="unset"
|
||||||
minW="unset"
|
minW="unset"
|
||||||
@@ -112,24 +92,16 @@ export const ResolvedTarget = forwardRef(
|
|||||||
py="0.1rem"
|
py="0.1rem"
|
||||||
px={2}
|
px={2}
|
||||||
mr={2}
|
mr={2}
|
||||||
variantColor={
|
variantColor={labelBgStatus[findAnswer(data4) === queryTarget]}
|
||||||
labelBgStatus[findAnswer(data4) === queryTarget]
|
|
||||||
}
|
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
onClick={() => handleOverride(findAnswer(data4))}
|
onClick={() => handleOverride(findAnswer(data4))}>
|
||||||
>
|
|
||||||
IPv4
|
IPv4
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{loading4 && <Spinner />}
|
{loading4 && <Spinner />}
|
||||||
{error4 && <Icon name="warning" />}
|
{error4 && <Icon name="warning" />}
|
||||||
{findAnswer(data4) && (
|
{findAnswer(data4) && (
|
||||||
<Text
|
<Text fontSize="xs" fontFamily="mono" as="span" fontWeight={400}>
|
||||||
fontSize="xs"
|
|
||||||
fontFamily="mono"
|
|
||||||
as="span"
|
|
||||||
fontWeight={400}
|
|
||||||
>
|
|
||||||
{findAnswer(data4)}
|
{findAnswer(data4)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
@@ -142,10 +114,9 @@ export const ResolvedTarget = forwardRef(
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
hasArrow
|
hasArrow
|
||||||
label={config.web.text.fqdn_tooltip.format({
|
label={config.web.text.fqdn_tooltip.format({
|
||||||
protocol: "IPv6"
|
protocol: 'IPv6',
|
||||||
})}
|
})}
|
||||||
placement="bottom"
|
placement="bottom">
|
||||||
>
|
|
||||||
<Button
|
<Button
|
||||||
height="unset"
|
height="unset"
|
||||||
minW="unset"
|
minW="unset"
|
||||||
@@ -155,20 +126,14 @@ export const ResolvedTarget = forwardRef(
|
|||||||
mr={2}
|
mr={2}
|
||||||
variantColor={isSelected(findAnswer(data6))}
|
variantColor={isSelected(findAnswer(data6))}
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
onClick={() => handleOverride(findAnswer(data6))}
|
onClick={() => handleOverride(findAnswer(data6))}>
|
||||||
>
|
|
||||||
IPv6
|
IPv6
|
||||||
</Button>
|
</Button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
{loading6 && <Spinner />}
|
{loading6 && <Spinner />}
|
||||||
{error6 && <Icon name="warning" />}
|
{error6 && <Icon name="warning" />}
|
||||||
{findAnswer(data6) && (
|
{findAnswer(data6) && (
|
||||||
<Text
|
<Text fontSize="xs" fontFamily="mono" as="span" fontWeight={400}>
|
||||||
fontSize="xs"
|
|
||||||
fontFamily="mono"
|
|
||||||
as="span"
|
|
||||||
fontWeight={400}
|
|
||||||
>
|
|
||||||
{findAnswer(data6)}
|
{findAnswer(data6)}
|
||||||
</Text>
|
</Text>
|
||||||
)}
|
)}
|
||||||
@@ -176,5 +141,5 @@ export const ResolvedTarget = forwardRef(
|
|||||||
))}
|
))}
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx } from "@emotion/core";
|
import { jsx } from '@emotion/core';
|
||||||
import { forwardRef, useEffect, useState } from "react";
|
import { forwardRef, useEffect, useState } from 'react';
|
||||||
import {
|
import {
|
||||||
AccordionItem,
|
AccordionItem,
|
||||||
AccordionHeader,
|
AccordionHeader,
|
||||||
@@ -13,30 +13,30 @@ import {
|
|||||||
Tooltip,
|
Tooltip,
|
||||||
Text,
|
Text,
|
||||||
useColorMode,
|
useColorMode,
|
||||||
useTheme
|
useTheme,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
import { BsLightningFill } from "@meronex/icons/bs";
|
import { BsLightningFill } from '@meronex/icons/bs';
|
||||||
import styled from "@emotion/styled";
|
import styled from '@emotion/styled';
|
||||||
import useAxios from "axios-hooks";
|
import useAxios from 'axios-hooks';
|
||||||
import strReplace from "react-string-replace";
|
import strReplace from 'react-string-replace';
|
||||||
import format from "string-format";
|
import format from 'string-format';
|
||||||
import { startCase } from "lodash";
|
import { startCase } from 'lodash';
|
||||||
import { useConfig, useMedia } from "app/context";
|
import { useConfig, useMedia } from 'app/context';
|
||||||
import {
|
import {
|
||||||
BGPTable,
|
BGPTable,
|
||||||
CacheTimeout,
|
CacheTimeout,
|
||||||
CopyButton,
|
CopyButton,
|
||||||
RequeryButton,
|
RequeryButton,
|
||||||
ResultHeader,
|
ResultHeader,
|
||||||
TextOutput
|
TextOutput,
|
||||||
} from "app/components";
|
} from 'app/components';
|
||||||
import { tableToString } from "app/util";
|
import { tableToString } from 'app/util';
|
||||||
|
|
||||||
format.extend(String.prototype, {});
|
format.extend(String.prototype, {});
|
||||||
|
|
||||||
const FormattedError = ({ keywords, message }) => {
|
const FormattedError = ({ keywords, message }) => {
|
||||||
const patternStr = keywords.map(kw => `(${kw})`).join("|");
|
const patternStr = keywords.map(kw => `(${kw})`).join('|');
|
||||||
const pattern = new RegExp(patternStr, "gi");
|
const pattern = new RegExp(patternStr, 'gi');
|
||||||
let errorFmt;
|
let errorFmt;
|
||||||
try {
|
try {
|
||||||
errorFmt = strReplace(message, pattern, match => (
|
errorFmt = strReplace(message, pattern, match => (
|
||||||
@@ -56,21 +56,21 @@ const AccordionHeaderWrapper = styled(Flex)`
|
|||||||
background-color: ${props => props.hoverBg};
|
background-color: ${props => props.hoverBg};
|
||||||
}
|
}
|
||||||
&:focus {
|
&:focus {
|
||||||
box-shadow: "outline";
|
box-shadow: 'outline';
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const statusMap = {
|
const statusMap = {
|
||||||
success: "success",
|
success: 'success',
|
||||||
warning: "warning",
|
warning: 'warning',
|
||||||
error: "warning",
|
error: 'warning',
|
||||||
danger: "error"
|
danger: 'error',
|
||||||
};
|
};
|
||||||
|
|
||||||
const color = { dark: "white", light: "black" };
|
const color = { dark: 'white', light: 'black' };
|
||||||
const scrollbar = { dark: "whiteAlpha.300", light: "blackAlpha.300" };
|
const scrollbar = { dark: 'whiteAlpha.300', light: 'blackAlpha.300' };
|
||||||
const scrollbarHover = { dark: "whiteAlpha.400", light: "blackAlpha.400" };
|
const scrollbarHover = { dark: 'whiteAlpha.400', light: 'blackAlpha.400' };
|
||||||
const scrollbarBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
const scrollbarBg = { dark: 'whiteAlpha.50', light: 'blackAlpha.50' };
|
||||||
|
|
||||||
export const Result = forwardRef(
|
export const Result = forwardRef(
|
||||||
(
|
(
|
||||||
@@ -83,25 +83,25 @@ export const Result = forwardRef(
|
|||||||
queryTarget,
|
queryTarget,
|
||||||
index,
|
index,
|
||||||
resultsComplete,
|
resultsComplete,
|
||||||
setComplete
|
setComplete,
|
||||||
},
|
},
|
||||||
ref
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const config = useConfig();
|
const config = useConfig();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { isSm } = useMedia();
|
const { isSm } = useMedia();
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
let [{ data, loading, error }, refetch] = useAxios({
|
let [{ data, loading, error }, refetch] = useAxios({
|
||||||
url: "/api/query/",
|
url: '/api/query/',
|
||||||
method: "post",
|
method: 'post',
|
||||||
data: {
|
data: {
|
||||||
query_location: queryLocation,
|
query_location: queryLocation,
|
||||||
query_type: queryType,
|
query_type: queryType,
|
||||||
query_vrf: queryVrf,
|
query_vrf: queryVrf,
|
||||||
query_target: queryTarget
|
query_target: queryTarget,
|
||||||
},
|
},
|
||||||
timeout: timeout,
|
timeout: timeout,
|
||||||
useCache: false
|
useCache: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [isOpen, setOpen] = useState(false);
|
const [isOpen, setOpen] = useState(false);
|
||||||
@@ -117,7 +117,7 @@ export const Result = forwardRef(
|
|||||||
let errorMsg;
|
let errorMsg;
|
||||||
if (error && error.response?.data?.output) {
|
if (error && error.response?.data?.output) {
|
||||||
errorMsg = error.response.data.output;
|
errorMsg = error.response.data.output;
|
||||||
} else if (error && error.message.startsWith("timeout")) {
|
} else if (error && error.message.startsWith('timeout')) {
|
||||||
errorMsg = config.messages.request_timeout;
|
errorMsg = config.messages.request_timeout;
|
||||||
} else if (error?.response?.statusText) {
|
} else if (error?.response?.statusText) {
|
||||||
errorMsg = startCase(error.response.statusText);
|
errorMsg = startCase(error.response.statusText);
|
||||||
@@ -130,22 +130,20 @@ export const Result = forwardRef(
|
|||||||
error && console.error(error);
|
error && console.error(error);
|
||||||
|
|
||||||
const errorLevel =
|
const errorLevel =
|
||||||
(error?.response?.data?.level &&
|
(error?.response?.data?.level && statusMap[error.response?.data?.level]) ?? 'error';
|
||||||
statusMap[error.response?.data?.level]) ??
|
|
||||||
"error";
|
|
||||||
|
|
||||||
const structuredDataComponent = {
|
const structuredDataComponent = {
|
||||||
bgp_route: BGPTable,
|
bgp_route: BGPTable,
|
||||||
bgp_aspath: BGPTable,
|
bgp_aspath: BGPTable,
|
||||||
bgp_community: BGPTable,
|
bgp_community: BGPTable,
|
||||||
ping: TextOutput,
|
ping: TextOutput,
|
||||||
traceroute: TextOutput
|
traceroute: TextOutput,
|
||||||
};
|
};
|
||||||
|
|
||||||
let Output = TextOutput;
|
let Output = TextOutput;
|
||||||
let copyValue = data?.output;
|
let copyValue = data?.output;
|
||||||
|
|
||||||
if (data?.format === "application/json") {
|
if (data?.format === 'application/json') {
|
||||||
Output = structuredDataComponent[queryType];
|
Output = structuredDataComponent[queryType];
|
||||||
copyValue = tableToString(queryTarget, data, config);
|
copyValue = tableToString(queryTarget, data, config);
|
||||||
}
|
}
|
||||||
@@ -168,10 +166,9 @@ export const Result = forwardRef(
|
|||||||
isDisabled={loading}
|
isDisabled={loading}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
css={css({
|
css={css({
|
||||||
"&:last-of-type": { borderBottom: "none" },
|
'&:last-of-type': { borderBottom: 'none' },
|
||||||
"&:first-of-type": { borderTop: "none" }
|
'&:first-of-type': { borderTop: 'none' },
|
||||||
})(theme)}
|
})(theme)}>
|
||||||
>
|
|
||||||
<AccordionHeaderWrapper hoverBg="blackAlpha.50">
|
<AccordionHeaderWrapper hoverBg="blackAlpha.50">
|
||||||
<AccordionHeader
|
<AccordionHeader
|
||||||
flex="1 0 auto"
|
flex="1 0 auto"
|
||||||
@@ -179,8 +176,7 @@ export const Result = forwardRef(
|
|||||||
_hover={{}}
|
_hover={{}}
|
||||||
_focus={{}}
|
_focus={{}}
|
||||||
w="unset"
|
w="unset"
|
||||||
onClick={handleToggle}
|
onClick={handleToggle}>
|
||||||
>
|
|
||||||
<ResultHeader
|
<ResultHeader
|
||||||
title={device.display_name}
|
title={device.display_name}
|
||||||
loading={loading}
|
loading={loading}
|
||||||
@@ -191,43 +187,30 @@ export const Result = forwardRef(
|
|||||||
/>
|
/>
|
||||||
</AccordionHeader>
|
</AccordionHeader>
|
||||||
<ButtonGroup px={[1, 1, 3, 3]} py={2}>
|
<ButtonGroup px={[1, 1, 3, 3]} py={2}>
|
||||||
<CopyButton
|
<CopyButton copyValue={copyValue} variant="ghost" isDisabled={loading} />
|
||||||
copyValue={copyValue}
|
<RequeryButton requery={refetch} variant="ghost" isDisabled={loading} />
|
||||||
variant="ghost"
|
|
||||||
isDisabled={loading}
|
|
||||||
/>
|
|
||||||
<RequeryButton
|
|
||||||
requery={refetch}
|
|
||||||
variant="ghost"
|
|
||||||
isDisabled={loading}
|
|
||||||
/>
|
|
||||||
</ButtonGroup>
|
</ButtonGroup>
|
||||||
</AccordionHeaderWrapper>
|
</AccordionHeaderWrapper>
|
||||||
<AccordionPanel
|
<AccordionPanel
|
||||||
pb={4}
|
pb={4}
|
||||||
overflowX="auto"
|
overflowX="auto"
|
||||||
css={css({
|
css={css({
|
||||||
WebkitOverflowScrolling: "touch",
|
WebkitOverflowScrolling: 'touch',
|
||||||
"&::-webkit-scrollbar": { height: "5px" },
|
'&::-webkit-scrollbar': { height: '5px' },
|
||||||
"&::-webkit-scrollbar-track": {
|
'&::-webkit-scrollbar-track': {
|
||||||
backgroundColor: scrollbarBg[colorMode]
|
backgroundColor: scrollbarBg[colorMode],
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb": {
|
'&::-webkit-scrollbar-thumb': {
|
||||||
backgroundColor: scrollbar[colorMode]
|
backgroundColor: scrollbar[colorMode],
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb:hover": {
|
'&::-webkit-scrollbar-thumb:hover': {
|
||||||
backgroundColor: scrollbarHover[colorMode]
|
backgroundColor: scrollbarHover[colorMode],
|
||||||
},
|
},
|
||||||
|
|
||||||
"-ms-overflow-style": { display: "none" }
|
'-ms-overflow-style': { display: 'none' },
|
||||||
})(theme)}
|
})(theme)}>
|
||||||
>
|
|
||||||
<Flex direction="column" flexWrap="wrap">
|
<Flex direction="column" flexWrap="wrap">
|
||||||
<Flex
|
<Flex direction="column" flex="1 0 auto" maxW={error ? '100%' : null}>
|
||||||
direction="column"
|
|
||||||
flex="1 0 auto"
|
|
||||||
maxW={error ? "100%" : null}
|
|
||||||
>
|
|
||||||
{!error && data && <Output>{data?.output}</Output>}
|
{!error && data && <Output>{data?.output}</Output>}
|
||||||
{error && (
|
{error && (
|
||||||
<Alert rounded="lg" my={2} py={4} status={errorLevel}>
|
<Alert rounded="lg" my={2} py={4} status={errorLevel}>
|
||||||
@@ -241,14 +224,8 @@ export const Result = forwardRef(
|
|||||||
<Flex
|
<Flex
|
||||||
px={3}
|
px={3}
|
||||||
mt={2}
|
mt={2}
|
||||||
justifyContent={[
|
justifyContent={['flex-start', 'flex-start', 'flex-end', 'flex-end']}
|
||||||
"flex-start",
|
flex="1 0 auto">
|
||||||
"flex-start",
|
|
||||||
"flex-end",
|
|
||||||
"flex-end"
|
|
||||||
]}
|
|
||||||
flex="1 0 auto"
|
|
||||||
>
|
|
||||||
{config.cache.show_text && data && !error && (
|
{config.cache.show_text && data && !error && (
|
||||||
<>
|
<>
|
||||||
{!isSm && (
|
{!isSm && (
|
||||||
@@ -258,14 +235,13 @@ export const Result = forwardRef(
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
<Tooltip
|
<Tooltip
|
||||||
display={data?.cached ? null : "none"}
|
display={data?.cached ? null : 'none'}
|
||||||
hasArrow
|
hasArrow
|
||||||
label={config.web.text.cache_icon.format({
|
label={config.web.text.cache_icon.format({
|
||||||
time: data?.timestamp
|
time: data?.timestamp,
|
||||||
})}
|
})}
|
||||||
placement="top"
|
placement="top">
|
||||||
>
|
<Box ml={1} display={data?.cached ? 'block' : 'none'}>
|
||||||
<Box ml={1} display={data?.cached ? "block" : "none"}>
|
|
||||||
<BsLightningFill color={color[colorMode]} />
|
<BsLightningFill color={color[colorMode]} />
|
||||||
</Box>
|
</Box>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
@@ -282,5 +258,5 @@ export const Result = forwardRef(
|
|||||||
</AccordionPanel>
|
</AccordionPanel>
|
||||||
</AccordionItem>
|
</AccordionItem>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,35 +1,27 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import {
|
import { AccordionIcon, Icon, Spinner, Stack, Text, Tooltip, useColorMode } from '@chakra-ui/core';
|
||||||
AccordionIcon,
|
import format from 'string-format';
|
||||||
Icon,
|
import { useConfig } from 'app/context';
|
||||||
Spinner,
|
|
||||||
Stack,
|
|
||||||
Text,
|
|
||||||
Tooltip,
|
|
||||||
useColorMode
|
|
||||||
} from "@chakra-ui/core";
|
|
||||||
import format from "string-format";
|
|
||||||
import { useConfig } from "app/context";
|
|
||||||
|
|
||||||
format.extend(String.prototype, {});
|
format.extend(String.prototype, {});
|
||||||
|
|
||||||
const runtimeText = (runtime, text) => {
|
const runtimeText = (runtime, text) => {
|
||||||
let unit;
|
let unit;
|
||||||
if (runtime === 1) {
|
if (runtime === 1) {
|
||||||
unit = "second";
|
unit = 'second';
|
||||||
} else {
|
} else {
|
||||||
unit = "seconds";
|
unit = 'seconds';
|
||||||
}
|
}
|
||||||
const fmt = text.format({ seconds: runtime });
|
const fmt = text.format({ seconds: runtime });
|
||||||
return `${fmt} ${unit}`;
|
return `${fmt} ${unit}`;
|
||||||
};
|
};
|
||||||
|
|
||||||
const statusColor = { dark: "primary.300", light: "primary.500" };
|
const statusColor = { dark: 'primary.300', light: 'primary.500' };
|
||||||
const warningColor = { dark: 300, light: 500 };
|
const warningColor = { dark: 300, light: 500 };
|
||||||
const defaultStatusColor = {
|
const defaultStatusColor = {
|
||||||
dark: "success.300",
|
dark: 'success.300',
|
||||||
light: "success.500"
|
light: 'success.500',
|
||||||
};
|
};
|
||||||
|
|
||||||
export const ResultHeader = forwardRef(
|
export const ResultHeader = forwardRef(
|
||||||
@@ -53,19 +45,13 @@ export const ResultHeader = forwardRef(
|
|||||||
<Tooltip
|
<Tooltip
|
||||||
hasArrow
|
hasArrow
|
||||||
label={runtimeText(runtime, config.web.text.complete_time)}
|
label={runtimeText(runtime, config.web.text.complete_time)}
|
||||||
placement="top"
|
placement="top">
|
||||||
>
|
<Icon name="check" color={defaultStatusColor[colorMode]} mr={4} size={6} />
|
||||||
<Icon
|
|
||||||
name="check"
|
|
||||||
color={defaultStatusColor[colorMode]}
|
|
||||||
mr={4}
|
|
||||||
size={6}
|
|
||||||
/>
|
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
)}
|
)}
|
||||||
<Text fontSize="lg">{title}</Text>
|
<Text fontSize="lg">{title}</Text>
|
||||||
<AccordionIcon ml="auto" />
|
<AccordionIcon ml="auto" />
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,9 +1,9 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useState } from "react";
|
import { useState } from 'react';
|
||||||
import { Accordion, Box, Stack, useTheme } from "@chakra-ui/core";
|
import { Accordion, Box, Stack, useTheme } from '@chakra-ui/core';
|
||||||
import { motion, AnimatePresence } from "framer-motion";
|
import { motion, AnimatePresence } from 'framer-motion';
|
||||||
import { Label, Result } from "app/components";
|
import { Label, Result } from 'app/components';
|
||||||
import { useConfig, useMedia } from "app/context";
|
import { useConfig, useMedia } from 'app/context';
|
||||||
|
|
||||||
const AnimatedResult = motion.custom(Result);
|
const AnimatedResult = motion.custom(Result);
|
||||||
const AnimatedLabel = motion.custom(Label);
|
const AnimatedLabel = motion.custom(Label);
|
||||||
@@ -13,40 +13,40 @@ const labelInitial = {
|
|||||||
sm: { opacity: 0, x: -100 },
|
sm: { opacity: 0, x: -100 },
|
||||||
md: { opacity: 0, x: -100 },
|
md: { opacity: 0, x: -100 },
|
||||||
lg: { opacity: 0, x: -100 },
|
lg: { opacity: 0, x: -100 },
|
||||||
xl: { opacity: 0, x: -100 }
|
xl: { opacity: 0, x: -100 },
|
||||||
},
|
},
|
||||||
center: {
|
center: {
|
||||||
sm: { opacity: 0 },
|
sm: { opacity: 0 },
|
||||||
md: { opacity: 0 },
|
md: { opacity: 0 },
|
||||||
lg: { opacity: 0 },
|
lg: { opacity: 0 },
|
||||||
xl: { opacity: 0 }
|
xl: { opacity: 0 },
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
sm: { opacity: 0, x: 100 },
|
sm: { opacity: 0, x: 100 },
|
||||||
md: { opacity: 0, x: 100 },
|
md: { opacity: 0, x: 100 },
|
||||||
lg: { opacity: 0, x: 100 },
|
lg: { opacity: 0, x: 100 },
|
||||||
xl: { opacity: 0, x: 100 }
|
xl: { opacity: 0, x: 100 },
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
const labelAnimate = {
|
const labelAnimate = {
|
||||||
left: {
|
left: {
|
||||||
sm: { opacity: 1, x: 0 },
|
sm: { opacity: 1, x: 0 },
|
||||||
md: { opacity: 1, x: 0 },
|
md: { opacity: 1, x: 0 },
|
||||||
lg: { opacity: 1, x: 0 },
|
lg: { opacity: 1, x: 0 },
|
||||||
xl: { opacity: 1, x: 0 }
|
xl: { opacity: 1, x: 0 },
|
||||||
},
|
},
|
||||||
center: {
|
center: {
|
||||||
sm: { opacity: 1 },
|
sm: { opacity: 1 },
|
||||||
md: { opacity: 1 },
|
md: { opacity: 1 },
|
||||||
lg: { opacity: 1 },
|
lg: { opacity: 1 },
|
||||||
xl: { opacity: 1 }
|
xl: { opacity: 1 },
|
||||||
},
|
},
|
||||||
right: {
|
right: {
|
||||||
sm: { opacity: 1, x: 0 },
|
sm: { opacity: 1, x: 0 },
|
||||||
md: { opacity: 1, x: 0 },
|
md: { opacity: 1, x: 0 },
|
||||||
lg: { opacity: 1, x: 0 },
|
lg: { opacity: 1, x: 0 },
|
||||||
xl: { opacity: 1, x: 0 }
|
xl: { opacity: 1, x: 0 },
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Results = ({
|
export const Results = ({
|
||||||
@@ -61,20 +61,18 @@ export const Results = ({
|
|||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const { mediaSize } = useMedia();
|
const { mediaSize } = useMedia();
|
||||||
const matchedVrf =
|
const matchedVrf =
|
||||||
config.vrfs.filter(v => v.id === queryVrf)[0] ??
|
config.vrfs.filter(v => v.id === queryVrf)[0] ?? config.vrfs.filter(v => v.id === 'default')[0];
|
||||||
config.vrfs.filter(v => v.id === "default")[0];
|
|
||||||
const [resultsComplete, setComplete] = useState(null);
|
const [resultsComplete, setComplete] = useState(null);
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Box
|
<Box
|
||||||
maxW={["100%", "100%", "75%", "50%"]}
|
maxW={['100%', '100%', '75%', '50%']}
|
||||||
w="100%"
|
w="100%"
|
||||||
p={0}
|
p={0}
|
||||||
mx="auto"
|
mx="auto"
|
||||||
my={4}
|
my={4}
|
||||||
textAlign="left"
|
textAlign="left"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<Stack isInline align="center" justify="center" mt={4} flexWrap="wrap">
|
<Stack isInline align="center" justify="center" mt={4} flexWrap="wrap">
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{queryLocation && (
|
{queryLocation && (
|
||||||
@@ -87,7 +85,7 @@ export const Results = ({
|
|||||||
label={config.web.text.query_type}
|
label={config.web.text.query_type}
|
||||||
value={config.queries[queryType].display_name}
|
value={config.queries[queryType].display_name}
|
||||||
valueBg={theme.colors.cyan[500]}
|
valueBg={theme.colors.cyan[500]}
|
||||||
fontSize={["xs", "sm", "sm", "sm"]}
|
fontSize={['xs', 'sm', 'sm', 'sm']}
|
||||||
/>
|
/>
|
||||||
<AnimatedLabel
|
<AnimatedLabel
|
||||||
initial={labelInitial.center[mediaSize]}
|
initial={labelInitial.center[mediaSize]}
|
||||||
@@ -97,7 +95,7 @@ export const Results = ({
|
|||||||
label={config.web.text.query_target}
|
label={config.web.text.query_target}
|
||||||
value={queryTarget}
|
value={queryTarget}
|
||||||
valueBg={theme.colors.teal[600]}
|
valueBg={theme.colors.teal[600]}
|
||||||
fontSize={["xs", "sm", "sm", "sm"]}
|
fontSize={['xs', 'sm', 'sm', 'sm']}
|
||||||
/>
|
/>
|
||||||
<AnimatedLabel
|
<AnimatedLabel
|
||||||
initial={labelInitial.right[mediaSize]}
|
initial={labelInitial.right[mediaSize]}
|
||||||
@@ -107,7 +105,7 @@ export const Results = ({
|
|||||||
label={config.web.text.query_vrf}
|
label={config.web.text.query_vrf}
|
||||||
value={matchedVrf.display_name}
|
value={matchedVrf.display_name}
|
||||||
valueBg={theme.colors.blue[500]}
|
valueBg={theme.colors.blue[500]}
|
||||||
fontSize={["xs", "sm", "sm", "sm"]}
|
fontSize={['xs', 'sm', 'sm', 'sm']}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
@@ -115,7 +113,7 @@ export const Results = ({
|
|||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
maxW={["100%", "100%", "75%", "75%"]}
|
maxW={['100%', '100%', '75%', '75%']}
|
||||||
w="100%"
|
w="100%"
|
||||||
p={0}
|
p={0}
|
||||||
mx="auto"
|
mx="auto"
|
||||||
@@ -123,15 +121,13 @@ export const Results = ({
|
|||||||
textAlign="left"
|
textAlign="left"
|
||||||
borderWidth="1px"
|
borderWidth="1px"
|
||||||
rounded="lg"
|
rounded="lg"
|
||||||
overflow="hidden"
|
overflow="hidden">
|
||||||
>
|
|
||||||
<Accordion
|
<Accordion
|
||||||
allowMultiple
|
allowMultiple
|
||||||
initial={{ opacity: 1 }}
|
initial={{ opacity: 1 }}
|
||||||
transition={{ duration: 0.3 }}
|
transition={{ duration: 0.3 }}
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
exit={{ opacity: 0, y: 300 }}
|
exit={{ opacity: 0, y: 300 }}>
|
||||||
>
|
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{queryLocation &&
|
{queryLocation &&
|
||||||
queryLocation.map((loc, i) => (
|
queryLocation.map((loc, i) => (
|
||||||
|
@@ -1,63 +1,57 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import {
|
import { Box, PseudoBox, Spinner, useColorMode, useTheme } from '@chakra-ui/core';
|
||||||
Box,
|
import { FiSearch } from '@meronex/icons/fi';
|
||||||
PseudoBox,
|
import { opposingColor } from 'app/util';
|
||||||
Spinner,
|
|
||||||
useColorMode,
|
|
||||||
useTheme
|
|
||||||
} from "@chakra-ui/core";
|
|
||||||
import { FiSearch } from "@meronex/icons/fi";
|
|
||||||
import { opposingColor } from "app/util";
|
|
||||||
|
|
||||||
const btnProps = {
|
const btnProps = {
|
||||||
display: "inline-flex",
|
display: 'inline-flex',
|
||||||
appearance: "none",
|
appearance: 'none',
|
||||||
alignItems: "center",
|
alignItems: 'center',
|
||||||
justifyContent: "center",
|
justifyContent: 'center',
|
||||||
transition: "all 250ms",
|
transition: 'all 250ms',
|
||||||
userSelect: "none",
|
userSelect: 'none',
|
||||||
position: "relative",
|
position: 'relative',
|
||||||
whiteSpace: "nowrap",
|
whiteSpace: 'nowrap',
|
||||||
verticalAlign: "middle",
|
verticalAlign: 'middle',
|
||||||
lineHeight: "1.2",
|
lineHeight: '1.2',
|
||||||
outline: "none",
|
outline: 'none',
|
||||||
as: "button",
|
as: 'button',
|
||||||
type: "submit",
|
type: 'submit',
|
||||||
borderRadius: "md",
|
borderRadius: 'md',
|
||||||
fontWeight: "semibold"
|
fontWeight: 'semibold',
|
||||||
};
|
};
|
||||||
|
|
||||||
const btnSizeMap = {
|
const btnSizeMap = {
|
||||||
lg: {
|
lg: {
|
||||||
height: 12,
|
height: 12,
|
||||||
minWidth: 12,
|
minWidth: 12,
|
||||||
fontSize: "lg",
|
fontSize: 'lg',
|
||||||
px: 6
|
px: 6,
|
||||||
},
|
},
|
||||||
md: {
|
md: {
|
||||||
height: 10,
|
height: 10,
|
||||||
minWidth: 10,
|
minWidth: 10,
|
||||||
fontSize: "md",
|
fontSize: 'md',
|
||||||
px: 4
|
px: 4,
|
||||||
},
|
},
|
||||||
sm: {
|
sm: {
|
||||||
height: 8,
|
height: 8,
|
||||||
minWidth: 8,
|
minWidth: 8,
|
||||||
fontSize: "sm",
|
fontSize: 'sm',
|
||||||
px: 3
|
px: 3,
|
||||||
},
|
},
|
||||||
xs: {
|
xs: {
|
||||||
height: 6,
|
height: 6,
|
||||||
minWidth: 6,
|
minWidth: 6,
|
||||||
fontSize: "xs",
|
fontSize: 'xs',
|
||||||
px: 2
|
px: 2,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const btnBg = { dark: "primary.300", light: "primary.500" };
|
const btnBg = { dark: 'primary.300', light: 'primary.500' };
|
||||||
const btnBgActive = { dark: "primary.400", light: "primary.600" };
|
const btnBgActive = { dark: 'primary.400', light: 'primary.600' };
|
||||||
const btnBgHover = { dark: "primary.200", light: "primary.400" };
|
const btnBgHover = { dark: 'primary.200', light: 'primary.400' };
|
||||||
|
|
||||||
export const SubmitButton = forwardRef(
|
export const SubmitButton = forwardRef(
|
||||||
(
|
(
|
||||||
@@ -66,12 +60,12 @@ export const SubmitButton = forwardRef(
|
|||||||
isDisabled = false,
|
isDisabled = false,
|
||||||
isActive = false,
|
isActive = false,
|
||||||
isFullWidth = false,
|
isFullWidth = false,
|
||||||
size = "lg",
|
size = 'lg',
|
||||||
loadingText,
|
loadingText,
|
||||||
children,
|
children,
|
||||||
...props
|
...props
|
||||||
},
|
},
|
||||||
ref
|
ref,
|
||||||
) => {
|
) => {
|
||||||
const _isDisabled = isDisabled || isLoading;
|
const _isDisabled = isDisabled || isLoading;
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
@@ -86,8 +80,8 @@ export const SubmitButton = forwardRef(
|
|||||||
disabled={_isDisabled}
|
disabled={_isDisabled}
|
||||||
aria-disabled={_isDisabled}
|
aria-disabled={_isDisabled}
|
||||||
aria-label="Submit Query"
|
aria-label="Submit Query"
|
||||||
width={isFullWidth ? "full" : undefined}
|
width={isFullWidth ? 'full' : undefined}
|
||||||
data-active={isActive ? "true" : undefined}
|
data-active={isActive ? 'true' : undefined}
|
||||||
bg={btnBg[colorMode]}
|
bg={btnBg[colorMode]}
|
||||||
color={btnColor}
|
color={btnColor}
|
||||||
_active={{ bg: btnBgActive[colorMode], color: btnColorActive }}
|
_active={{ bg: btnBgActive[colorMode], color: btnColorActive }}
|
||||||
@@ -95,11 +89,10 @@ export const SubmitButton = forwardRef(
|
|||||||
_focus={{ boxShadow: theme.shadows.outline }}
|
_focus={{ boxShadow: theme.shadows.outline }}
|
||||||
{...btnProps}
|
{...btnProps}
|
||||||
{...btnSize}
|
{...btnSize}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Spinner
|
<Spinner
|
||||||
position={loadingText ? "relative" : "absolute"}
|
position={loadingText ? 'relative' : 'absolute'}
|
||||||
mr={loadingText ? 2 : 0}
|
mr={loadingText ? 2 : 0}
|
||||||
color="currentColor"
|
color="currentColor"
|
||||||
size="1em"
|
size="1em"
|
||||||
@@ -116,5 +109,5 @@ export const SubmitButton = forwardRef(
|
|||||||
: children}
|
: children}
|
||||||
</PseudoBox>
|
</PseudoBox>
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
@@ -1,16 +1,16 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { useMemo } from "react";
|
import { useMemo } from 'react';
|
||||||
import { Flex, Icon, Text } from "@chakra-ui/core";
|
import { Flex, Icon, Text } from '@chakra-ui/core';
|
||||||
import { usePagination, useSortBy, useTable } from "react-table";
|
import { usePagination, useSortBy, useTable } from 'react-table';
|
||||||
import { useMedia } from "app/context";
|
import { useMedia } from 'app/context';
|
||||||
import { CardBody, CardFooter, CardHeader } from "app/components";
|
import { CardBody, CardFooter, CardHeader } from 'app/components';
|
||||||
import { TableMain } from "./TableMain";
|
import { TableMain } from './TableMain';
|
||||||
import { TableCell } from "./TableCell";
|
import { TableCell } from './TableCell';
|
||||||
import { TableHead } from "./TableHead";
|
import { TableHead } from './TableHead';
|
||||||
import { TableRow } from "./TableRow";
|
import { TableRow } from './TableRow';
|
||||||
import { TableBody } from "./TableBody";
|
import { TableBody } from './TableBody';
|
||||||
import { TableIconButton } from "./TableIconButton";
|
import { TableIconButton } from './TableIconButton';
|
||||||
import { TableSelectShow } from "./TableSelectShow";
|
import { TableSelectShow } from './TableSelectShow';
|
||||||
|
|
||||||
export const Table = ({
|
export const Table = ({
|
||||||
columns,
|
columns,
|
||||||
@@ -24,7 +24,7 @@ export const Table = ({
|
|||||||
cellRender = null,
|
cellRender = null,
|
||||||
rowHighlightProp,
|
rowHighlightProp,
|
||||||
rowHighlightBg,
|
rowHighlightBg,
|
||||||
rowHighlightColor
|
rowHighlightColor,
|
||||||
}) => {
|
}) => {
|
||||||
const tableColumns = useMemo(() => columns, [columns]);
|
const tableColumns = useMemo(() => columns, [columns]);
|
||||||
|
|
||||||
@@ -34,9 +34,9 @@ export const Table = ({
|
|||||||
() => ({
|
() => ({
|
||||||
minWidth: 100,
|
minWidth: 100,
|
||||||
width: 150,
|
width: 150,
|
||||||
maxWidth: 300
|
maxWidth: 300,
|
||||||
}),
|
}),
|
||||||
[]
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
let hiddenColumns = [];
|
let hiddenColumns = [];
|
||||||
@@ -60,7 +60,7 @@ export const Table = ({
|
|||||||
nextPage,
|
nextPage,
|
||||||
previousPage,
|
previousPage,
|
||||||
setPageSize,
|
setPageSize,
|
||||||
state: { pageIndex, pageSize }
|
state: { pageIndex, pageSize },
|
||||||
} = useTable(
|
} = useTable(
|
||||||
{
|
{
|
||||||
columns: tableColumns,
|
columns: tableColumns,
|
||||||
@@ -69,11 +69,11 @@ export const Table = ({
|
|||||||
initialState: {
|
initialState: {
|
||||||
pageIndex: 0,
|
pageIndex: 0,
|
||||||
pageSize: initialPageSize,
|
pageSize: initialPageSize,
|
||||||
hiddenColumns: hiddenColumns
|
hiddenColumns: hiddenColumns,
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
useSortBy,
|
useSortBy,
|
||||||
usePagination
|
usePagination,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -82,20 +82,16 @@ export const Table = ({
|
|||||||
<TableMain {...getTableProps()}>
|
<TableMain {...getTableProps()}>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
{headerGroups.map(headerGroup => (
|
{headerGroups.map(headerGroup => (
|
||||||
<TableRow
|
<TableRow key={headerGroup.id} {...headerGroup.getHeaderGroupProps()}>
|
||||||
key={headerGroup.id}
|
|
||||||
{...headerGroup.getHeaderGroupProps()}
|
|
||||||
>
|
|
||||||
{headerGroup.headers.map(column => (
|
{headerGroup.headers.map(column => (
|
||||||
<TableCell
|
<TableCell
|
||||||
as="th"
|
as="th"
|
||||||
align={column.align}
|
align={column.align}
|
||||||
key={column.id}
|
key={column.id}
|
||||||
{...column.getHeaderProps()}
|
{...column.getHeaderProps()}
|
||||||
{...column.getSortByToggleProps()}
|
{...column.getSortByToggleProps()}>
|
||||||
>
|
|
||||||
<Text fontSize="sm" fontWeight="bold" display="inline-block">
|
<Text fontSize="sm" fontWeight="bold" display="inline-block">
|
||||||
{column.render("Header")}
|
{column.render('Header')}
|
||||||
</Text>
|
</Text>
|
||||||
{column.isSorted ? (
|
{column.isSorted ? (
|
||||||
column.isSortedDesc ? (
|
column.isSortedDesc ? (
|
||||||
@@ -104,7 +100,7 @@ export const Table = ({
|
|||||||
<Icon name="chevron-up" size={4} ml={1} />
|
<Icon name="chevron-up" size={4} ml={1} />
|
||||||
)
|
)
|
||||||
) : (
|
) : (
|
||||||
""
|
''
|
||||||
)}
|
)}
|
||||||
</TableCell>
|
</TableCell>
|
||||||
))}
|
))}
|
||||||
@@ -124,8 +120,7 @@ export const Table = ({
|
|||||||
highlight={row.values[rowHighlightProp] ?? false}
|
highlight={row.values[rowHighlightProp] ?? false}
|
||||||
highlightBg={rowHighlightBg}
|
highlightBg={rowHighlightBg}
|
||||||
highlightColor={rowHighlightColor}
|
highlightColor={rowHighlightColor}
|
||||||
{...row.getRowProps()}
|
{...row.getRowProps()}>
|
||||||
>
|
|
||||||
{row.cells.map((cell, i) => {
|
{row.cells.map((cell, i) => {
|
||||||
return (
|
return (
|
||||||
<TableCell
|
<TableCell
|
||||||
@@ -133,14 +128,13 @@ export const Table = ({
|
|||||||
cell={cell}
|
cell={cell}
|
||||||
bordersVertical={[bordersVertical, i]}
|
bordersVertical={[bordersVertical, i]}
|
||||||
key={cell.row.index}
|
key={cell.row.index}
|
||||||
{...cell.getCellProps()}
|
{...cell.getCellProps()}>
|
||||||
>
|
{cell.render(cellRender ?? 'Cell')}
|
||||||
{cell.render(cellRender ?? "Cell")}
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</TableRow>
|
</TableRow>
|
||||||
)
|
),
|
||||||
)}
|
)}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</TableMain>
|
</TableMain>
|
||||||
@@ -161,10 +155,10 @@ export const Table = ({
|
|||||||
</Flex>
|
</Flex>
|
||||||
<Flex justifyContent="center" alignItems="center">
|
<Flex justifyContent="center" alignItems="center">
|
||||||
<Text fontSize="sm" mr={4} whiteSpace="nowrap">
|
<Text fontSize="sm" mr={4} whiteSpace="nowrap">
|
||||||
Page{" "}
|
Page{' '}
|
||||||
<strong>
|
<strong>
|
||||||
{pageIndex + 1} of {pageOptions.length}
|
{pageIndex + 1} of {pageOptions.length}
|
||||||
</strong>{" "}
|
</strong>{' '}
|
||||||
</Text>
|
</Text>
|
||||||
{!(isSm || isMd) && (
|
{!(isSm || isMd) && (
|
||||||
<TableSelectShow
|
<TableSelectShow
|
||||||
|
@@ -1,18 +1,17 @@
|
|||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx } from "@emotion/core";
|
import { jsx } from '@emotion/core';
|
||||||
import { Box, css } from "@chakra-ui/core";
|
import { Box, css } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const TableBody = ({ children, ...props }) => (
|
export const TableBody = ({ children, ...props }) => (
|
||||||
<Box
|
<Box
|
||||||
as="tbody"
|
as="tbody"
|
||||||
overflowY="scroll"
|
overflowY="scroll"
|
||||||
css={css({
|
css={css({
|
||||||
"&::-webkit-scrollbar": { display: "none" },
|
'&::-webkit-scrollbar': { display: 'none' },
|
||||||
"&": { msOverflowStyle: "none" }
|
'&': { msOverflowStyle: 'none' },
|
||||||
})}
|
})}
|
||||||
overflowX="hidden"
|
overflowX="hidden"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@@ -1,18 +1,12 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Box, useColorMode } from "@chakra-ui/core";
|
import { Box, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const cellBorder = {
|
const cellBorder = {
|
||||||
dark: { borderLeft: "1px", borderLeftColor: "whiteAlpha.100" },
|
dark: { borderLeft: '1px', borderLeftColor: 'whiteAlpha.100' },
|
||||||
light: { borderLeft: "1px", borderLeftColor: "blackAlpha.100" }
|
light: { borderLeft: '1px', borderLeftColor: 'blackAlpha.100' },
|
||||||
};
|
};
|
||||||
|
|
||||||
export const TableCell = ({
|
export const TableCell = ({ bordersVertical = [false, 0, 0], align, cell, children, ...props }) => {
|
||||||
bordersVertical = [false, 0, 0],
|
|
||||||
align,
|
|
||||||
cell,
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}) => {
|
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const [doVerticalBorders, index] = bordersVertical;
|
const [doVerticalBorders, index] = bordersVertical;
|
||||||
let borderProps = {};
|
let borderProps = {};
|
||||||
@@ -28,8 +22,7 @@ export const TableCell = ({
|
|||||||
whiteSpace="nowrap"
|
whiteSpace="nowrap"
|
||||||
textAlign={align}
|
textAlign={align}
|
||||||
{...borderProps}
|
{...borderProps}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@@ -1,18 +1,12 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Box, useColorMode } from "@chakra-ui/core";
|
import { Box, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const bg = { dark: "whiteAlpha.100", light: "blackAlpha.100" };
|
const bg = { dark: 'whiteAlpha.100', light: 'blackAlpha.100' };
|
||||||
|
|
||||||
export const TableHead = ({ children, ...props }) => {
|
export const TableHead = ({ children, ...props }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
return (
|
return (
|
||||||
<Box
|
<Box as="thead" overflowX="hidden" overflowY="auto" bg={bg[colorMode]} {...props}>
|
||||||
as="thead"
|
|
||||||
overflowX="hidden"
|
|
||||||
overflowY="auto"
|
|
||||||
bg={bg[colorMode]}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@@ -1,14 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { IconButton } from "@chakra-ui/core";
|
import { IconButton } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const TableIconButton = ({
|
export const TableIconButton = ({ icon, onClick, isDisabled, color, children, ...props }) => (
|
||||||
icon,
|
|
||||||
onClick,
|
|
||||||
isDisabled,
|
|
||||||
color,
|
|
||||||
children,
|
|
||||||
...props
|
|
||||||
}) => (
|
|
||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
icon={icon}
|
icon={icon}
|
||||||
@@ -17,8 +10,7 @@ export const TableIconButton = ({
|
|||||||
variantColor={color}
|
variantColor={color}
|
||||||
isDisabled={isDisabled}
|
isDisabled={isDisabled}
|
||||||
aria-label="Table Icon Button"
|
aria-label="Table Icon Button"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</IconButton>
|
</IconButton>
|
||||||
);
|
);
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx } from "@emotion/core";
|
import { jsx } from '@emotion/core';
|
||||||
import { Box, css, useTheme, useColorMode } from "@chakra-ui/core";
|
import { Box, css, useTheme, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const scrollbar = { dark: "whiteAlpha.300", light: "blackAlpha.300" };
|
const scrollbar = { dark: 'whiteAlpha.300', light: 'blackAlpha.300' };
|
||||||
const scrollbarHover = { dark: "whiteAlpha.400", light: "blackAlpha.400" };
|
const scrollbarHover = { dark: 'whiteAlpha.400', light: 'blackAlpha.400' };
|
||||||
const scrollbarBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
const scrollbarBg = { dark: 'whiteAlpha.50', light: 'blackAlpha.50' };
|
||||||
|
|
||||||
export const TableMain = ({ children, ...props }) => {
|
export const TableMain = ({ children, ...props }) => {
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
@@ -14,24 +14,23 @@ export const TableMain = ({ children, ...props }) => {
|
|||||||
as="table"
|
as="table"
|
||||||
display="block"
|
display="block"
|
||||||
css={css({
|
css={css({
|
||||||
"&::-webkit-scrollbar": { height: "5px" },
|
'&::-webkit-scrollbar': { height: '5px' },
|
||||||
"&::-webkit-scrollbar-track": {
|
'&::-webkit-scrollbar-track': {
|
||||||
backgroundColor: scrollbarBg[colorMode]
|
backgroundColor: scrollbarBg[colorMode],
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb": {
|
'&::-webkit-scrollbar-thumb': {
|
||||||
backgroundColor: scrollbar[colorMode]
|
backgroundColor: scrollbar[colorMode],
|
||||||
},
|
},
|
||||||
"&::-webkit-scrollbar-thumb:hover": {
|
'&::-webkit-scrollbar-thumb:hover': {
|
||||||
backgroundColor: scrollbarHover[colorMode]
|
backgroundColor: scrollbarHover[colorMode],
|
||||||
},
|
},
|
||||||
|
|
||||||
"-ms-overflow-style": { display: "none" }
|
'-ms-overflow-style': { display: 'none' },
|
||||||
})(theme)}
|
})(theme)}
|
||||||
overflowX="auto"
|
overflowX="auto"
|
||||||
borderRadius="md"
|
borderRadius="md"
|
||||||
boxSizing="border-box"
|
boxSizing="border-box"
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
@@ -1,19 +1,19 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { PseudoBox, useColorMode, useTheme } from "@chakra-ui/core";
|
import { PseudoBox, useColorMode, useTheme } from '@chakra-ui/core';
|
||||||
import { opposingColor } from "app/util";
|
import { opposingColor } from 'app/util';
|
||||||
|
|
||||||
const hoverBg = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
const hoverBg = { dark: 'whiteAlpha.50', light: 'blackAlpha.50' };
|
||||||
const bgStripe = { dark: "whiteAlpha.50", light: "blackAlpha.50" };
|
const bgStripe = { dark: 'whiteAlpha.50', light: 'blackAlpha.50' };
|
||||||
const rowBorder = {
|
const rowBorder = {
|
||||||
dark: { borderTop: "1px", borderTopColor: "whiteAlpha.100" },
|
dark: { borderTop: '1px', borderTopColor: 'whiteAlpha.100' },
|
||||||
light: { borderTop: "1px", borderTopColor: "blackAlpha.100" }
|
light: { borderTop: '1px', borderTopColor: 'blackAlpha.100' },
|
||||||
};
|
};
|
||||||
const alphaMap = { dark: "200", light: "100" };
|
const alphaMap = { dark: '200', light: '100' };
|
||||||
const alphaMapHover = { dark: "100", light: "200" };
|
const alphaMapHover = { dark: '100', light: '200' };
|
||||||
|
|
||||||
export const TableRow = ({
|
export const TableRow = ({
|
||||||
highlight = false,
|
highlight = false,
|
||||||
highlightBg = "primary",
|
highlightBg = 'primary',
|
||||||
doStripe = false,
|
doStripe = false,
|
||||||
doHorizontalBorders = false,
|
doHorizontalBorders = false,
|
||||||
index = 0,
|
index = 0,
|
||||||
@@ -31,23 +31,21 @@ export const TableRow = ({
|
|||||||
}
|
}
|
||||||
const color = highlight ? opposingColor(theme, bg) : null;
|
const color = highlight ? opposingColor(theme, bg) : null;
|
||||||
|
|
||||||
const borderProps =
|
const borderProps = doHorizontalBorders && index !== 0 ? rowBorder[colorMode] : {};
|
||||||
doHorizontalBorders && index !== 0 ? rowBorder[colorMode] : {};
|
|
||||||
return (
|
return (
|
||||||
<PseudoBox
|
<PseudoBox
|
||||||
as="tr"
|
as="tr"
|
||||||
_hover={{
|
_hover={{
|
||||||
cursor: "pointer",
|
cursor: 'pointer',
|
||||||
backgroundColor: highlight
|
backgroundColor: highlight
|
||||||
? `${highlightBg}.${alphaMapHover[colorMode]}`
|
? `${highlightBg}.${alphaMapHover[colorMode]}`
|
||||||
: hoverBg[colorMode]
|
: hoverBg[colorMode],
|
||||||
}}
|
}}
|
||||||
bg={bg}
|
bg={bg}
|
||||||
color={color}
|
color={color}
|
||||||
fontWeight={highlight ? "bold" : null}
|
fontWeight={highlight ? 'bold' : null}
|
||||||
{...borderProps}
|
{...borderProps}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children}
|
{children}
|
||||||
</PseudoBox>
|
</PseudoBox>
|
||||||
);
|
);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { Select } from "@chakra-ui/core";
|
import { Select } from '@chakra-ui/core';
|
||||||
|
|
||||||
export const TableSelectShow = ({ value, onChange, children, ...props }) => (
|
export const TableSelectShow = ({ value, onChange, children, ...props }) => (
|
||||||
<Select size="sm" onChange={onChange} {...props}>
|
<Select size="sm" onChange={onChange} {...props}>
|
||||||
|
@@ -1,8 +1,8 @@
|
|||||||
export * from "./Table";
|
export * from './Table';
|
||||||
export * from "./TableBody";
|
export * from './TableBody';
|
||||||
export * from "./TableCell";
|
export * from './TableCell';
|
||||||
export * from "./TableHead";
|
export * from './TableHead';
|
||||||
export * from "./TableIconButton";
|
export * from './TableIconButton';
|
||||||
export * from "./TableMain";
|
export * from './TableMain';
|
||||||
export * from "./TableRow";
|
export * from './TableRow';
|
||||||
export * from "./TableSelectShow";
|
export * from './TableSelectShow';
|
||||||
|
@@ -1,11 +1,11 @@
|
|||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx } from "@emotion/core";
|
import { jsx } from '@emotion/core';
|
||||||
import { Box, css, useColorMode } from "@chakra-ui/core";
|
import { Box, css, useColorMode } from '@chakra-ui/core';
|
||||||
|
|
||||||
const bg = { dark: "gray.800", light: "blackAlpha.100" };
|
const bg = { dark: 'gray.800', light: 'blackAlpha.100' };
|
||||||
const color = { dark: "white", light: "black" };
|
const color = { dark: 'white', light: 'black' };
|
||||||
const selectionBg = { dark: "white", light: "black" };
|
const selectionBg = { dark: 'white', light: 'black' };
|
||||||
const selectionColor = { dark: "black", light: "white" };
|
const selectionColor = { dark: 'black', light: 'white' };
|
||||||
|
|
||||||
export const TextOutput = ({ children, ...props }) => {
|
export const TextOutput = ({ children, ...props }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
@@ -25,17 +25,16 @@ export const TextOutput = ({ children, ...props }) => {
|
|||||||
whiteSpace="pre-wrap"
|
whiteSpace="pre-wrap"
|
||||||
as="pre"
|
as="pre"
|
||||||
css={css({
|
css={css({
|
||||||
"&::selection": {
|
'&::selection': {
|
||||||
backgroundColor: selectionBg[colorMode],
|
backgroundColor: selectionBg[colorMode],
|
||||||
color: selectionColor[colorMode]
|
color: selectionColor[colorMode],
|
||||||
}
|
},
|
||||||
})}
|
})}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{children
|
{children
|
||||||
.split("\\n")
|
.split('\\n')
|
||||||
.join("\n")
|
.join('\n')
|
||||||
.replace(/\n\n/g, "\n")}
|
.replace(/\n\n/g, '\n')}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@@ -1,31 +1,25 @@
|
|||||||
/** @jsx jsx */
|
/** @jsx jsx */
|
||||||
import { jsx } from "@emotion/core";
|
import { jsx } from '@emotion/core';
|
||||||
import { forwardRef } from "react";
|
import { forwardRef } from 'react';
|
||||||
import { Button, Heading, Image, Stack, useColorMode } from "@chakra-ui/core";
|
import { Button, Heading, Image, Stack, useColorMode } from '@chakra-ui/core';
|
||||||
import { useConfig, useMedia } from "app/context";
|
import { useConfig, useMedia } from 'app/context';
|
||||||
|
|
||||||
const titleSize = { true: ["2xl", "2xl", "5xl", "5xl"], false: "2xl" };
|
const titleSize = { true: ['2xl', '2xl', '5xl', '5xl'], false: '2xl' };
|
||||||
const titleMargin = { true: 2, false: 0 };
|
const titleMargin = { true: 2, false: 0 };
|
||||||
const textAlignment = { false: ["right", "center"], true: ["left", "center"] };
|
const textAlignment = { false: ['right', 'center'], true: ['left', 'center'] };
|
||||||
const logoName = { light: "dark", dark: "light" };
|
const logoName = { light: 'dark', dark: 'light' };
|
||||||
const justifyMap = {
|
const justifyMap = {
|
||||||
true: ["flex-end", "center", "center", "center"],
|
true: ['flex-end', 'center', 'center', 'center'],
|
||||||
false: ["flex-start", "center", "center", "center"]
|
false: ['flex-start', 'center', 'center', 'center'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const logoFallback = {
|
const logoFallback = {
|
||||||
light:
|
light: 'https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-dark.svg',
|
||||||
"https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-dark.svg",
|
dark: 'https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-light.svg',
|
||||||
dark:
|
|
||||||
"https://res.cloudinary.com/hyperglass/image/upload/v1593916013/logo-light.svg"
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const TitleOnly = ({ text, showSubtitle }) => (
|
const TitleOnly = ({ text, showSubtitle }) => (
|
||||||
<Heading
|
<Heading as="h1" mb={titleMargin[showSubtitle]} fontSize={titleSize[showSubtitle]}>
|
||||||
as="h1"
|
|
||||||
mb={titleMargin[showSubtitle]}
|
|
||||||
fontSize={titleSize[showSubtitle]}
|
|
||||||
>
|
|
||||||
{text}
|
{text}
|
||||||
</Heading>
|
</Heading>
|
||||||
);
|
);
|
||||||
@@ -33,26 +27,18 @@ const TitleOnly = ({ text, showSubtitle }) => (
|
|||||||
const SubtitleOnly = ({ text, mediaSize, ...props }) => (
|
const SubtitleOnly = ({ text, mediaSize, ...props }) => (
|
||||||
<Heading
|
<Heading
|
||||||
as="h3"
|
as="h3"
|
||||||
fontSize={["md", "md", "xl", "xl"]}
|
fontSize={['md', 'md', 'xl', 'xl']}
|
||||||
whiteSpace="break-spaces"
|
whiteSpace="break-spaces"
|
||||||
textAlign={["left", "left", "center", "center"]}
|
textAlign={['left', 'left', 'center', 'center']}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
{text}
|
{text}
|
||||||
</Heading>
|
</Heading>
|
||||||
);
|
);
|
||||||
|
|
||||||
const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => (
|
const TextOnly = ({ text, mediaSize, showSubtitle, ...props }) => (
|
||||||
<Stack
|
<Stack spacing={2} maxW="100%" textAlign={textAlignment[showSubtitle]} {...props}>
|
||||||
spacing={2}
|
|
||||||
maxW="100%"
|
|
||||||
textAlign={textAlignment[showSubtitle]}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<TitleOnly text={text.title} showSubtitle={showSubtitle} />
|
<TitleOnly text={text.title} showSubtitle={showSubtitle} />
|
||||||
{showSubtitle && (
|
{showSubtitle && <SubtitleOnly text={text.subtitle} mediaSize={mediaSize} />}
|
||||||
<SubtitleOnly text={text.subtitle} mediaSize={mediaSize} />
|
|
||||||
)}
|
|
||||||
</Stack>
|
</Stack>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -63,15 +49,15 @@ const Logo = ({ text, logo }) => {
|
|||||||
return (
|
return (
|
||||||
<Image
|
<Image
|
||||||
css={{
|
css={{
|
||||||
userDrag: "none",
|
userDrag: 'none',
|
||||||
userSelect: "none",
|
userSelect: 'none',
|
||||||
msUserSelect: "none",
|
msUserSelect: 'none',
|
||||||
MozUserSelect: "none",
|
MozUserSelect: 'none',
|
||||||
WebkitUserDrag: "none",
|
WebkitUserDrag: 'none',
|
||||||
WebkitUserSelect: "none"
|
WebkitUserSelect: 'none',
|
||||||
}}
|
}}
|
||||||
alt={text.title}
|
alt={text.title}
|
||||||
width={width ?? "auto"}
|
width={width ?? 'auto'}
|
||||||
fallbackSrc={logoFallback[colorMode]}
|
fallbackSrc={logoFallback[colorMode]}
|
||||||
src={`/images/${logoName[colorMode]}${logoExt[colorMode]}`}
|
src={`/images/${logoName[colorMode]}${logoExt[colorMode]}`}
|
||||||
/>
|
/>
|
||||||
@@ -88,12 +74,7 @@ const LogoSubtitle = ({ text, logo, mediaSize }) => (
|
|||||||
const All = ({ text, logo, mediaSize, showSubtitle }) => (
|
const All = ({ text, logo, mediaSize, showSubtitle }) => (
|
||||||
<>
|
<>
|
||||||
<Logo text={text} logo={logo} />
|
<Logo text={text} logo={logo} />
|
||||||
<TextOnly
|
<TextOnly mediaSize={mediaSize} showSubtitle={showSubtitle} mt={2} text={text} />
|
||||||
mediaSize={mediaSize}
|
|
||||||
showSubtitle={showSubtitle}
|
|
||||||
mt={2}
|
|
||||||
text={text}
|
|
||||||
/>
|
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -101,7 +82,7 @@ const modeMap = {
|
|||||||
text_only: TextOnly,
|
text_only: TextOnly,
|
||||||
logo_only: Logo,
|
logo_only: Logo,
|
||||||
logo_subtitle: LogoSubtitle,
|
logo_subtitle: LogoSubtitle,
|
||||||
all: All
|
all: All,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const Title = forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
export const Title = forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
||||||
@@ -118,12 +99,11 @@ export const Title = forwardRef(({ onClick, isSubmitting, ...props }, ref) => {
|
|||||||
flexWrap="wrap"
|
flexWrap="wrap"
|
||||||
flexDir="column"
|
flexDir="column"
|
||||||
onClick={onClick}
|
onClick={onClick}
|
||||||
_focus={{ boxShadow: "none" }}
|
_focus={{ boxShadow: 'none' }}
|
||||||
_hover={{ textDecoration: "none" }}
|
_hover={{ textDecoration: 'none' }}
|
||||||
justifyContent={justifyMap[isSubmitting]}
|
justifyContent={justifyMap[isSubmitting]}
|
||||||
alignItems={["flex-start", "flex-start", "center"]}
|
alignItems={['flex-start', 'flex-start', 'center']}
|
||||||
{...props}
|
{...props}>
|
||||||
>
|
|
||||||
<MatchedMode
|
<MatchedMode
|
||||||
mediaSize={mediaSize}
|
mediaSize={mediaSize}
|
||||||
showSubtitle={!isSubmitting}
|
showSubtitle={!isSubmitting}
|
||||||
|
@@ -1,35 +1,35 @@
|
|||||||
export * from "./BGPTable";
|
export * from './BGPTable';
|
||||||
export * from "./CacheTimeout";
|
export * from './CacheTimeout';
|
||||||
export * from "./Card";
|
export * from './Card';
|
||||||
export * from "./ChakraSelect";
|
export * from './ChakraSelect';
|
||||||
export * from "./CodeBlock";
|
export * from './CodeBlock';
|
||||||
export * from "./ColorModeToggle";
|
export * from './ColorModeToggle';
|
||||||
export * from "./CommunitySelect";
|
export * from './CommunitySelect';
|
||||||
export * from "./CopyButton";
|
export * from './CopyButton';
|
||||||
export * from "./Debugger";
|
export * from './Debugger';
|
||||||
export * from "./Footer";
|
export * from './Footer';
|
||||||
export * from "./FormField";
|
export * from './FormField';
|
||||||
export * from "./Greeting";
|
export * from './Greeting';
|
||||||
export * from "./Header";
|
export * from './Header';
|
||||||
export * from "./HelpModal";
|
export * from './HelpModal';
|
||||||
export * from "./HyperglassForm";
|
export * from './HyperglassForm';
|
||||||
export * from "./Label";
|
export * from './Label';
|
||||||
export * from "./Layout";
|
export * from './Layout';
|
||||||
export * from "./Loading";
|
export * from './Loading';
|
||||||
export * from "./LookingGlass";
|
export * from './LookingGlass';
|
||||||
export * from "./Markdown";
|
export * from './Markdown';
|
||||||
export * from "./Meta";
|
export * from './Meta';
|
||||||
export * from "./QueryLocation";
|
export * from './QueryLocation';
|
||||||
export * from "./QueryTarget";
|
export * from './QueryTarget';
|
||||||
export * from "./QueryType";
|
export * from './QueryType';
|
||||||
export * from "./QueryVrf";
|
export * from './QueryVrf';
|
||||||
export * from "./RequeryButton";
|
export * from './RequeryButton';
|
||||||
export * from "./ResetButton";
|
export * from './ResetButton';
|
||||||
export * from "./ResolvedTarget";
|
export * from './ResolvedTarget';
|
||||||
export * from "./Result";
|
export * from './Result';
|
||||||
export * from "./ResultHeader";
|
export * from './ResultHeader';
|
||||||
export * from "./Results";
|
export * from './Results';
|
||||||
export * from "./SubmitButton";
|
export * from './SubmitButton';
|
||||||
export * from "./Table";
|
export * from './Table';
|
||||||
export * from "./TextOutput";
|
export * from './TextOutput';
|
||||||
export * from "./Title";
|
export * from './Title';
|
||||||
|
@@ -1,15 +1,15 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { createContext, useContext, useMemo } from "react";
|
import { createContext, useContext, useMemo } from 'react';
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from 'next/dynamic';
|
||||||
import { CSSReset, ThemeProvider } from "@chakra-ui/core";
|
import { CSSReset, ThemeProvider } from '@chakra-ui/core';
|
||||||
import { MediaProvider } from "./MediaProvider";
|
import { MediaProvider } from './MediaProvider';
|
||||||
import { StateProvider } from "./StateProvider";
|
import { StateProvider } from './StateProvider';
|
||||||
import { makeTheme, defaultTheme } from "app/util";
|
import { makeTheme, defaultTheme } from 'app/util';
|
||||||
|
|
||||||
// Disable SSR for ColorModeProvider
|
// Disable SSR for ColorModeProvider
|
||||||
const ColorModeProvider = dynamic(
|
const ColorModeProvider = dynamic(
|
||||||
() => import("@chakra-ui/core").then(mod => mod.ColorModeProvider),
|
() => import('@chakra-ui/core').then(mod => mod.ColorModeProvider),
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
const HyperglassContext = createContext(null);
|
const HyperglassContext = createContext(null);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { createContext, useContext, useMemo } from "react";
|
import { createContext, useContext, useMemo } from 'react';
|
||||||
import { useMediaLayout } from "use-media";
|
import { useMediaLayout } from 'use-media';
|
||||||
|
|
||||||
const MediaContext = createContext(null);
|
const MediaContext = createContext(null);
|
||||||
|
|
||||||
@@ -13,16 +13,16 @@ export const MediaProvider = ({ theme, children }) => {
|
|||||||
let mediaSize = false;
|
let mediaSize = false;
|
||||||
switch (true) {
|
switch (true) {
|
||||||
case isSm:
|
case isSm:
|
||||||
mediaSize = "sm";
|
mediaSize = 'sm';
|
||||||
break;
|
break;
|
||||||
case isMd:
|
case isMd:
|
||||||
mediaSize = "md";
|
mediaSize = 'md';
|
||||||
break;
|
break;
|
||||||
case isLg:
|
case isLg:
|
||||||
mediaSize = "lg";
|
mediaSize = 'lg';
|
||||||
break;
|
break;
|
||||||
case isXl:
|
case isXl:
|
||||||
mediaSize = "xl";
|
mediaSize = 'xl';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
const value = useMemo(
|
const value = useMemo(
|
||||||
@@ -31,13 +31,11 @@ export const MediaProvider = ({ theme, children }) => {
|
|||||||
isMd: isMd,
|
isMd: isMd,
|
||||||
isLg: isLg,
|
isLg: isLg,
|
||||||
isXl: isXl,
|
isXl: isXl,
|
||||||
mediaSize: mediaSize
|
mediaSize: mediaSize,
|
||||||
}),
|
}),
|
||||||
[isSm, isMd, isLg, isXl, mediaSize]
|
[isSm, isMd, isLg, isXl, mediaSize],
|
||||||
);
|
|
||||||
return (
|
|
||||||
<MediaContext.Provider value={value}>{children}</MediaContext.Provider>
|
|
||||||
);
|
);
|
||||||
|
return <MediaContext.Provider value={value}>{children}</MediaContext.Provider>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useMedia = () => useContext(MediaContext);
|
export const useMedia = () => useContext(MediaContext);
|
||||||
|
@@ -1,18 +1,15 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import { createContext, useContext, useMemo, useState } from "react";
|
import { createContext, useContext, useMemo, useState } from 'react';
|
||||||
import { useSessionStorage } from "app/hooks";
|
import { useSessionStorage } from 'app/hooks';
|
||||||
|
|
||||||
const StateContext = createContext(null);
|
const StateContext = createContext(null);
|
||||||
|
|
||||||
export const StateProvider = ({ children }) => {
|
export const StateProvider = ({ children }) => {
|
||||||
const [isSubmitting, setSubmitting] = useState(false);
|
const [isSubmitting, setSubmitting] = useState(false);
|
||||||
const [formData, setFormData] = useState({});
|
const [formData, setFormData] = useState({});
|
||||||
const [greetingAck, setGreetingAck] = useSessionStorage(
|
const [greetingAck, setGreetingAck] = useSessionStorage('hyperglass-greeting-ack', false);
|
||||||
"hyperglass-greeting-ack",
|
|
||||||
false
|
|
||||||
);
|
|
||||||
const resetForm = layoutRef => {
|
const resetForm = layoutRef => {
|
||||||
layoutRef.current.scrollIntoView({ behavior: "smooth", block: "start" });
|
layoutRef.current.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
||||||
setSubmitting(false);
|
setSubmitting(false);
|
||||||
setFormData({});
|
setFormData({});
|
||||||
};
|
};
|
||||||
@@ -23,11 +20,9 @@ export const StateProvider = ({ children }) => {
|
|||||||
setFormData,
|
setFormData,
|
||||||
greetingAck,
|
greetingAck,
|
||||||
setGreetingAck,
|
setGreetingAck,
|
||||||
resetForm
|
resetForm,
|
||||||
}));
|
}));
|
||||||
return (
|
return <StateContext.Provider value={value}>{children}</StateContext.Provider>;
|
||||||
<StateContext.Provider value={value}>{children}</StateContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const useHyperglassState = () => useContext(StateContext);
|
export const useHyperglassState = () => useContext(StateContext);
|
||||||
|
@@ -1,3 +1,3 @@
|
|||||||
export * from "./HyperglassProvider";
|
export * from './HyperglassProvider';
|
||||||
export * from "./MediaProvider";
|
export * from './MediaProvider';
|
||||||
export * from "./StateProvider";
|
export * from './StateProvider';
|
||||||
|
@@ -1 +1 @@
|
|||||||
export * from "./useSessionStorage";
|
export * from './useSessionStorage';
|
||||||
|
@@ -3,10 +3,10 @@ react-use: useSessionStorage
|
|||||||
https://github.com/streamich/react-use/blob/master/src/useSessionStorage.ts
|
https://github.com/streamich/react-use/blob/master/src/useSessionStorage.ts
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { useEffect, useState } from 'react';
|
||||||
|
|
||||||
export const useSessionStorage = (key, initialValue, raw) => {
|
export const useSessionStorage = (key, initialValue, raw) => {
|
||||||
const isClient = typeof window === "object";
|
const isClient = typeof window === 'object';
|
||||||
if (!isClient) {
|
if (!isClient) {
|
||||||
return [initialValue, () => {}];
|
return [initialValue, () => {}];
|
||||||
}
|
}
|
||||||
@@ -14,16 +14,11 @@ export const useSessionStorage = (key, initialValue, raw) => {
|
|||||||
const [state, setState] = useState(() => {
|
const [state, setState] = useState(() => {
|
||||||
try {
|
try {
|
||||||
const sessionStorageValue = sessionStorage.getItem(key);
|
const sessionStorageValue = sessionStorage.getItem(key);
|
||||||
if (typeof sessionStorageValue !== "string") {
|
if (typeof sessionStorageValue !== 'string') {
|
||||||
sessionStorage.setItem(
|
sessionStorage.setItem(key, raw ? String(initialValue) : JSON.stringify(initialValue));
|
||||||
key,
|
|
||||||
raw ? String(initialValue) : JSON.stringify(initialValue)
|
|
||||||
);
|
|
||||||
return initialValue;
|
return initialValue;
|
||||||
} else {
|
} else {
|
||||||
return raw
|
return raw ? sessionStorageValue : JSON.parse(sessionStorageValue || 'null');
|
||||||
? sessionStorageValue
|
|
||||||
: JSON.parse(sessionStorageValue || "null");
|
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// If user is in private mode or has storage restriction
|
// If user is in private mode or has storage restriction
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
// const aliases = require("./.alias");
|
// const aliases = require("./.alias");
|
||||||
const envVars = require("/tmp/hyperglass.env.json");
|
const envVars = require('/tmp/hyperglass.env.json');
|
||||||
const { configFile } = envVars;
|
const { configFile } = envVars;
|
||||||
const config = require(String(configFile));
|
const config = require(String(configFile));
|
||||||
|
|
||||||
@@ -18,6 +18,6 @@ module.exports = {
|
|||||||
_NODE_ENV_: config.NODE_ENV,
|
_NODE_ENV_: config.NODE_ENV,
|
||||||
_HYPERGLASS_URL_: config._HYPERGLASS_URL_,
|
_HYPERGLASS_URL_: config._HYPERGLASS_URL_,
|
||||||
_HYPERGLASS_CONFIG_: config._HYPERGLASS_CONFIG_,
|
_HYPERGLASS_CONFIG_: config._HYPERGLASS_CONFIG_,
|
||||||
_HYPERGLASS_FAVICONS_: config._HYPERGLASS_FAVICONS_
|
_HYPERGLASS_FAVICONS_: config._HYPERGLASS_FAVICONS_,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
@@ -1,51 +1,52 @@
|
|||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
const express = require("express");
|
const express = require('express');
|
||||||
const proxyMiddleware = require("http-proxy-middleware");
|
const proxyMiddleware = require('http-proxy-middleware');
|
||||||
const next = require("next");
|
const next = require('next');
|
||||||
const envVars = require("/tmp/hyperglass.env.json");
|
const envVars = require('/tmp/hyperglass.env.json');
|
||||||
const { configFile } = envVars;
|
const { configFile } = envVars;
|
||||||
const config = require(String(configFile));
|
const config = require(String(configFile));
|
||||||
|
|
||||||
const { NODE_ENV: env, _HYPERGLASS_URL_: envUrl } = config;
|
const { NODE_ENV: env, _HYPERGLASS_URL_: envUrl } = config;
|
||||||
|
|
||||||
const devProxy = {
|
const devProxy = {
|
||||||
"/api/query/": { target: envUrl + "api/query/", pathRewrite: { "^/api/query/": "" } },
|
'/api/query/': { target: envUrl + 'api/query/', pathRewrite: { '^/api/query/': '' } },
|
||||||
"/images": { target: envUrl + "images", pathRewrite: { "^/images": "" } },
|
'/images': { target: envUrl + 'images', pathRewrite: { '^/images': '' } },
|
||||||
"/custom": { target: envUrl + "custom", pathRewrite: { "^/custom": "" } }
|
'/custom': { target: envUrl + 'custom', pathRewrite: { '^/custom': '' } },
|
||||||
};
|
};
|
||||||
|
|
||||||
const port = parseInt(process.env.PORT, 10) || 3000;
|
const port = parseInt(process.env.PORT, 10) || 3000;
|
||||||
const dev = env !== "production";
|
const dev = env !== 'production';
|
||||||
const app = next({
|
const app = next({
|
||||||
dir: ".", // base directory where everything is, could move to src later
|
dir: '.', // base directory where everything is, could move to src later
|
||||||
dev
|
dev,
|
||||||
});
|
});
|
||||||
|
|
||||||
const handle = app.getRequestHandler();
|
const handle = app.getRequestHandler();
|
||||||
|
|
||||||
let server;
|
let server;
|
||||||
app.prepare()
|
app
|
||||||
.then(() => {
|
.prepare()
|
||||||
server = express();
|
.then(() => {
|
||||||
|
server = express();
|
||||||
|
|
||||||
// Set up the proxy.
|
// Set up the proxy.
|
||||||
if (dev && devProxy) {
|
if (dev && devProxy) {
|
||||||
Object.keys(devProxy).forEach(function(context) {
|
Object.keys(devProxy).forEach(function(context) {
|
||||||
server.use(proxyMiddleware(context, devProxy[context]));
|
server.use(proxyMiddleware(context, devProxy[context]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Default catch-all handler to allow Next.js to handle all other routes
|
// Default catch-all handler to allow Next.js to handle all other routes
|
||||||
server.all("*", (req, res) => handle(req, res));
|
server.all('*', (req, res) => handle(req, res));
|
||||||
|
|
||||||
server.listen(port, err => {
|
server.listen(port, err => {
|
||||||
if (err) {
|
if (err) {
|
||||||
throw err;
|
throw err;
|
||||||
}
|
}
|
||||||
console.log(`> Ready on port ${port} [${env}]`);
|
console.log(`> Ready on port ${port} [${env}]`);
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(err => {
|
|
||||||
console.log("An error occurred, unable to start the server");
|
|
||||||
console.log(err);
|
|
||||||
});
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.log('An error occurred, unable to start the server');
|
||||||
|
console.log(err);
|
||||||
|
});
|
||||||
|
6
hyperglass/ui/package.json
vendored
6
hyperglass/ui/package.json
vendored
@@ -45,17 +45,15 @@
|
|||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@typescript-eslint/eslint-plugin": "^2.24.0",
|
"@typescript-eslint/eslint-plugin": "^2.24.0",
|
||||||
"@typescript-eslint/parser": "^2.24.0",
|
"@typescript-eslint/parser": "^2.24.0",
|
||||||
|
"@upstatement/eslint-config": "^0.4.3",
|
||||||
|
"@upstatement/prettier-config": "^0.3.0",
|
||||||
"babel-eslint": "^10.1.0",
|
"babel-eslint": "^10.1.0",
|
||||||
"es-check": "^5.1.0",
|
"es-check": "^5.1.0",
|
||||||
"eslint": "^6.8.0",
|
"eslint": "^6.8.0",
|
||||||
"eslint-config-airbnb": "^18.1.0",
|
|
||||||
"eslint-config-prettier": "^6.10.0",
|
|
||||||
"eslint-config-react-app": "^5.2.0",
|
"eslint-config-react-app": "^5.2.0",
|
||||||
"eslint-import-resolver-webpack": "^0.13.0",
|
"eslint-import-resolver-webpack": "^0.13.0",
|
||||||
"eslint-plugin-flowtype": "^4.6.0",
|
|
||||||
"eslint-plugin-import": "^2.20.1",
|
"eslint-plugin-import": "^2.20.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
"eslint-plugin-prettier": "^3.1.2",
|
|
||||||
"eslint-plugin-react": "^7.19.0",
|
"eslint-plugin-react": "^7.19.0",
|
||||||
"eslint-plugin-react-hooks": "^2.3.0",
|
"eslint-plugin-react-hooks": "^2.3.0",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import Head from "next/head";
|
import Head from 'next/head';
|
||||||
// import { useRouter } from "next/router";
|
// import { useRouter } from "next/router";
|
||||||
import { HyperglassProvider } from "app/context";
|
import { HyperglassProvider } from 'app/context';
|
||||||
// import Error from "./_error";
|
// import Error from "./_error";
|
||||||
|
|
||||||
const config = process.env._HYPERGLASS_CONFIG_;
|
const config = process.env._HYPERGLASS_CONFIG_;
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import Document, { Html, Head, Main, NextScript } from "next/document";
|
import Document, { Html, Head, Main, NextScript } from 'next/document';
|
||||||
|
|
||||||
class MyDocument extends Document {
|
class MyDocument extends Document {
|
||||||
static async getInitialProps(ctx) {
|
static async getInitialProps(ctx) {
|
||||||
@@ -13,11 +13,7 @@ class MyDocument extends Document {
|
|||||||
<Head>
|
<Head>
|
||||||
<link rel="dns-prefetch" href="//fonts.googleapis.com" />
|
<link rel="dns-prefetch" href="//fonts.googleapis.com" />
|
||||||
<link rel="dns-prefetch" href="//fonts.gstatic.com" />
|
<link rel="dns-prefetch" href="//fonts.gstatic.com" />
|
||||||
<link
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossOrigin="true" />
|
||||||
rel="preconnect"
|
|
||||||
href="https://fonts.gstatic.com"
|
|
||||||
crossOrigin="true"
|
|
||||||
/>
|
|
||||||
<link rel="preconnect" href="https://www.google-analytics.com" />
|
<link rel="preconnect" href="https://www.google-analytics.com" />
|
||||||
</Head>
|
</Head>
|
||||||
<body>
|
<body>
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from 'react';
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from 'next/dynamic';
|
||||||
import { useRouter } from "next/router";
|
import { useRouter } from 'next/router';
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
CSSReset,
|
CSSReset,
|
||||||
@@ -9,42 +9,37 @@ import {
|
|||||||
Text,
|
Text,
|
||||||
ThemeProvider,
|
ThemeProvider,
|
||||||
useColorMode,
|
useColorMode,
|
||||||
theme as defaultTheme
|
theme as defaultTheme,
|
||||||
} from "@chakra-ui/core";
|
} from '@chakra-ui/core';
|
||||||
import { inRange } from "lodash";
|
import { inRange } from 'lodash';
|
||||||
|
|
||||||
const ColorModeProvider = dynamic(
|
const ColorModeProvider = dynamic(
|
||||||
() => import("@chakra-ui/core").then(mod => mod.ColorModeProvider),
|
() => import('@chakra-ui/core').then(mod => mod.ColorModeProvider),
|
||||||
{ ssr: false }
|
{ ssr: false },
|
||||||
);
|
);
|
||||||
|
|
||||||
const ErrorContent = ({ msg, statusCode }) => {
|
const ErrorContent = ({ msg, statusCode }) => {
|
||||||
const { colorMode } = useColorMode();
|
const { colorMode } = useColorMode();
|
||||||
const bg = { light: "white", dark: "black" };
|
const bg = { light: 'white', dark: 'black' };
|
||||||
const baseCode = inRange(statusCode, 400, 500)
|
const baseCode = inRange(statusCode, 400, 500) ? 400 : inRange(statusCode, 500, 600) ? 500 : 400;
|
||||||
? 400
|
|
||||||
: inRange(statusCode, 500, 600)
|
|
||||||
? 500
|
|
||||||
: 400;
|
|
||||||
const errorColor = {
|
const errorColor = {
|
||||||
400: { light: "error.500", dark: "error.300" },
|
400: { light: 'error.500', dark: 'error.300' },
|
||||||
500: { light: "danger.500", dark: "danger.300" }
|
500: { light: 'danger.500', dark: 'danger.300' },
|
||||||
};
|
};
|
||||||
const variantColor = {
|
const variantColor = {
|
||||||
400: "error",
|
400: 'error',
|
||||||
500: "danger"
|
500: 'danger',
|
||||||
};
|
};
|
||||||
const color = { light: "black", dark: "white" };
|
const color = { light: 'black', dark: 'white' };
|
||||||
const { push } = useRouter();
|
const { push } = useRouter();
|
||||||
const handleClick = () => push("/");
|
const handleClick = () => push('/');
|
||||||
return (
|
return (
|
||||||
<Flex
|
<Flex
|
||||||
w="100%"
|
w="100%"
|
||||||
minHeight="100vh"
|
minHeight="100vh"
|
||||||
bg={bg[colorMode]}
|
bg={bg[colorMode]}
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
color={color[colorMode]}
|
color={color[colorMode]}>
|
||||||
>
|
|
||||||
<Flex
|
<Flex
|
||||||
px={2}
|
px={2}
|
||||||
py={0}
|
py={0}
|
||||||
@@ -57,8 +52,7 @@ const ErrorContent = ({ msg, statusCode }) => {
|
|||||||
alignItems="center"
|
alignItems="center"
|
||||||
flexDirection="column"
|
flexDirection="column"
|
||||||
justifyContent="start"
|
justifyContent="start"
|
||||||
mt={["50%", "50%", "50%", "25%"]}
|
mt={['50%', '50%', '50%', '25%']}>
|
||||||
>
|
|
||||||
<Heading mb={4} as="h1" fontSize="2xl">
|
<Heading mb={4} as="h1" fontSize="2xl">
|
||||||
<Text as="span" color={errorColor[baseCode][colorMode]}>
|
<Text as="span" color={errorColor[baseCode][colorMode]}>
|
||||||
{msg}
|
{msg}
|
||||||
@@ -66,11 +60,7 @@ const ErrorContent = ({ msg, statusCode }) => {
|
|||||||
{statusCode === 404 && <Text as="span"> isn't a thing...</Text>}
|
{statusCode === 404 && <Text as="span"> isn't a thing...</Text>}
|
||||||
</Heading>
|
</Heading>
|
||||||
|
|
||||||
<Button
|
<Button variant="outline" onClick={handleClick} variantColor={variantColor[baseCode]}>
|
||||||
variant="outline"
|
|
||||||
onClick={handleClick}
|
|
||||||
variantColor={variantColor[baseCode]}
|
|
||||||
>
|
|
||||||
Home
|
Home
|
||||||
</Button>
|
</Button>
|
||||||
</Flex>
|
</Flex>
|
||||||
@@ -91,7 +81,7 @@ const ErrorPage = ({ msg, statusCode }) => {
|
|||||||
|
|
||||||
ErrorPage.getInitialProps = ({ res, err }) => {
|
ErrorPage.getInitialProps = ({ res, err }) => {
|
||||||
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
|
const statusCode = res ? res.statusCode : err ? err.statusCode : 404;
|
||||||
const msg = err ? err.message : res.req?.url || "Error";
|
const msg = err ? err.message : res.req?.url || 'Error';
|
||||||
return { msg, statusCode };
|
return { msg, statusCode };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,12 +1,12 @@
|
|||||||
import * as React from "react";
|
import * as React from 'react';
|
||||||
import Head from "next/head";
|
import Head from 'next/head';
|
||||||
import dynamic from "next/dynamic";
|
import dynamic from 'next/dynamic';
|
||||||
import { Meta, Loading } from "app/components";
|
import { Meta, Loading } from 'app/components';
|
||||||
const LookingGlass = dynamic(
|
const LookingGlass = dynamic(
|
||||||
() => import("app/components/LookingGlass").then(i => i.LookingGlass),
|
() => import('app/components/LookingGlass').then(i => i.LookingGlass),
|
||||||
{
|
{
|
||||||
loading: Loading
|
loading: Loading,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const Index = ({ faviconComponents }) => {
|
const Index = ({ faviconComponents }) => {
|
||||||
@@ -31,8 +31,8 @@ export async function getStaticProps(context) {
|
|||||||
});
|
});
|
||||||
return {
|
return {
|
||||||
props: {
|
props: {
|
||||||
faviconComponents: components
|
faviconComponents: components,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
1
hyperglass/ui/prettier.config.js
Normal file
1
hyperglass/ui/prettier.config.js
Normal file
@@ -0,0 +1 @@
|
|||||||
|
module.exports = require("@upstatement/prettier-config");
|
@@ -2,39 +2,39 @@
|
|||||||
// This will help to prevent a flash if dark mode is the default.
|
// This will help to prevent a flash if dark mode is the default.
|
||||||
|
|
||||||
(function() {
|
(function() {
|
||||||
// Change these if you use something different in your hook.
|
// Change these if you use something different in your hook.
|
||||||
var storageKey = "darkMode";
|
var storageKey = 'darkMode';
|
||||||
var classNameDark = "dark-mode";
|
var classNameDark = 'dark-mode';
|
||||||
var classNameLight = "light-mode";
|
var classNameLight = 'light-mode';
|
||||||
|
|
||||||
function setClassOnDocumentBody(darkMode) {
|
function setClassOnDocumentBody(darkMode) {
|
||||||
document.body.classList.add(darkMode ? classNameDark : classNameLight);
|
document.body.classList.add(darkMode ? classNameDark : classNameLight);
|
||||||
document.body.classList.remove(darkMode ? classNameLight : classNameDark);
|
document.body.classList.remove(darkMode ? classNameLight : classNameDark);
|
||||||
}
|
}
|
||||||
|
|
||||||
var preferDarkQuery = "(prefers-color-scheme: dark)";
|
var preferDarkQuery = '(prefers-color-scheme: dark)';
|
||||||
var mql = window.matchMedia(preferDarkQuery);
|
var mql = window.matchMedia(preferDarkQuery);
|
||||||
var supportsColorSchemeQuery = mql.media === preferDarkQuery;
|
var supportsColorSchemeQuery = mql.media === preferDarkQuery;
|
||||||
var localStorageTheme = null;
|
var localStorageTheme = null;
|
||||||
try {
|
try {
|
||||||
localStorageTheme = localStorage.getItem(storageKey);
|
localStorageTheme = localStorage.getItem(storageKey);
|
||||||
} catch (err) {}
|
} catch (err) {}
|
||||||
var localStorageExists = localStorageTheme !== null;
|
var localStorageExists = localStorageTheme !== null;
|
||||||
if (localStorageExists) {
|
if (localStorageExists) {
|
||||||
localStorageTheme = JSON.parse(localStorageTheme);
|
localStorageTheme = JSON.parse(localStorageTheme);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determine the source of truth
|
// Determine the source of truth
|
||||||
if (localStorageExists) {
|
if (localStorageExists) {
|
||||||
// source of truth from localStorage
|
// source of truth from localStorage
|
||||||
setClassOnDocumentBody(localStorageTheme);
|
setClassOnDocumentBody(localStorageTheme);
|
||||||
} else if (supportsColorSchemeQuery) {
|
} else if (supportsColorSchemeQuery) {
|
||||||
// source of truth from system
|
// source of truth from system
|
||||||
setClassOnDocumentBody(mql.matches);
|
setClassOnDocumentBody(mql.matches);
|
||||||
localStorage.setItem(storageKey, mql.matches);
|
localStorage.setItem(storageKey, mql.matches);
|
||||||
} else {
|
} else {
|
||||||
// source of truth from document.body
|
// source of truth from document.body
|
||||||
var isDarkMode = document.body.classList.contains(classNameDark);
|
var isDarkMode = document.body.classList.contains(classNameDark);
|
||||||
localStorage.setItem(storageKey, JSON.stringify(isDarkMode));
|
localStorage.setItem(storageKey, JSON.stringify(isDarkMode));
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@@ -1,33 +1,33 @@
|
|||||||
import dayjs from "dayjs";
|
import dayjs from 'dayjs';
|
||||||
import relativeTimePlugin from "dayjs/plugin/relativeTime";
|
import relativeTimePlugin from 'dayjs/plugin/relativeTime';
|
||||||
import utcPlugin from "dayjs/plugin/utc";
|
import utcPlugin from 'dayjs/plugin/utc';
|
||||||
|
|
||||||
dayjs.extend(relativeTimePlugin);
|
dayjs.extend(relativeTimePlugin);
|
||||||
dayjs.extend(utcPlugin);
|
dayjs.extend(utcPlugin);
|
||||||
|
|
||||||
const formatAsPath = path => {
|
const formatAsPath = path => {
|
||||||
return path.join(" → ");
|
return path.join(' → ');
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatCommunities = comms => {
|
const formatCommunities = comms => {
|
||||||
const commsStr = comms.map(c => ` - ${c}`);
|
const commsStr = comms.map(c => ` - ${c}`);
|
||||||
return "\n" + commsStr.join("\n");
|
return '\n' + commsStr.join('\n');
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatBool = val => {
|
const formatBool = val => {
|
||||||
let fmt = "";
|
let fmt = '';
|
||||||
if (val === true) {
|
if (val === true) {
|
||||||
fmt = "yes";
|
fmt = 'yes';
|
||||||
} else if (val === false) {
|
} else if (val === false) {
|
||||||
fmt = "no";
|
fmt = 'no';
|
||||||
}
|
}
|
||||||
return fmt;
|
return fmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
const formatTime = val => {
|
const formatTime = val => {
|
||||||
const now = dayjs.utc();
|
const now = dayjs.utc();
|
||||||
const then = now.subtract(val, "seconds");
|
const then = now.subtract(val, 'seconds');
|
||||||
const timestamp = then.toString().replace("GMT", "UTC");
|
const timestamp = then.toString().replace('GMT', 'UTC');
|
||||||
const relative = now.to(then, true);
|
const relative = now.to(then, true);
|
||||||
return `${relative} (${timestamp})`;
|
return `${relative} (${timestamp})`;
|
||||||
};
|
};
|
||||||
@@ -39,7 +39,7 @@ export const tableToString = (target, data, config) => {
|
|||||||
config.web.text.rpki_invalid,
|
config.web.text.rpki_invalid,
|
||||||
config.web.text.rpki_valid,
|
config.web.text.rpki_valid,
|
||||||
config.web.text.rpki_unknown,
|
config.web.text.rpki_unknown,
|
||||||
config.web.text.rpki_unverified
|
config.web.text.rpki_unverified,
|
||||||
];
|
];
|
||||||
return rpkiStateNames[val];
|
return rpkiStateNames[val];
|
||||||
};
|
};
|
||||||
@@ -49,13 +49,10 @@ export const tableToString = (target, data, config) => {
|
|||||||
active: formatBool,
|
active: formatBool,
|
||||||
as_path: formatAsPath,
|
as_path: formatAsPath,
|
||||||
communities: formatCommunities,
|
communities: formatCommunities,
|
||||||
rpki_state: formatRpkiState
|
rpki_state: formatRpkiState,
|
||||||
};
|
};
|
||||||
|
|
||||||
let tableStringParts = [
|
let tableStringParts = [`Routes For: ${target}`, `Timestamp: ${data.timestamp} UTC`];
|
||||||
`Routes For: ${target}`,
|
|
||||||
`Timestamp: ${data.timestamp} UTC`
|
|
||||||
];
|
|
||||||
|
|
||||||
data.output.routes.map(route => {
|
data.output.routes.map(route => {
|
||||||
config.parsed_data_fields.map(field => {
|
config.parsed_data_fields.map(field => {
|
||||||
@@ -64,7 +61,7 @@ export const tableToString = (target, data, config) => {
|
|||||||
let value = route[accessor];
|
let value = route[accessor];
|
||||||
const fmtFunc = tableFormatMap[accessor] ?? String;
|
const fmtFunc = tableFormatMap[accessor] ?? String;
|
||||||
value = fmtFunc(value);
|
value = fmtFunc(value);
|
||||||
if (accessor === "prefix") {
|
if (accessor === 'prefix') {
|
||||||
tableStringParts.push(` - ${header}: ${value}`);
|
tableStringParts.push(` - ${header}: ${value}`);
|
||||||
} else {
|
} else {
|
||||||
tableStringParts.push(` - ${header}: ${value}`);
|
tableStringParts.push(` - ${header}: ${value}`);
|
||||||
@@ -72,7 +69,7 @@ export const tableToString = (target, data, config) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return tableStringParts.join("\n");
|
return tableStringParts.join('\n');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
return `An error occurred while parsing the output: '${err.message}'`;
|
return `An error occurred while parsing the output: '${err.message}'`;
|
||||||
|
@@ -1,2 +1,2 @@
|
|||||||
export * from "./theme";
|
export * from './formatters';
|
||||||
export * from "./formatters";
|
export * from './theme';
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
import { theme as chakraTheme } from "@chakra-ui/core";
|
import { theme as chakraTheme } from '@chakra-ui/core';
|
||||||
import chroma from "chroma-js";
|
import chroma from 'chroma-js';
|
||||||
|
|
||||||
const alphaColors = color => ({
|
const alphaColors = color => ({
|
||||||
900: chroma(color)
|
900: chroma(color)
|
||||||
@@ -31,41 +31,26 @@ const alphaColors = color => ({
|
|||||||
.css(),
|
.css(),
|
||||||
50: chroma(color)
|
50: chroma(color)
|
||||||
.alpha(0.04)
|
.alpha(0.04)
|
||||||
.css()
|
.css(),
|
||||||
});
|
});
|
||||||
|
|
||||||
const generateColors = colorInput => {
|
const generateColors = colorInput => {
|
||||||
const colorMap = {};
|
const colorMap = {};
|
||||||
|
|
||||||
const lightnessMap = [
|
const lightnessMap = [0.95, 0.85, 0.75, 0.65, 0.55, 0.45, 0.35, 0.25, 0.15, 0.05];
|
||||||
0.95,
|
|
||||||
0.85,
|
|
||||||
0.75,
|
|
||||||
0.65,
|
|
||||||
0.55,
|
|
||||||
0.45,
|
|
||||||
0.35,
|
|
||||||
0.25,
|
|
||||||
0.15,
|
|
||||||
0.05
|
|
||||||
];
|
|
||||||
const saturationMap = [0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32];
|
const saturationMap = [0.32, 0.16, 0.08, 0.04, 0, 0, 0.04, 0.08, 0.16, 0.32];
|
||||||
|
|
||||||
const validColor = chroma.valid(colorInput.trim())
|
const validColor = chroma.valid(colorInput.trim()) ? chroma(colorInput.trim()) : chroma('#000');
|
||||||
? chroma(colorInput.trim())
|
|
||||||
: chroma("#000");
|
|
||||||
|
|
||||||
const lightnessGoal = validColor.get("hsl.l");
|
const lightnessGoal = validColor.get('hsl.l');
|
||||||
const closestLightness = lightnessMap.reduce((prev, curr) =>
|
const closestLightness = lightnessMap.reduce((prev, curr) =>
|
||||||
Math.abs(curr - lightnessGoal) < Math.abs(prev - lightnessGoal)
|
Math.abs(curr - lightnessGoal) < Math.abs(prev - lightnessGoal) ? curr : prev,
|
||||||
? curr
|
|
||||||
: prev
|
|
||||||
);
|
);
|
||||||
|
|
||||||
const baseColorIndex = lightnessMap.findIndex(l => l === closestLightness);
|
const baseColorIndex = lightnessMap.findIndex(l => l === closestLightness);
|
||||||
|
|
||||||
const colors = lightnessMap
|
const colors = lightnessMap
|
||||||
.map(l => validColor.set("hsl.l", l))
|
.map(l => validColor.set('hsl.l', l))
|
||||||
.map(color => chroma(color))
|
.map(color => chroma(color))
|
||||||
.map((color, i) => {
|
.map((color, i) => {
|
||||||
const saturationDelta = saturationMap[i] - saturationMap[baseColorIndex];
|
const saturationDelta = saturationMap[i] - saturationMap[baseColorIndex];
|
||||||
@@ -84,31 +69,31 @@ const generateColors = colorInput => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const defaultBodyFonts = [
|
const defaultBodyFonts = [
|
||||||
"-apple-system",
|
'-apple-system',
|
||||||
"BlinkMacSystemFont",
|
'BlinkMacSystemFont',
|
||||||
'"Segoe UI"',
|
'"Segoe UI"',
|
||||||
"Helvetica",
|
'Helvetica',
|
||||||
"Arial",
|
'Arial',
|
||||||
"sans-serif",
|
'sans-serif',
|
||||||
'"Apple Color Emoji"',
|
'"Apple Color Emoji"',
|
||||||
'"Segoe UI Emoji"',
|
'"Segoe UI Emoji"',
|
||||||
'"Segoe UI Symbol"'
|
'"Segoe UI Symbol"',
|
||||||
];
|
];
|
||||||
|
|
||||||
const defaultMonoFonts = [
|
const defaultMonoFonts = [
|
||||||
"SFMono-Regular",
|
'SFMono-Regular',
|
||||||
"Melno",
|
'Melno',
|
||||||
"Monaco",
|
'Monaco',
|
||||||
"Consolas",
|
'Consolas',
|
||||||
'"Liberation Mono"',
|
'"Liberation Mono"',
|
||||||
'"Courier New"',
|
'"Courier New"',
|
||||||
"monospace"
|
'monospace',
|
||||||
];
|
];
|
||||||
|
|
||||||
const generatePalette = palette => {
|
const generatePalette = palette => {
|
||||||
const generatedPalette = {};
|
const generatedPalette = {};
|
||||||
Object.keys(palette).map(color => {
|
Object.keys(palette).map(color => {
|
||||||
if (!["black", "white"].includes(color)) {
|
if (!['black', 'white'].includes(color)) {
|
||||||
generatedPalette[color] = generateColors(palette[color]);
|
generatedPalette[color] = generateColors(palette[color]);
|
||||||
} else {
|
} else {
|
||||||
generatedPalette[color] = palette[color];
|
generatedPalette[color] = palette[color];
|
||||||
@@ -120,9 +105,8 @@ const generatePalette = palette => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const formatFont = font => {
|
const formatFont = font => {
|
||||||
const fontList = font.split(" ");
|
const fontList = font.split(' ');
|
||||||
const fontFmt =
|
const fontFmt = fontList.length >= 2 ? `'${fontList.join(' ')}'` : fontList.join(' ');
|
||||||
fontList.length >= 2 ? `'${fontList.join(" ")}'` : fontList.join(" ");
|
|
||||||
return fontFmt;
|
return fontFmt;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -137,25 +121,25 @@ const importFonts = userFonts => {
|
|||||||
mono.unshift(monoFmt);
|
mono.unshift(monoFmt);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
body: body.join(", "),
|
body: body.join(', '),
|
||||||
heading: body.join(", "),
|
heading: body.join(', '),
|
||||||
mono: mono.join(", ")
|
mono: mono.join(', '),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const importColors = (userColors = {}) => {
|
const importColors = (userColors = {}) => {
|
||||||
const generatedColors = generatePalette(userColors);
|
const generatedColors = generatePalette(userColors);
|
||||||
return {
|
return {
|
||||||
transparent: "transparent",
|
transparent: 'transparent',
|
||||||
current: "currentColor",
|
current: 'currentColor',
|
||||||
...generatedColors
|
...generatedColors,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const makeTheme = userTheme => ({
|
export const makeTheme = userTheme => ({
|
||||||
...chakraTheme,
|
...chakraTheme,
|
||||||
colors: importColors(userTheme.colors),
|
colors: importColors(userTheme.colors),
|
||||||
fonts: importFonts(userTheme.fonts)
|
fonts: importFonts(userTheme.fonts),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const isDark = color => {
|
export const isDark = color => {
|
||||||
@@ -169,7 +153,7 @@ export const isLight = color => isDark(color);
|
|||||||
|
|
||||||
export const opposingColor = (theme, color) => {
|
export const opposingColor = (theme, color) => {
|
||||||
if (color.match(/^\w+\.\d+$/m)) {
|
if (color.match(/^\w+\.\d+$/m)) {
|
||||||
const colorParts = color.split(".");
|
const colorParts = color.split('.');
|
||||||
if (colorParts.length !== 2) {
|
if (colorParts.length !== 2) {
|
||||||
throw Error(`Color is improperly formatted. Got '${color}'`);
|
throw Error(`Color is improperly formatted. Got '${color}'`);
|
||||||
}
|
}
|
||||||
@@ -181,14 +165,14 @@ export const opposingColor = (theme, color) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const googleFontUrl = (fontFamily, weights = [300, 400, 700]) => {
|
export const googleFontUrl = (fontFamily, weights = [300, 400, 700]) => {
|
||||||
const urlWeights = weights.join(",");
|
const urlWeights = weights.join(',');
|
||||||
const fontName = fontFamily
|
const fontName = fontFamily
|
||||||
.split(/, /)[0]
|
.split(/, /)[0]
|
||||||
.trim()
|
.trim()
|
||||||
.replace(/'|"/g, "");
|
.replace(/'|"/g, '');
|
||||||
const urlFont = fontName.split(/ /).join("+");
|
const urlFont = fontName.split(/ /).join('+');
|
||||||
const urlBase = `https://fonts.googleapis.com/css?family=${urlFont}:${urlWeights}&display=swap`;
|
const urlBase = `https://fonts.googleapis.com/css?family=${urlFont}:${urlWeights}&display=swap`;
|
||||||
return urlBase;
|
return urlBase;
|
||||||
};
|
};
|
||||||
|
|
||||||
export { theme as defaultTheme } from "@chakra-ui/core";
|
export { theme as defaultTheme } from '@chakra-ui/core';
|
||||||
|
70
hyperglass/ui/yarn.lock
vendored
70
hyperglass/ui/yarn.lock
vendored
@@ -1432,6 +1432,18 @@
|
|||||||
semver "^7.3.2"
|
semver "^7.3.2"
|
||||||
tsutils "^3.17.1"
|
tsutils "^3.17.1"
|
||||||
|
|
||||||
|
"@upstatement/eslint-config@^0.4.3":
|
||||||
|
version "0.4.3"
|
||||||
|
resolved "https://registry.yarnpkg.com/@upstatement/eslint-config/-/eslint-config-0.4.3.tgz#9cfbe22d15c0fee2f7154e9f61455c4e53718027"
|
||||||
|
integrity sha512-I5wYURRsCUpYyTkyq/AOF+aNglJAde2Kzlq297pQ2r61AatUgn84Jw4CsYR6rgQNmTinpLtb8uwi12mOIaM8zg==
|
||||||
|
|
||||||
|
"@upstatement/prettier-config@^0.3.0":
|
||||||
|
version "0.3.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@upstatement/prettier-config/-/prettier-config-0.3.0.tgz#cf34332dfba90c7586cd0bde134b7fc771163323"
|
||||||
|
integrity sha512-/DCKpd5tsgZ7Mshb7MSLdFkPRXHxZhzEKJP9ZW58ix0ARw1nbrcdbyiovHEutiQqmh4OjdLJjIAJ2MVUiEaB+Q==
|
||||||
|
dependencies:
|
||||||
|
prettier "^1.x.x"
|
||||||
|
|
||||||
"@use-it/event-listener@^0.1.2":
|
"@use-it/event-listener@^0.1.2":
|
||||||
version "0.1.5"
|
version "0.1.5"
|
||||||
resolved "https://registry.yarnpkg.com/@use-it/event-listener/-/event-listener-0.1.5.tgz#870456241bfef66acea6395c69b66fe516bee3cd"
|
resolved "https://registry.yarnpkg.com/@use-it/event-listener/-/event-listener-0.1.5.tgz#870456241bfef66acea6395c69b66fe516bee3cd"
|
||||||
@@ -3336,31 +3348,6 @@ escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5:
|
|||||||
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4"
|
||||||
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=
|
||||||
|
|
||||||
eslint-config-airbnb-base@^14.2.0:
|
|
||||||
version "14.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb-base/-/eslint-config-airbnb-base-14.2.0.tgz#fe89c24b3f9dc8008c9c0d0d88c28f95ed65e9c4"
|
|
||||||
integrity sha512-Snswd5oC6nJaevs3nZoLSTvGJBvzTfnBqOIArkf3cbyTyq9UD79wOk8s+RiL6bhca0p/eRO6veczhf6A/7Jy8Q==
|
|
||||||
dependencies:
|
|
||||||
confusing-browser-globals "^1.0.9"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
object.entries "^1.1.2"
|
|
||||||
|
|
||||||
eslint-config-airbnb@^18.1.0:
|
|
||||||
version "18.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-airbnb/-/eslint-config-airbnb-18.2.0.tgz#8a82168713effce8fc08e10896a63f1235499dcd"
|
|
||||||
integrity sha512-Fz4JIUKkrhO0du2cg5opdyPKQXOI2MvF8KUvN2710nJMT6jaRUpRE2swrJftAjVGL7T1otLM5ieo5RqS1v9Udg==
|
|
||||||
dependencies:
|
|
||||||
eslint-config-airbnb-base "^14.2.0"
|
|
||||||
object.assign "^4.1.0"
|
|
||||||
object.entries "^1.1.2"
|
|
||||||
|
|
||||||
eslint-config-prettier@^6.10.0:
|
|
||||||
version "6.12.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-6.12.0.tgz#9eb2bccff727db1c52104f0b49e87ea46605a0d2"
|
|
||||||
integrity sha512-9jWPlFlgNwRUYVoujvWTQ1aMO8o6648r+K7qU7K5Jmkbyqav1fuEZC0COYpGBxyiAJb65Ra9hrmFx19xRGwXWw==
|
|
||||||
dependencies:
|
|
||||||
get-stdin "^6.0.0"
|
|
||||||
|
|
||||||
eslint-config-react-app@^5.2.0:
|
eslint-config-react-app@^5.2.0:
|
||||||
version "5.2.1"
|
version "5.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz#698bf7aeee27f0cea0139eaef261c7bf7dd623df"
|
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-5.2.1.tgz#698bf7aeee27f0cea0139eaef261c7bf7dd623df"
|
||||||
@@ -3400,13 +3387,6 @@ eslint-module-utils@^2.6.0:
|
|||||||
debug "^2.6.9"
|
debug "^2.6.9"
|
||||||
pkg-dir "^2.0.0"
|
pkg-dir "^2.0.0"
|
||||||
|
|
||||||
eslint-plugin-flowtype@^4.6.0:
|
|
||||||
version "4.7.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-flowtype/-/eslint-plugin-flowtype-4.7.0.tgz#903a6ea3eb5cbf4c7ba7fa73cc43fc39ab7e4a70"
|
|
||||||
integrity sha512-M+hxhSCk5QBEValO5/UqrS4UunT+MgplIJK5wA1sCtXjzBcZkpTGRwxmLHhGpbHcrmQecgt6ZL/KDdXWqGB7VA==
|
|
||||||
dependencies:
|
|
||||||
lodash "^4.17.15"
|
|
||||||
|
|
||||||
eslint-plugin-import@^2.20.1:
|
eslint-plugin-import@^2.20.1:
|
||||||
version "2.22.1"
|
version "2.22.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.22.1.tgz#0896c7e6a0cf44109a2d97b95903c2bb689d7702"
|
||||||
@@ -3443,13 +3423,6 @@ eslint-plugin-jsx-a11y@^6.2.3:
|
|||||||
jsx-ast-utils "^2.4.1"
|
jsx-ast-utils "^2.4.1"
|
||||||
language-tags "^1.0.5"
|
language-tags "^1.0.5"
|
||||||
|
|
||||||
eslint-plugin-prettier@^3.1.2:
|
|
||||||
version "3.1.4"
|
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2"
|
|
||||||
integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==
|
|
||||||
dependencies:
|
|
||||||
prettier-linter-helpers "^1.0.0"
|
|
||||||
|
|
||||||
eslint-plugin-react-hooks@^2.3.0:
|
eslint-plugin-react-hooks@^2.3.0:
|
||||||
version "2.5.1"
|
version "2.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.5.1.tgz#4ef5930592588ce171abeb26f400c7fbcbc23cd0"
|
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-2.5.1.tgz#4ef5930592588ce171abeb26f400c7fbcbc23cd0"
|
||||||
@@ -3749,11 +3722,6 @@ fast-deep-equal@^3.1.1:
|
|||||||
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
|
||||||
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
|
||||||
|
|
||||||
fast-diff@^1.1.2:
|
|
||||||
version "1.2.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
|
|
||||||
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
|
|
||||||
|
|
||||||
fast-json-stable-stringify@^2.0.0:
|
fast-json-stable-stringify@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
|
||||||
@@ -4024,11 +3992,6 @@ gauge@~1.2.5:
|
|||||||
lodash.padend "^4.1.0"
|
lodash.padend "^4.1.0"
|
||||||
lodash.padstart "^4.1.0"
|
lodash.padstart "^4.1.0"
|
||||||
|
|
||||||
get-stdin@^6.0.0:
|
|
||||||
version "6.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/get-stdin/-/get-stdin-6.0.0.tgz#9e09bf712b360ab9225e812048f71fde9c89657b"
|
|
||||||
integrity sha512-jp4tHawyV7+fkkSKyvjuLZswblUtz+SQKzSWnBbii16BuZksJlU1wuBYXY75r+duh/llF1ur6oNwi+2ZzjKZ7g==
|
|
||||||
|
|
||||||
get-value@^2.0.3, get-value@^2.0.6:
|
get-value@^2.0.3, get-value@^2.0.6:
|
||||||
version "2.0.6"
|
version "2.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
resolved "https://registry.yarnpkg.com/get-value/-/get-value-2.0.6.tgz#dc15ca1c672387ca76bd37ac0a395ba2042a2c28"
|
||||||
@@ -5935,14 +5898,7 @@ prelude-ls@~1.1.2:
|
|||||||
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
|
||||||
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
|
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
|
||||||
|
|
||||||
prettier-linter-helpers@^1.0.0:
|
prettier@^1.19.1, prettier@^1.x.x:
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
|
|
||||||
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
|
|
||||||
dependencies:
|
|
||||||
fast-diff "^1.1.2"
|
|
||||||
|
|
||||||
prettier@^1.19.1:
|
|
||||||
version "1.19.1"
|
version "1.19.1"
|
||||||
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
resolved "https://registry.yarnpkg.com/prettier/-/prettier-1.19.1.tgz#f7d7f5ff8a9cd872a7be4ca142095956a60797cb"
|
||||||
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
integrity sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==
|
||||||
|
Reference in New Issue
Block a user