135 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.8 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
import React from 'react';
 | 
						|
 | 
						|
import Tree from 'rc-tree';
 | 
						|
import { DataNode, EventDataNode } from 'rc-tree/lib/interface';
 | 
						|
import { useNavigate } from 'react-router';
 | 
						|
import Loading from '../../common/lib/Loading';
 | 
						|
import { BrainAtlasType, MultiLang } from '../../config';
 | 
						|
import Functions from '../../functions';
 | 
						|
import IndexUtil, { INDEX_ID_PUBLIC, Index } from '../lib/IndexUtil';
 | 
						|
 | 
						|
import styles from './IndexTree.module.css';
 | 
						|
 | 
						|
interface Props {
 | 
						|
  lang: MultiLang;
 | 
						|
  type: BrainAtlasType;
 | 
						|
}
 | 
						|
 | 
						|
const IndexTree: React.FC<Props> = (props) => {
 | 
						|
  const { lang, type } = props;
 | 
						|
  const navigate = useNavigate();
 | 
						|
 | 
						|
  const [tree, setTree] = React.useState<DataNode[]>([]);
 | 
						|
  const [keys, setKeys] = React.useState<string[]>([]);
 | 
						|
  const [expandedKeys, setExpandedKeys] = React.useState<string[]>([]);
 | 
						|
  const [selectedKeys, setSelectedKeys] = React.useState<number[]>([]);
 | 
						|
 | 
						|
  React.useEffect(() => {
 | 
						|
    const tree: DataNode[] = [];
 | 
						|
    const keys: string[] = [];
 | 
						|
    const eKeys: string[] = [];
 | 
						|
    const makeTreeNode = (index: Index, depth: number, func: (node: DataNode) => void): void => {
 | 
						|
      const title =
 | 
						|
        Functions.mlang(index.title, lang) +
 | 
						|
        (index.numOfItems > 0 ? ' (' + index.numOfItems + ')' : '');
 | 
						|
      IndexUtil.getChildren(type, index.id, (children) => {
 | 
						|
        if (children.length === 0) {
 | 
						|
          func({ key: String(index.id), title: title });
 | 
						|
        } else {
 | 
						|
          if (depth < 1) {
 | 
						|
            eKeys.push(String(index.id));
 | 
						|
          }
 | 
						|
          keys.push(String(index.id));
 | 
						|
          const childTreeNodes: DataNode[] = [];
 | 
						|
          let called = 0;
 | 
						|
          children.forEach((value: Index) => {
 | 
						|
            makeTreeNode(value, depth + 1, (cNode) => {
 | 
						|
              called++;
 | 
						|
              childTreeNodes.push(cNode);
 | 
						|
              if (called === children.length) {
 | 
						|
                func({ key: String(index.id), title: title, children: childTreeNodes });
 | 
						|
              }
 | 
						|
            });
 | 
						|
          });
 | 
						|
        }
 | 
						|
      });
 | 
						|
    };
 | 
						|
    IndexUtil.get(type, INDEX_ID_PUBLIC, (index) => {
 | 
						|
      if (index != null) {
 | 
						|
        makeTreeNode(index, 0, (node) => {
 | 
						|
          tree.push(node);
 | 
						|
          setTree(tree);
 | 
						|
          setKeys(keys);
 | 
						|
          setExpandedKeys(eKeys);
 | 
						|
          setSelectedKeys([]);
 | 
						|
        });
 | 
						|
      }
 | 
						|
    });
 | 
						|
  }, [lang, type]);
 | 
						|
 | 
						|
  const handleClickOpenAll = () => {
 | 
						|
    setExpandedKeys(keys);
 | 
						|
  };
 | 
						|
 | 
						|
  const handleClickCloseAll = () => {
 | 
						|
    setExpandedKeys([]);
 | 
						|
  };
 | 
						|
 | 
						|
  const handleExpand: (
 | 
						|
    expandedKeys: React.Key[],
 | 
						|
    info: {
 | 
						|
      node: EventDataNode<DataNode>;
 | 
						|
      expanded: boolean;
 | 
						|
      nativeEvent: MouseEvent;
 | 
						|
    },
 | 
						|
  ) => void = (expandedKeys) => {
 | 
						|
    const keys: string[] = expandedKeys.map((key) => {
 | 
						|
      return typeof key === 'string' ? key : String(key);
 | 
						|
    });
 | 
						|
    setExpandedKeys(keys);
 | 
						|
  };
 | 
						|
 | 
						|
  const handleSelect: (
 | 
						|
    selectedKeys: React.Key[],
 | 
						|
    info: {
 | 
						|
      event: 'select';
 | 
						|
      selected: boolean;
 | 
						|
      node: EventDataNode<DataNode>;
 | 
						|
      selectedNodes: DataNode[];
 | 
						|
      nativeEvent: MouseEvent;
 | 
						|
    },
 | 
						|
  ) => void = (selectedKeys) => {
 | 
						|
    const selectedKey = selectedKeys.shift() ?? 0;
 | 
						|
    const key = typeof selectedKey === 'string' ? parseInt(selectedKey, 10) : selectedKey;
 | 
						|
    const url = IndexUtil.getUrl(type, key);
 | 
						|
    navigate(url);
 | 
						|
    setSelectedKeys([]);
 | 
						|
  };
 | 
						|
 | 
						|
  if (tree.length === 0) {
 | 
						|
    return <Loading />;
 | 
						|
  }
 | 
						|
 | 
						|
  return (
 | 
						|
    <div className={styles.container}>
 | 
						|
      <button className={styles.formButton} onClick={handleClickOpenAll}>
 | 
						|
        open all
 | 
						|
      </button>
 | 
						|
      <button className={styles.formButton} onClick={handleClickCloseAll}>
 | 
						|
        close all
 | 
						|
      </button>
 | 
						|
      <Tree
 | 
						|
        className={styles.indexTree}
 | 
						|
        expandedKeys={expandedKeys}
 | 
						|
        selectedKeys={selectedKeys}
 | 
						|
        onExpand={handleExpand}
 | 
						|
        onSelect={handleSelect}
 | 
						|
        showIcon={false}
 | 
						|
        treeData={tree}
 | 
						|
      />
 | 
						|
    </div>
 | 
						|
  );
 | 
						|
};
 | 
						|
 | 
						|
export default IndexTree;
 |