github.com/thanos-io/thanos@v0.32.5/pkg/ui/react-app/src/components/ListTree.tsx (about) 1 import React, { useState } from 'react'; 2 import { InputProps, Collapse, ListGroupItem, ListGroup } from 'reactstrap'; 3 4 export interface QueryTree { 5 name: string; 6 children?: QueryTree[]; 7 } 8 9 interface NodeProps extends InputProps { 10 node: QueryTree | null; 11 } 12 13 const ListTree: React.FC<NodeProps> = ({ id, node }) => { 14 type idMapping = { 15 [key: string]: boolean; 16 }; 17 18 const [mapping, setMapping] = useState<idMapping>({}); 19 const toggle = (e: React.MouseEvent<HTMLDivElement>) => { 20 const el = e.target as HTMLDivElement; 21 const id = el.getAttribute('id'); 22 if (id) { 23 setMapping({ ...mapping, [id]: !mapping[id] }); 24 } 25 }; 26 27 // Constructing List Items recursively. 28 const mapper = (nodes: QueryTree[], parentId?: any, lvl?: any) => { 29 return nodes.map((node: QueryTree, index: number) => { 30 const id = `${index}-${parentId ? parentId : 'top'}`.replace(/[^a-zA-Z0-9-_]/g, ''); 31 const item = ( 32 <React.Fragment> 33 <ListGroupItem 34 className={`bg-transparent p-0 border-0 ${parentId ? `rounded-0 ${lvl ? 'border-bottom-0' : ''}` : ''}`} 35 > 36 { 37 <div className={`d-flex align-items-center`} style={{ paddingLeft: `${25 * lvl}px` }}> 38 {node.children && ( 39 <div className="pl-0 btn text-primary" style={{ cursor: 'inherit' }} color="link"> 40 {mapping[id] ? '\u002B' : '\u002D'} 41 </div> 42 )} 43 <div id={id} style={{ cursor: `${node.children ? 'pointer' : 'inherit'}` }} onClick={toggle}> 44 {node.name} 45 </div> 46 </div> 47 } 48 </ListGroupItem> 49 {node.children && <Collapse isOpen={mapping[id]}>{mapper(node.children, id, (lvl || 0) + 1)}</Collapse>} 50 </React.Fragment> 51 ); 52 53 return item; 54 }); 55 }; 56 57 if (node) { 58 return <ListGroup>{mapper([node], id)}</ListGroup>; 59 } else { 60 return null; 61 } 62 }; 63 64 export default ListTree;