From 0b045c412250a705995a0d846ac174fabdf203f2 Mon Sep 17 00:00:00 2001 From: amcdnl Date: Tue, 16 Apr 2024 06:01:02 -0400 Subject: [PATCH] json tree continued --- src/layout/Tree/JsonTree/JsonTree.story.tsx | 3 + src/layout/Tree/JsonTree/JsonTree.tsx | 23 +++-- src/layout/Tree/JsonTree/JsonTreeNode.tsx | 47 ++++++--- src/layout/Tree/JsonTree/JsonTreeTheme.ts | 15 +++ src/layout/Tree/JsonTree/index.ts | 3 + src/layout/Tree/JsonTree/utils.ts | 102 ++++++++++++++++++++ src/layout/Tree/index.tsx | 1 + 7 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 src/layout/Tree/JsonTree/JsonTreeTheme.ts diff --git a/src/layout/Tree/JsonTree/JsonTree.story.tsx b/src/layout/Tree/JsonTree/JsonTree.story.tsx index 33f5a75a..cc784bb0 100644 --- a/src/layout/Tree/JsonTree/JsonTree.story.tsx +++ b/src/layout/Tree/JsonTree/JsonTree.story.tsx @@ -9,6 +9,7 @@ export default { const data = { name: 'John Doe', age: 30, + over21: true, children: [ { name: 'Jane Doe', age: 25 }, { name: 'Jim Doe', age: 33 } @@ -16,3 +17,5 @@ const data = { }; export const Simple = () => ; + +export const Expanded = () => ; diff --git a/src/layout/Tree/JsonTree/JsonTree.tsx b/src/layout/Tree/JsonTree/JsonTree.tsx index 7ca62994..032d92a8 100644 --- a/src/layout/Tree/JsonTree/JsonTree.tsx +++ b/src/layout/Tree/JsonTree/JsonTree.tsx @@ -1,32 +1,38 @@ import React, { FC } from 'react'; import { Tree } from '../Tree'; import { JsonTreeNode } from './JsonTreeNode'; +import { parseJsonTree } from './utils'; export interface JsonTreeProps { data: { [key: string]: any }; - root?: boolean; - allowCopy?: boolean; showAll?: boolean; showAllLimit?: number; showAllThreshold?: number; - showCount: boolean; - showEmpty: boolean; + showCount?: boolean; + showEmpty?: boolean; ellipsisText?: boolean; ellipsisTextLength?: number; - expandDepth: number; + expandDepth?: number; className?: string; } export const JsonTree: FC = ({ data, - root, className, + expandDepth, ...rest }) => { + const tree = parseJsonTree({ data }); + return (
- {root && } +
); @@ -40,6 +46,5 @@ JsonTree.defaultProps = { showEmpty: true, ellipsisText: true, ellipsisTextLength: 150, - expandDepth: 2, - root: true + expandDepth: 2 }; diff --git a/src/layout/Tree/JsonTree/JsonTreeNode.tsx b/src/layout/Tree/JsonTree/JsonTreeNode.tsx index 78f6ca33..10d5a19f 100644 --- a/src/layout/Tree/JsonTree/JsonTreeNode.tsx +++ b/src/layout/Tree/JsonTree/JsonTreeNode.tsx @@ -1,28 +1,39 @@ -import React, { FC, PropsWithChildren, useCallback } from 'react'; +import React, { FC, useCallback } from 'react'; import { TreeNode } from '../TreeNode'; +import { JsonTreeData } from './utils'; -export interface JsonTreeNodeProps extends PropsWithChildren { - data?: any; +export interface JsonTreeNodeProps { + data?: JsonTreeData; className?: string; - index?: number; depth?: number; expandDepth?: number; - type?: string; } export const JsonTreeNode: FC = ({ depth, - children, - type, + data, expandDepth }) => { + const type = data.type; + const renderExpandableNode = useCallback(() => { - return
hi
; - }, []); + const label = type === 'array' ? 'items' : 'keys'; + return ( + + {data.label} + {` (${data.data.length.toLocaleString()} ${label})`} + + ); + }, [data]); const renderPrimativeNode = useCallback(() => { - return
hi
; - }, []); + return ( + + {data.label} + {`: ${data.data}`} + + ); + }, [data]); return ( = ({ } > - {children} + {(data.type === 'array' || data.type === 'object') && ( + <> + {data.data.map(item => ( + + ))} + + )} ); }; diff --git a/src/layout/Tree/JsonTree/JsonTreeTheme.ts b/src/layout/Tree/JsonTree/JsonTreeTheme.ts new file mode 100644 index 00000000..ed72d658 --- /dev/null +++ b/src/layout/Tree/JsonTree/JsonTreeTheme.ts @@ -0,0 +1,15 @@ +export interface JsonTreeTheme { + node: { + label: string; + value: string; + count: string; + }; +} + +const baseTheme: JsonTreeTheme = { + node: { + label: 'font-mono opacity-70', + value: '', + count: '' + } +}; diff --git a/src/layout/Tree/JsonTree/index.ts b/src/layout/Tree/JsonTree/index.ts index e69de29b..5540078d 100644 --- a/src/layout/Tree/JsonTree/index.ts +++ b/src/layout/Tree/JsonTree/index.ts @@ -0,0 +1,3 @@ +export * from './JsonTree'; +export * from './JsonTreeNode'; +export * from './JsonTreeTheme'; diff --git a/src/layout/Tree/JsonTree/utils.ts b/src/layout/Tree/JsonTree/utils.ts index e69de29b..81716d04 100644 --- a/src/layout/Tree/JsonTree/utils.ts +++ b/src/layout/Tree/JsonTree/utils.ts @@ -0,0 +1,102 @@ +function getDataType(data: any) { + if (data === null || data === undefined) { + return 'nil'; + } + + if (data instanceof Date) { + return 'date'; + } + + if (Array.isArray(data)) { + return 'array'; + } + + if (data != null && data.constructor.name === 'Object') { + return 'object'; + } + + if (typeof data === 'string') { + return 'string'; + } + + if (typeof data === 'number') { + return 'number'; + } + + if (typeof data === 'boolean') { + return 'boolean'; + } + + return 'unknown'; +} + +export interface ParseJsonInputs { + data: any; + id?: string; + label?: string; + index?: number; + showEmpty?: boolean; +} + +export interface JsonTreeData { + type: string; + id: string; + data: any; + label: string; + index?: number; +} + +export function parseJsonTree({ + id = 'root', + data, + index, + label, + showEmpty = true +}: ParseJsonInputs): JsonTreeData { + const type = getDataType(data); + + if (type === 'object') { + const keys = Object.keys(data); + const result = keys.reduce((parsedItems, key, idx) => { + const value = data[key]; + const childParsed = parseJsonTree({ + data: value, + id: `${id}.${key}`, + index: idx, + label: key + }); + if (showEmpty || (!showEmpty && childParsed !== null)) { + parsedItems.push(childParsed); + } + return parsedItems; + }, []); + + return { + type, + id, + data: result, + label: index !== undefined ? `${index}` : 'root', + index + }; + } else if (type === 'array') { + const result = data.map((item, idx) => + parseJsonTree({ data: item, id: `${id}[${idx}]`, index: idx }) + ); + + return { + type, + id, + data: result, + label, + index + }; + } else { + return { + type, + id, + data, + label, + index + }; + } +} diff --git a/src/layout/Tree/index.tsx b/src/layout/Tree/index.tsx index c37697f1..7ba552c0 100644 --- a/src/layout/Tree/index.tsx +++ b/src/layout/Tree/index.tsx @@ -1,3 +1,4 @@ export * from './Tree'; export * from './TreeNode'; export * from './TreeTheme'; +export * from './JsonTree';