mirror of
https://github.com/checktheroads/hyperglass
synced 2024-05-11 05:55:08 +00:00
continue typescript & chakra v1 migrations [skip ci]
This commit is contained in:
@@ -1,30 +1,29 @@
|
||||
import { Button } from '@chakra-ui/react';
|
||||
import { AnimatedDiv } from '~/components';
|
||||
import { Button, Menu, MenuButton, MenuList } from '@chakra-ui/react';
|
||||
import { Markdown } from '~/components';
|
||||
|
||||
import type { TFooterButton } from './types';
|
||||
|
||||
export const FooterButton = (props: TFooterButton) => {
|
||||
const { side, href, ...rest } = props;
|
||||
|
||||
let buttonProps = Object();
|
||||
if (typeof href !== 'undefined') {
|
||||
buttonProps = { href, as: 'a', target: '_blank', rel: 'noopener noreferrer' };
|
||||
}
|
||||
|
||||
const { content, title, side, ...rest } = props;
|
||||
const placement = side === 'left' ? 'top-end' : side === 'right' ? 'top-start' : undefined;
|
||||
return (
|
||||
<AnimatedDiv
|
||||
p={0}
|
||||
w="auto"
|
||||
d="flex"
|
||||
flexGrow={0}
|
||||
float={side}
|
||||
flexShrink={0}
|
||||
maxWidth="100%"
|
||||
flexBasis="auto"
|
||||
initial={{ opacity: 0 }}
|
||||
animate={{ opacity: 1 }}
|
||||
transition={{ duration: 0.6 }}>
|
||||
<Button size="xs" variant="ghost" {...buttonProps} {...rest} />
|
||||
</AnimatedDiv>
|
||||
<Menu placement={placement}>
|
||||
<MenuButton
|
||||
as={Button}
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
aria-label={typeof title === 'string' ? title : undefined}>
|
||||
{title}
|
||||
</MenuButton>
|
||||
<MenuList
|
||||
px={6}
|
||||
py={4}
|
||||
textAlign={side}
|
||||
mx={{ base: 1, lg: 2 }}
|
||||
maxW={{ base: '100vw', lg: '50vw' }}
|
||||
{...rest}>
|
||||
<Markdown content={content} />
|
||||
</MenuList>
|
||||
</Menu>
|
||||
);
|
||||
};
|
||||
|
@@ -1,28 +0,0 @@
|
||||
import { Drawer, DrawerBody, DrawerOverlay, DrawerContent } from '@chakra-ui/react';
|
||||
import { Markdown } from '~/components';
|
||||
|
||||
import type { TFooterContent } from './types';
|
||||
|
||||
export const FooterContent = (props: TFooterContent) => {
|
||||
const { isOpen, onClose, content, side = 'left', ...rest } = props;
|
||||
return (
|
||||
<Drawer placement="bottom" isOpen={isOpen} onClose={onClose}>
|
||||
<DrawerOverlay>
|
||||
<DrawerContent
|
||||
px={6}
|
||||
py={4}
|
||||
w="auto"
|
||||
borderBottom="1px"
|
||||
display="flex"
|
||||
maxWidth="100%"
|
||||
flexBasis="auto"
|
||||
justifyContent={side === 'left' ? 'flex-start' : 'flex-end'}
|
||||
{...rest}>
|
||||
<DrawerBody textAlign={side}>
|
||||
<Markdown content={content} />
|
||||
</DrawerBody>
|
||||
</DrawerContent>
|
||||
</DrawerOverlay>
|
||||
</Drawer>
|
||||
);
|
||||
};
|
@@ -1,101 +1,56 @@
|
||||
import { Box, Flex, useDisclosure } from '@chakra-ui/react';
|
||||
import { FiCode } from '@meronex/icons/fi';
|
||||
import { GoLinkExternal } from '@meronex/icons/go';
|
||||
import stringFormat from 'string-format';
|
||||
import dynamic from 'next/dynamic';
|
||||
import { Button, Flex, Link } from '@chakra-ui/react';
|
||||
import { If } from '~/components';
|
||||
import { useConfig, useColorValue } from '~/context';
|
||||
import { useStrf } from '~/hooks';
|
||||
import { FooterButton } from './button';
|
||||
import { FooterContent } from './content';
|
||||
|
||||
const CodeIcon = dynamic<MeronexIcon>(() => import('@meronex/icons/fi').then(i => i.FiCode));
|
||||
const ExtIcon = dynamic<MeronexIcon>(() => import('@meronex/icons/go').then(i => i.GoLinkExternal));
|
||||
|
||||
export const Footer = () => {
|
||||
const { web, content, primary_asn } = useConfig();
|
||||
const help = useDisclosure();
|
||||
const terms = useDisclosure();
|
||||
const credit = useDisclosure();
|
||||
|
||||
const footerBg = useColorValue('blackAlpha.50', 'whiteAlpha.100');
|
||||
const footerColor = useColorValue('black', 'white');
|
||||
const contentBorder = useColorValue('blackAlpha.100', 'whiteAlpha.200');
|
||||
|
||||
const extUrl = web.external_link.url.includes('{primary_asn}')
|
||||
? stringFormat(web.external_link.url, { primary_asn })
|
||||
: web.external_link.url ?? '/';
|
||||
const extUrl = useStrf(web.external_link.url, { primary_asn }) ?? '/';
|
||||
|
||||
return (
|
||||
<>
|
||||
{web.help_menu.enable && (
|
||||
<FooterContent
|
||||
content={content.help_menu}
|
||||
borderColor={contentBorder}
|
||||
bg={footerBg}
|
||||
side="left"
|
||||
{...help}
|
||||
/>
|
||||
)}
|
||||
{web.terms.enable && (
|
||||
<FooterContent
|
||||
content={content.terms}
|
||||
borderColor={contentBorder}
|
||||
bg={footerBg}
|
||||
side="left"
|
||||
{...terms}
|
||||
/>
|
||||
)}
|
||||
{web.credit.enable && (
|
||||
<FooterContent
|
||||
borderColor={contentBorder}
|
||||
content={content.credit}
|
||||
bg={footerBg}
|
||||
side="right"
|
||||
{...credit}
|
||||
/>
|
||||
)}
|
||||
<Flex
|
||||
px={6}
|
||||
w="100%"
|
||||
as="footer"
|
||||
bg={footerBg}
|
||||
flexWrap="wrap"
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
color={footerColor}
|
||||
py={{ base: 4, lg: 2 }}
|
||||
justifyContent="space-between">
|
||||
<If c={web.terms.enable}>
|
||||
<FooterButton side="left" onClick={terms.onToggle} aria-label={web.terms.title}>
|
||||
{web.terms.title}
|
||||
</FooterButton>
|
||||
</If>
|
||||
<If c={web.help_menu.enable}>
|
||||
<FooterButton side="left" onClick={help.onToggle} aria-label={web.help_menu.title}>
|
||||
{web.help_menu.title}
|
||||
</FooterButton>
|
||||
</If>
|
||||
<Flex
|
||||
p={0}
|
||||
flexGrow={0}
|
||||
flexShrink={0}
|
||||
maxWidth="100%"
|
||||
flexBasis="auto"
|
||||
marginRight="auto"
|
||||
/>
|
||||
<If c={web.credit.enable}>
|
||||
<FooterButton side="right" onClick={credit.onToggle} aria-label="Powered by hyperglass">
|
||||
<FiCode />
|
||||
</FooterButton>
|
||||
</If>
|
||||
<If c={web.external_link.enable}>
|
||||
<FooterButton
|
||||
size="xs"
|
||||
side="right"
|
||||
href={extUrl}
|
||||
variant="ghost"
|
||||
aria-label={web.external_link.title}
|
||||
rightIcon={<Box as={GoLinkExternal} />}>
|
||||
{web.external_link.title}
|
||||
</FooterButton>
|
||||
</If>
|
||||
</Flex>
|
||||
</>
|
||||
<Flex
|
||||
px={6}
|
||||
w="100%"
|
||||
zIndex={1}
|
||||
as="footer"
|
||||
bg={footerBg}
|
||||
flexWrap="wrap"
|
||||
textAlign="center"
|
||||
alignItems="center"
|
||||
color={footerColor}
|
||||
py={{ base: 4, lg: 2 }}
|
||||
justifyContent="space-between">
|
||||
<If c={web.terms.enable}>
|
||||
<FooterButton side="left" content={content.terms} title={web.terms.title} />
|
||||
</If>
|
||||
<If c={web.help_menu.enable}>
|
||||
<FooterButton side="left" content={content.help_menu} title={web.help_menu.title} />
|
||||
</If>
|
||||
<Flex p={0} flexGrow={0} flexShrink={0} maxWidth="100%" flexBasis="auto" marginRight="auto" />
|
||||
<If c={web.credit.enable}>
|
||||
<FooterButton side="right" content={content.credit} title={<CodeIcon />} />
|
||||
</If>
|
||||
<If c={web.external_link.enable}>
|
||||
<Button
|
||||
size="xs"
|
||||
as={Link}
|
||||
isExternal
|
||||
href={extUrl}
|
||||
variant="ghost"
|
||||
rightIcon={<ExtIcon />}
|
||||
aria-label={web.external_link.title}>
|
||||
{web.external_link.title}
|
||||
</Button>
|
||||
</If>
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
@@ -1,16 +1,11 @@
|
||||
import type { ButtonProps, DrawerProps, DrawerContentProps } from '@chakra-ui/react';
|
||||
import type { MenuListProps } from '@chakra-ui/react';
|
||||
|
||||
type TFooterSide = 'left' | 'right';
|
||||
|
||||
export interface TFooterButton extends ButtonProps {
|
||||
export interface TFooterButton extends Omit<MenuListProps, 'title'> {
|
||||
side: TFooterSide;
|
||||
href?: string;
|
||||
}
|
||||
|
||||
export interface TFooterContent extends Omit<DrawerProps, 'children'>, DrawerContentProps {
|
||||
isOpen: boolean;
|
||||
title?: MenuListProps['children'];
|
||||
content: string;
|
||||
side: TFooterSide;
|
||||
}
|
||||
|
||||
export type TFooterItems = 'help' | 'credit' | 'terms';
|
||||
|
@@ -1,4 +1,5 @@
|
||||
import { chakra } from '@chakra-ui/react';
|
||||
import { motion } from 'framer-motion';
|
||||
|
||||
export const AnimatedDiv = chakra(motion.div);
|
||||
export const AnimatedDiv = motion.custom(chakra.div);
|
||||
export const AnimatedForm = motion.custom(chakra.form);
|
||||
|
@@ -46,9 +46,9 @@ export const SubmitButton = forwardRef<HTMLDivElement, TSubmitButton>((props, re
|
||||
} = props;
|
||||
const _isDisabled = isDisabled || isLoading;
|
||||
|
||||
const bg = useColorValue('primary.500', 'primary.300');
|
||||
const bgActive = useColorValue('primary.600', 'primary.400');
|
||||
const bgHover = useColorValue('primary.400', 'primary.200');
|
||||
const bg = useColorValue('primary.400', 'primary.500');
|
||||
const bgActive = useColorValue('primary.500', 'primary.600');
|
||||
const bgHover = useColorValue('primary.300', 'primary.400');
|
||||
const color = useOpposingColor(bg);
|
||||
const colorActive = useOpposingColor(bgActive);
|
||||
const colorHover = useOpposingColor(bgHover);
|
||||
|
@@ -41,12 +41,12 @@ export const Debugger = () => {
|
||||
position="relative"
|
||||
justifyContent="center"
|
||||
borderColor={borderColor}>
|
||||
<Tag variantColor="gray">{colorMode.toUpperCase()}</Tag>
|
||||
<Tag variantColor="teal">{mediaSize}</Tag>
|
||||
<Button size="sm" variantColor="cyan" onClick={onConfigOpen}>
|
||||
<Tag colorScheme="gray">{colorMode.toUpperCase()}</Tag>
|
||||
<Tag colorScheme="teal">{mediaSize}</Tag>
|
||||
<Button size="sm" colorScheme="cyan" onClick={onConfigOpen}>
|
||||
View Config
|
||||
</Button>
|
||||
<Button size="sm" variantColor="purple" onClick={onThemeOpen}>
|
||||
<Button size="sm" colorScheme="purple" onClick={onThemeOpen}>
|
||||
View Theme
|
||||
</Button>
|
||||
</Stack>
|
||||
|
@@ -33,7 +33,7 @@ export const CommunitySelect = (props: TCommunitySelect) => {
|
||||
const options = useMemo(() => buildOptions(communities), [communities.length]);
|
||||
|
||||
function handleChange(e: TSelectOption | TSelectOption[]): void {
|
||||
if (!Array.isArray(e)) {
|
||||
if (!Array.isArray(e) && e !== null) {
|
||||
onChange({ field: name, value: e.value });
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@ export const QueryLocation = (props: TQuerySelectField) => {
|
||||
const options = useMemo(() => buildOptions(networks), [networks.length]);
|
||||
|
||||
function handleChange(e: TSelectOption): void {
|
||||
if (Array.isArray(e.value)) {
|
||||
if (Array.isArray(e?.value) && e !== null) {
|
||||
const value = e.value.map(sel => sel);
|
||||
onChange({ field: 'query_location', value });
|
||||
}
|
||||
|
@@ -56,11 +56,11 @@ export const QueryTarget = (props: TQueryTarget) => {
|
||||
bg={bg}
|
||||
size="lg"
|
||||
color={color}
|
||||
borderRadius="md"
|
||||
onBlur={handleBlur}
|
||||
onFocus={handleBlur}
|
||||
value={displayValue}
|
||||
borderColor={border}
|
||||
borderRadius="0.25rem"
|
||||
onChange={handleChange}
|
||||
aria-label={placeholder}
|
||||
onKeyDown={handleKeyDown}
|
||||
|
@@ -18,7 +18,9 @@ export const QueryType = (props: TQuerySelectField) => {
|
||||
const options = useMemo(() => buildOptions(queries.list), [queries.list.length]);
|
||||
|
||||
function handleChange(e: TSelectOption): void {
|
||||
onChange({ field: 'query_type', value: e.value });
|
||||
if (e !== null) {
|
||||
onChange({ field: 'query_type', value: e.value });
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
@@ -14,7 +14,9 @@ export const QueryVrf = (props: TQueryVrf) => {
|
||||
const options = useMemo(() => buildOptions(vrfs), [vrfs.length]);
|
||||
|
||||
function handleChange(e: TSelectOption): void {
|
||||
onChange({ field: 'query_vrf', value: e.value });
|
||||
if (e !== null) {
|
||||
onChange({ field: 'query_vrf', value: e.value });
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
@@ -25,14 +25,7 @@ export const Frame = (props: TFrame) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
<Flex
|
||||
bg={bg}
|
||||
w="100%"
|
||||
color={color}
|
||||
flexDir="column"
|
||||
minHeight="100vh"
|
||||
ref={containerRef}
|
||||
{...props}>
|
||||
<Flex bg={bg} w="100%" color={color} flexDir="column" minHeight="100vh" ref={containerRef}>
|
||||
<Flex px={2} flex="0 1 auto" flexDirection="column">
|
||||
<Header resetForm={resetForm} />
|
||||
</Flex>
|
||||
@@ -49,9 +42,9 @@ export const Frame = (props: TFrame) => {
|
||||
{...props}
|
||||
/>
|
||||
<Footer />
|
||||
<If c={developer_mode}>
|
||||
{/* <If c={developer_mode}>
|
||||
<Debugger />
|
||||
</If>
|
||||
</If> */}
|
||||
</Flex>
|
||||
<If c={web.greeting.enable && !greetingAck}>
|
||||
<Greeting onClickThrough={setGreetingAck} />
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { motion, AnimatePresence } from 'framer-motion';
|
||||
import { AnimatePresence } from 'framer-motion';
|
||||
import { If, HyperglassForm, Results } from '~/components';
|
||||
import { useGlobalState } from '~/context';
|
||||
import { all } from '~/util';
|
||||
@@ -28,13 +28,7 @@ export const Layout: React.FC = () => {
|
||||
</If>
|
||||
<AnimatePresence>
|
||||
<If c={!isSubmitting.value}>
|
||||
<motion.div
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
exit={{ opacity: 0, x: -300 }}
|
||||
initial={{ opacity: 0, y: 300 }}>
|
||||
<HyperglassForm />
|
||||
</motion.div>
|
||||
<HyperglassForm />
|
||||
</If>
|
||||
</AnimatePresence>
|
||||
</Frame>
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import { useEffect, useMemo, useState } from 'react';
|
||||
import { Box, Flex } from '@chakra-ui/react';
|
||||
import { Flex } from '@chakra-ui/react';
|
||||
import { useForm } from 'react-hook-form';
|
||||
import { uniqWith } from 'lodash';
|
||||
import * as yup from 'yup';
|
||||
import {
|
||||
AnimatedForm,
|
||||
FormRow,
|
||||
QueryVrf,
|
||||
FormField,
|
||||
@@ -248,13 +249,16 @@ export const HyperglassForm = () => {
|
||||
Object.keys(errors).length >= 1 && console.error(errors);
|
||||
|
||||
return (
|
||||
<Box
|
||||
<AnimatedForm
|
||||
p={0}
|
||||
my={4}
|
||||
w="100%"
|
||||
as="form"
|
||||
mx="auto"
|
||||
textAlign="left"
|
||||
animate={{ opacity: 1, y: 0 }}
|
||||
transition={{ duration: 0.3 }}
|
||||
exit={{ opacity: 0, x: -300 }}
|
||||
initial={{ opacity: 0, y: 300 }}
|
||||
onSubmit={handleSubmit(onSubmit)}
|
||||
maxW={{ base: '100%', lg: '75%' }}>
|
||||
<FormRow>
|
||||
@@ -330,6 +334,6 @@ export const HyperglassForm = () => {
|
||||
<SubmitButton isLoading={isSubmitting.value} />
|
||||
</Flex>
|
||||
</FormRow>
|
||||
</Box>
|
||||
</AnimatedForm>
|
||||
);
|
||||
};
|
||||
|
@@ -23,13 +23,13 @@ export const useControlStyle = (base: TStyles, state: TControl): TStyles => {
|
||||
const { colorMode } = useSelectContext();
|
||||
const borderHover = useColorValue(
|
||||
useToken('colors', 'gray.300'),
|
||||
useToken('colors', 'whiteAlpha.200'),
|
||||
useToken('colors', 'whiteAlpha.400'),
|
||||
);
|
||||
const focusBorder = useToken('colors', 'secondary.500');
|
||||
const focusBorder = useColorValue(useToken('colors', 'blue.500'), useToken('colors', 'blue.300'));
|
||||
const invalidBorder = useColorValue(useToken('colors', 'red.500'), useToken('colors', 'red.300'));
|
||||
|
||||
const borderColor = useColorValue('inherit', useToken('colors', 'whiteAlpha.50'));
|
||||
const borderRadius = useToken('radii', 'md');
|
||||
const minHeight = useToken('sizes', 'lg');
|
||||
const minHeight = useToken('space', 12);
|
||||
const color = useColorValue(useToken('colors', 'black'), useToken('colors', 'whiteAlpha.800'));
|
||||
const backgroundColor = useColorValue(
|
||||
useToken('colors', 'white'),
|
||||
@@ -40,9 +40,12 @@ export const useControlStyle = (base: TStyles, state: TControl): TStyles => {
|
||||
borderRadius,
|
||||
color,
|
||||
minHeight,
|
||||
transition: 'all 0.2s',
|
||||
borderColor: isFocused ? focusBorder : borderColor,
|
||||
boxShadow: isFocused ? `0 0 0 1px ${focusBorder}` : undefined,
|
||||
'&:hover': { borderColor: isFocused ? focusBorder : borderHover },
|
||||
'&:hover > div > span': { backgroundColor: borderHover },
|
||||
|
||||
'&:focus': { borderColor: focusBorder },
|
||||
'&.invalid': { borderColor: invalidBorder, boxShadow: `0 0 0 1px ${invalidBorder}` },
|
||||
};
|
||||
return useMemo(() => mergeWith({}, base, styles), [colorMode, isFocused]);
|
||||
@@ -52,7 +55,7 @@ export const useMenuStyle = (base: TStyles, state: TMenu): TStyles => {
|
||||
const { colorMode, isOpen } = useSelectContext();
|
||||
const backgroundColor = useColorValue(
|
||||
useToken('colors', 'white'),
|
||||
useToken('colors', 'whiteFaded.50'),
|
||||
useToken('colors', 'blackFaded.800'),
|
||||
);
|
||||
const borderRadius = useToken('radii', 'md');
|
||||
const styles = { borderRadius, backgroundColor };
|
||||
@@ -87,7 +90,7 @@ export const useMenuListStyle = (base: TStyles, state: TMenuList): TStyles => {
|
||||
};
|
||||
|
||||
export const useOptionStyle = (base: TStyles, state: TOption): TStyles => {
|
||||
const { isFocused } = state;
|
||||
const { isFocused, isSelected, isDisabled } = state;
|
||||
const { colorMode, isOpen } = useSelectContext();
|
||||
const fontSize = useToken('fontSizes', 'lg');
|
||||
const disabled = useToken('colors', 'whiteAlpha.400');
|
||||
@@ -103,31 +106,42 @@ export const useOptionStyle = (base: TStyles, state: TOption): TStyles => {
|
||||
useToken('colors', 'primary.600'),
|
||||
useToken('colors', 'primary.400'),
|
||||
);
|
||||
const disabledColor = useOpposingColor(disabled);
|
||||
const selectedColor = useOpposingColor(selected);
|
||||
const focusedColor = useOpposingColor(focused);
|
||||
|
||||
const activeColor = useOpposingColor(active);
|
||||
|
||||
const backgroundColor = useMemo(() => {
|
||||
let bg = 'transparent';
|
||||
switch (true) {
|
||||
case isDisabled:
|
||||
bg = disabled;
|
||||
break;
|
||||
case isSelected:
|
||||
bg = selected;
|
||||
break;
|
||||
case isFocused:
|
||||
bg = focused;
|
||||
break;
|
||||
}
|
||||
return bg;
|
||||
}, [isDisabled, isFocused, isSelected]);
|
||||
|
||||
const color = useOpposingColor(backgroundColor);
|
||||
|
||||
const styles = {
|
||||
backgroundColor: state.isDisabled
|
||||
? disabled
|
||||
: state.isSelected
|
||||
? selected
|
||||
: state.isFocused
|
||||
? focused
|
||||
: 'transparent',
|
||||
color: state.isDisabled
|
||||
? disabledColor
|
||||
: state.isSelected
|
||||
? selectedColor
|
||||
: state.isFocused
|
||||
? focusedColor
|
||||
: 'transparent',
|
||||
backgroundColor,
|
||||
color,
|
||||
fontSize,
|
||||
'&:focus': { backgroundColor: active, color: activeColor },
|
||||
'&:active': { backgroundColor: active, color: activeColor },
|
||||
};
|
||||
return useMemo(() => mergeWith({}, base, styles), [colorMode, isFocused, isOpen]);
|
||||
|
||||
return useMemo(() => mergeWith({}, base, styles), [
|
||||
isOpen,
|
||||
colorMode,
|
||||
isFocused,
|
||||
isDisabled,
|
||||
isSelected,
|
||||
]);
|
||||
};
|
||||
|
||||
export const useIndicatorSeparatorStyle = (base: TStyles, state: TIndicator): TStyles => {
|
||||
@@ -142,8 +156,9 @@ export const useIndicatorSeparatorStyle = (base: TStyles, state: TIndicator): TS
|
||||
|
||||
export const usePlaceholderStyle = (base: TStyles, state: TPlaceholder): TStyles => {
|
||||
const { colorMode } = useSelectContext();
|
||||
const color = useColorValue(useToken('colors', 'whiteAlpha.700'), useToken('colors', 'gray.600'));
|
||||
return useMemo(() => mergeWith({}, base, { color }), [colorMode]);
|
||||
const color = useColorValue(useToken('colors', 'gray.600'), useToken('colors', 'whiteAlpha.700'));
|
||||
const fontSize = useToken('fontSizes', 'lg');
|
||||
return useMemo(() => mergeWith({}, base, { color, fontSize }), [colorMode]);
|
||||
};
|
||||
|
||||
export const useSingleValueStyle = (props: TStyles) => {
|
||||
|
@@ -1,7 +1,8 @@
|
||||
export type TSelectOption = {
|
||||
label: string;
|
||||
value: string | string[];
|
||||
};
|
||||
group?: string;
|
||||
} | null;
|
||||
|
||||
export type TSelectOptionGroup = {
|
||||
label: string;
|
||||
|
@@ -1,77 +0,0 @@
|
||||
import dayjs from 'dayjs';
|
||||
import relativeTimePlugin from 'dayjs/plugin/relativeTime';
|
||||
import utcPlugin from 'dayjs/plugin/utc';
|
||||
|
||||
dayjs.extend(relativeTimePlugin);
|
||||
dayjs.extend(utcPlugin);
|
||||
|
||||
const formatAsPath = path => {
|
||||
return path.join(' → ');
|
||||
};
|
||||
|
||||
const formatCommunities = comms => {
|
||||
const commsStr = comms.map(c => ` - ${c}`);
|
||||
return '\n' + commsStr.join('\n');
|
||||
};
|
||||
|
||||
const formatBool = val => {
|
||||
let fmt = '';
|
||||
if (val === true) {
|
||||
fmt = 'yes';
|
||||
} else if (val === false) {
|
||||
fmt = 'no';
|
||||
}
|
||||
return fmt;
|
||||
};
|
||||
|
||||
const formatTime = val => {
|
||||
const now = dayjs.utc();
|
||||
const then = now.subtract(val, 'seconds');
|
||||
const timestamp = then.toString().replace('GMT', 'UTC');
|
||||
const relative = now.to(then, true);
|
||||
return `${relative} (${timestamp})`;
|
||||
};
|
||||
|
||||
export const tableToString = (target, data, config) => {
|
||||
try {
|
||||
const formatRpkiState = val => {
|
||||
const rpkiStateNames = [
|
||||
config.web.text.rpki_invalid,
|
||||
config.web.text.rpki_valid,
|
||||
config.web.text.rpki_unknown,
|
||||
config.web.text.rpki_unverified,
|
||||
];
|
||||
return rpkiStateNames[val];
|
||||
};
|
||||
|
||||
const tableFormatMap = {
|
||||
age: formatTime,
|
||||
active: formatBool,
|
||||
as_path: formatAsPath,
|
||||
communities: formatCommunities,
|
||||
rpki_state: formatRpkiState,
|
||||
};
|
||||
|
||||
let tableStringParts = [`Routes For: ${target}`, `Timestamp: ${data.timestamp} UTC`];
|
||||
|
||||
data.output.routes.map(route => {
|
||||
config.parsed_data_fields.map(field => {
|
||||
const [header, accessor, align] = field;
|
||||
if (align !== null) {
|
||||
let value = route[accessor];
|
||||
const fmtFunc = tableFormatMap[accessor] ?? String;
|
||||
value = fmtFunc(value);
|
||||
if (accessor === 'prefix') {
|
||||
tableStringParts.push(` - ${header}: ${value}`);
|
||||
} else {
|
||||
tableStringParts.push(` - ${header}: ${value}`);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
return tableStringParts.join('\n');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
return `An error occurred while parsing the output: '${err.message}'`;
|
||||
}
|
||||
};
|
@@ -1,3 +1,2 @@
|
||||
export * from './common';
|
||||
export * from './formatters';
|
||||
export * from './theme';
|
||||
|
Reference in New Issue
Block a user