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;