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;
|