forked from mirrors/thatmattlove-hyperglass
update UI dependencies, fix layout issues
This commit is contained in:
parent
8c8e4f8109
commit
0c0bdc7f9b
10 changed files with 812 additions and 631 deletions
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Flex, FormControl, FormErrorMessage, FormLabel } from '@chakra-ui/react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Flex, FormControl, FormLabel, FormErrorMessage } from '@chakra-ui/react';
|
|
||||||
import { useFormContext } from 'react-hook-form';
|
import { useFormContext } from 'react-hook-form';
|
||||||
import { If, Then } from 'react-if';
|
import { If, Then } from 'react-if';
|
||||||
import { useBooleanValue, useColorValue } from '~/hooks';
|
import { useBooleanValue, useColorValue } from '~/hooks';
|
||||||
|
|
@ -40,6 +40,7 @@ export const FormField = (props: FormFieldProps): JSX.Element => {
|
||||||
w="100%"
|
w="100%"
|
||||||
maxW="100%"
|
maxW="100%"
|
||||||
flexDir="column"
|
flexDir="column"
|
||||||
|
alignItems="center"
|
||||||
my={{ base: 2, lg: 4 }}
|
my={{ base: 2, lg: 4 }}
|
||||||
isInvalid={error !== null}
|
isInvalid={error !== null}
|
||||||
{...rest}
|
{...rest}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
|
import { Flex, ScaleFade, SlideFade, chakra } from '@chakra-ui/react';
|
||||||
|
import { vestResolver } from '@hookform/resolvers/vest';
|
||||||
import { useCallback, useEffect, useMemo } from 'react';
|
import { useCallback, useEffect, useMemo } from 'react';
|
||||||
import isEqual from 'react-fast-compare';
|
import isEqual from 'react-fast-compare';
|
||||||
import { chakra, Flex, ScaleFade, SlideFade } from '@chakra-ui/react';
|
|
||||||
import { FormProvider, useForm } from 'react-hook-form';
|
import { FormProvider, useForm } from 'react-hook-form';
|
||||||
import { vestResolver } from '@hookform/resolvers/vest';
|
|
||||||
import vest, { test, enforce } from 'vest';
|
import vest, { test, enforce } from 'vest';
|
||||||
import {
|
import {
|
||||||
FormField,
|
|
||||||
DirectiveInfoModal,
|
DirectiveInfoModal,
|
||||||
QueryType,
|
FormField,
|
||||||
QueryTarget,
|
|
||||||
SubmitButton,
|
|
||||||
QueryLocation,
|
QueryLocation,
|
||||||
|
QueryTarget,
|
||||||
|
QueryType,
|
||||||
|
SubmitButton,
|
||||||
} from '~/components';
|
} from '~/components';
|
||||||
import { useConfig } from '~/context';
|
import { useConfig } from '~/context';
|
||||||
import { FormRow } from '~/elements';
|
import { FormRow } from '~/elements';
|
||||||
import { useStrf, useGreeting, useDevice, useFormState } from '~/hooks';
|
import { useDevice, useFormState, useGreeting, useStrf } from '~/hooks';
|
||||||
|
import { Directive, isQueryField, isString } from '~/types';
|
||||||
import { isFQDN } from '~/util';
|
import { isFQDN } from '~/util';
|
||||||
import { isString, isQueryField, Directive } from '~/types';
|
|
||||||
|
|
||||||
import type { FormData, OnChangeArgs } from '~/types';
|
import type { FormData, OnChangeArgs } from '~/types';
|
||||||
|
|
||||||
|
|
@ -70,7 +70,6 @@ export const LookingGlassForm = (): JSX.Element => {
|
||||||
|
|
||||||
const { handleSubmit, register, setValue, setError, clearErrors } = formInstance;
|
const { handleSubmit, register, setValue, setError, clearErrors } = formInstance;
|
||||||
|
|
||||||
// const isFqdnQuery = useIsFqdn(form.queryTarget, form.queryType);
|
|
||||||
const isFqdnQuery = useCallback(
|
const isFqdnQuery = useCallback(
|
||||||
(target: string | string[], fieldType: Directive['fieldType'] | null): boolean =>
|
(target: string | string[], fieldType: Directive['fieldType'] | null): boolean =>
|
||||||
typeof target === 'string' && fieldType === 'text' && isFQDN(target),
|
typeof target === 'string' && fieldType === 'text' && isFQDN(target),
|
||||||
|
|
@ -79,20 +78,21 @@ export const LookingGlassForm = (): JSX.Element => {
|
||||||
|
|
||||||
const directive = useMemo<Directive | null>(
|
const directive = useMemo<Directive | null>(
|
||||||
() => getDirective(),
|
() => getDirective(),
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
||||||
[form.queryType, form.queryLocation, getDirective],
|
[form.queryType, form.queryLocation, getDirective],
|
||||||
);
|
);
|
||||||
|
|
||||||
function submitHandler(): void {
|
function submitHandler(): void {
|
||||||
console.table({
|
if (process.env.NODE_ENV === 'development') {
|
||||||
'Query Location': form.queryLocation.toString(),
|
console.table({
|
||||||
'Query Type': form.queryType,
|
'Query Location': form.queryLocation.toString(),
|
||||||
'Query Target': form.queryTarget,
|
'Query Type': form.queryType,
|
||||||
'Selected Directive': directive?.name ?? null,
|
'Query Target': form.queryTarget,
|
||||||
});
|
'Selected Directive': directive?.name ?? null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Before submitting a query, make sure the greeting is acknowledged if required. This should
|
// Before submitting a query, make sure the greeting is acknowledged if required. This should
|
||||||
// be handled before loading the app, but people be sneaky.
|
// be handled before loading the app, but people be sneaky.
|
||||||
|
|
||||||
if (!greetingReady) {
|
if (!greetingReady) {
|
||||||
resetForm();
|
resetForm();
|
||||||
location.reload();
|
location.reload();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
|
import { Badge, Box, Flex, SkeletonText, VStack } from '@chakra-ui/react';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import { Box, Flex, SkeletonText, Badge, VStack } from '@chakra-ui/react';
|
|
||||||
import ReactFlow, {
|
import ReactFlow, {
|
||||||
Background,
|
Background,
|
||||||
ReactFlowProvider,
|
ReactFlowProvider,
|
||||||
|
|
@ -7,13 +7,13 @@ import ReactFlow, {
|
||||||
Position,
|
Position,
|
||||||
isNode,
|
isNode,
|
||||||
isEdge,
|
isEdge,
|
||||||
} from 'react-flow-renderer';
|
} from 'reactflow';
|
||||||
import { useConfig } from '~/context';
|
import { useConfig } from '~/context';
|
||||||
import { useASNDetail, useColorValue, useColorToken } from '~/hooks';
|
import { useASNDetail, useColorToken, useColorValue } from '~/hooks';
|
||||||
import { Controls } from './controls';
|
import { Controls } from './controls';
|
||||||
import { useElements } from './useElements';
|
import { useElements } from './useElements';
|
||||||
|
|
||||||
import type { NodeProps as ReactFlowNodeProps } from 'react-flow-renderer';
|
import type { NodeProps as ReactFlowNodeProps } from 'reactflow';
|
||||||
|
|
||||||
interface ChartProps {
|
interface ChartProps {
|
||||||
data: StructuredResponse;
|
data: StructuredResponse;
|
||||||
|
|
@ -49,7 +49,11 @@ export const Chart = (props: ChartProps): JSX.Element => {
|
||||||
nodes={nodes}
|
nodes={nodes}
|
||||||
edges={edges}
|
edges={edges}
|
||||||
nodeTypes={{ ASNode }}
|
nodeTypes={{ ASNode }}
|
||||||
|
edgesUpdatable={false}
|
||||||
|
nodesDraggable={false}
|
||||||
|
nodesConnectable={false}
|
||||||
onInit={inst => setTimeout(() => inst.fitView(), 0)}
|
onInit={inst => setTimeout(() => inst.fitView(), 0)}
|
||||||
|
proOptions={{ hideAttribution: true }}
|
||||||
>
|
>
|
||||||
<Background color={dots} />
|
<Background color={dots} />
|
||||||
<Controls />
|
<Controls />
|
||||||
|
|
@ -64,15 +68,15 @@ const ASNode = (props: NodeProps<NodeData>): JSX.Element => {
|
||||||
const { asn, name, hasChildren, hasParents } = data;
|
const { asn, name, hasChildren, hasParents } = data;
|
||||||
|
|
||||||
const color = useColorValue('black', 'white');
|
const color = useColorValue('black', 'white');
|
||||||
const bg = useColorValue('white', 'whiteAlpha.100');
|
const bg = useColorValue('white', 'whiteAlpha.200');
|
||||||
|
|
||||||
const { data: asnData, isError, isLoading } = useASNDetail(String(asn));
|
const { data: asnData, isError, isLoading } = useASNDetail(String(asn));
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
{hasChildren && <Handle type="source" position={Position.Top} />}
|
{hasChildren && <Handle type="source" position={Position.Top} />}
|
||||||
<Box py={3} px={4} bg={bg} minW={40} minH={12} color={color} boxShadow="md" borderRadius="md">
|
<Box py={2} px={3} bg={bg} minW={32} minH={8} color={color} boxShadow="md" borderRadius="md">
|
||||||
<VStack spacing={4}>
|
<VStack spacing={2}>
|
||||||
<Flex fontSize="lg">
|
<Flex fontSize="lg">
|
||||||
{isLoading ? (
|
{isLoading ? (
|
||||||
<Box h={2} w={24}>
|
<Box h={2} w={24}>
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
import { ButtonGroup, IconButton } from '@chakra-ui/react';
|
import { ButtonGroup, IconButton } from '@chakra-ui/react';
|
||||||
import { useReactFlow } from 'react-flow-renderer';
|
import { useReactFlow } from 'reactflow';
|
||||||
import { DynamicIcon } from '~/elements';
|
import { DynamicIcon } from '~/elements';
|
||||||
|
|
||||||
export const Controls = (): JSX.Element => {
|
export const Controls = (): JSX.Element => {
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,17 @@
|
||||||
import {
|
import {
|
||||||
Modal,
|
Modal,
|
||||||
Skeleton,
|
|
||||||
ModalBody,
|
ModalBody,
|
||||||
|
ModalCloseButton,
|
||||||
|
ModalContent,
|
||||||
ModalHeader,
|
ModalHeader,
|
||||||
ModalOverlay,
|
ModalOverlay,
|
||||||
ModalContent,
|
Skeleton,
|
||||||
useDisclosure,
|
useDisclosure,
|
||||||
ModalCloseButton,
|
|
||||||
} from '@chakra-ui/react';
|
} from '@chakra-ui/react';
|
||||||
import { useFormState, useColorValue, useBreakpointValue } from '~/hooks';
|
import 'reactflow/dist/style.css';
|
||||||
import { PathButton } from './path-button';
|
import { useBreakpointValue, useColorValue, useFormState } from '~/hooks';
|
||||||
import { Chart } from './chart';
|
import { Chart } from './chart';
|
||||||
|
import { PathButton } from './path-button';
|
||||||
|
|
||||||
interface PathProps {
|
interface PathProps {
|
||||||
device: string;
|
device: string;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ import dagre from 'dagre';
|
||||||
import { useMemo } from 'react';
|
import { useMemo } from 'react';
|
||||||
import isEqual from 'react-fast-compare';
|
import isEqual from 'react-fast-compare';
|
||||||
|
|
||||||
import type { Node, Edge } from 'react-flow-renderer';
|
import type { Edge, Node } from 'reactflow';
|
||||||
import type { NodeData } from './chart';
|
import type { NodeData } from './chart';
|
||||||
|
|
||||||
interface BasePath {
|
interface BasePath {
|
||||||
|
|
@ -12,7 +12,7 @@ interface BasePath {
|
||||||
|
|
||||||
type FlowElement<T> = Node<T> | Edge<T>;
|
type FlowElement<T> = Node<T> | Edge<T>;
|
||||||
|
|
||||||
const NODE_WIDTH = 200;
|
const NODE_WIDTH = 128;
|
||||||
const NODE_HEIGHT = 48;
|
const NODE_HEIGHT = 48;
|
||||||
|
|
||||||
export function useElements(base: BasePath, data: StructuredResponse): FlowElement<NodeData>[] {
|
export function useElements(base: BasePath, data: StructuredResponse): FlowElement<NodeData>[] {
|
||||||
|
|
|
||||||
|
|
@ -124,7 +124,7 @@ export const QueryLocation = (props: QueryLocationProps): JSX.Element => {
|
||||||
align="flex-start"
|
align="flex-start"
|
||||||
shouldWrapChildren
|
shouldWrapChildren
|
||||||
spacing={{ base: 4, lg: 8 }}
|
spacing={{ base: 4, lg: 8 }}
|
||||||
justify={{ base: 'center', lg: 'flex-start' }}
|
justify={{ base: 'center', lg: 'center' }}
|
||||||
>
|
>
|
||||||
{options[0].options.map(opt => {
|
{options[0].options.map(opt => {
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { useEffect } from 'react';
|
|
||||||
import { Accordion } from '@chakra-ui/react';
|
import { Accordion } from '@chakra-ui/react';
|
||||||
import { AnimatePresence } from 'framer-motion';
|
import { AnimatePresence } from 'framer-motion';
|
||||||
|
import { useEffect } from 'react';
|
||||||
import { AnimatedDiv } from '~/elements';
|
import { AnimatedDiv } from '~/elements';
|
||||||
import { useFormState } from '~/hooks';
|
import { useFormState } from '~/hooks';
|
||||||
import { Result } from './individual';
|
import { Result } from './individual';
|
||||||
|
|
@ -34,7 +34,7 @@ export const Results = (): JSX.Element => {
|
||||||
animate={{ opacity: 1, y: 0 }}
|
animate={{ opacity: 1, y: 0 }}
|
||||||
maxW={{ base: '100%', md: '75%' }}
|
maxW={{ base: '100%', md: '75%' }}
|
||||||
>
|
>
|
||||||
<Accordion allowMultiple allowToggle>
|
<Accordion allowMultiple>
|
||||||
<AnimatePresence>
|
<AnimatePresence>
|
||||||
{queryLocation.length > 0 &&
|
{queryLocation.length > 0 &&
|
||||||
queryLocation.map((location, index) => {
|
queryLocation.map((location, index) => {
|
||||||
|
|
|
||||||
14
hyperglass/ui/package.json
vendored
14
hyperglass/ui/package.json
vendored
|
|
@ -17,12 +17,12 @@
|
||||||
},
|
},
|
||||||
"browserslist": "> 0.25%, not dead",
|
"browserslist": "> 0.25%, not dead",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@chakra-ui/react": "^2.5.5",
|
"@chakra-ui/react": "^2.8.2",
|
||||||
"@chakra-ui/theme": "3.0.1",
|
"@chakra-ui/theme": "3.3.1",
|
||||||
"@chakra-ui/theme-tools": "^2.0.17",
|
"@chakra-ui/theme-tools": "^2.1.2",
|
||||||
"@chakra-ui/utils": "^2.0.15",
|
"@chakra-ui/utils": "^2.0.14",
|
||||||
"@emotion/react": "^11.10.6",
|
"@emotion/react": "^11.11.4",
|
||||||
"@emotion/styled": "^11.10.6",
|
"@emotion/styled": "^11.11.0",
|
||||||
"@hookform/devtools": "^4.3.0",
|
"@hookform/devtools": "^4.3.0",
|
||||||
"@hookform/resolvers": "^2.9.10",
|
"@hookform/resolvers": "^2.9.10",
|
||||||
"@tanstack/react-query": "^4.22.0",
|
"@tanstack/react-query": "^4.22.0",
|
||||||
|
|
@ -39,7 +39,6 @@
|
||||||
"react-device-detect": "^1.15.0",
|
"react-device-detect": "^1.15.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
"react-fast-compare": "^3.2.1",
|
"react-fast-compare": "^3.2.1",
|
||||||
"react-flow-renderer": "^10.3.17",
|
|
||||||
"react-hook-form": "^7.42.1",
|
"react-hook-form": "^7.42.1",
|
||||||
"react-icons": "^4.3.1",
|
"react-icons": "^4.3.1",
|
||||||
"react-if": "^4.1.4",
|
"react-if": "^4.1.4",
|
||||||
|
|
@ -47,6 +46,7 @@
|
||||||
"react-select": "^5.7.0",
|
"react-select": "^5.7.0",
|
||||||
"react-string-replace": "^0.5.0",
|
"react-string-replace": "^0.5.0",
|
||||||
"react-table": "^7.7.0",
|
"react-table": "^7.7.0",
|
||||||
|
"reactflow": "^11.10.4",
|
||||||
"remark-gfm": "^1.0.0",
|
"remark-gfm": "^1.0.0",
|
||||||
"string-format": "^2.0.0",
|
"string-format": "^2.0.0",
|
||||||
"vest": "^3.2.8",
|
"vest": "^3.2.8",
|
||||||
|
|
|
||||||
1351
hyperglass/ui/pnpm-lock.yaml
generated
1351
hyperglass/ui/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue