feat: tree search
This commit is contained in:
1 parent
fcb27ff156
commit
bcbc20ff98
2 files changed
+138
-43
No files matched your search
+130
-43
@@ -1,14 +1,14 @@
|
|||||||
import React, { Component } from "react";
|
import React, { ChangeEvent, Component } from "react";
|
||||||
import { Menu, Input, Tree ,Dropdown} from "antd";
|
import { Input, Tree, Dropdown } from "antd";
|
||||||
import * as fs from "fs";
|
import * as fs from "fs";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
import { ipcRenderer } from "electron";
|
import { ipcRenderer } from "electron";
|
||||||
import MainEventType from "../common/MainEventType";
|
import MainEventType from "../common/MainEventType";
|
||||||
import { DataNode } from "antd/lib/tree";
|
import { DataNode } from "antd/lib/tree";
|
||||||
import { IconType } from "rc-tree/lib/interface";
|
import { EventDataNode, IconType } from "rc-tree/lib/interface";
|
||||||
|
|
||||||
const { Search } = Input;
|
const { Search } = Input;
|
||||||
const { DirectoryTree } = Tree;
|
const { DirectoryTree, TreeNode } = Tree;
|
||||||
|
|
||||||
export interface PropertiesProps {
|
export interface PropertiesProps {
|
||||||
workdir: string;
|
workdir: string;
|
||||||
@@ -67,9 +67,9 @@ class FileDataNode implements DataNode {
|
|||||||
parent: this,
|
parent: this,
|
||||||
});
|
});
|
||||||
|
|
||||||
node.children = isFolder&&recursive ? (node.loadChilds(recursive) as FileDataNode[]) : [],
|
(node.children =
|
||||||
|
isFolder && recursive ? (node.loadChilds(recursive) as FileDataNode[]) : []),
|
||||||
list.push(node);
|
list.push(node);
|
||||||
});
|
});
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
@@ -112,6 +112,15 @@ class FileDataNode implements DataNode {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getList(): FileDataNode[] {
|
||||||
|
let ret = new Array<FileDataNode>(this);
|
||||||
|
for (const child of this.children) {
|
||||||
|
const childList = child.getList();
|
||||||
|
ret.push(...childList);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
// name:string;
|
// name:string;
|
||||||
// path: string;
|
// path: string;
|
||||||
// isFolder : boolean;
|
// isFolder : boolean;
|
||||||
@@ -121,6 +130,15 @@ class FileDataNode implements DataNode {
|
|||||||
|
|
||||||
interface PropertiesState {
|
interface PropertiesState {
|
||||||
root: FileDataNode;
|
root: FileDataNode;
|
||||||
|
searchKey: string;
|
||||||
|
defaultExpandedKeys:string[];
|
||||||
|
expandedKeys: string[];
|
||||||
|
autoExpandParent: boolean;
|
||||||
|
rightClickNode: {
|
||||||
|
pageX: number;
|
||||||
|
pageY: number;
|
||||||
|
key: string;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
const NodeActions: { [x: string]: string } = {
|
const NodeActions: { [x: string]: string } = {
|
||||||
@@ -134,6 +152,11 @@ const NodeActions: { [x: string]: string } = {
|
|||||||
export default class Properties extends Component<PropertiesProps> {
|
export default class Properties extends Component<PropertiesProps> {
|
||||||
state: PropertiesState = {
|
state: PropertiesState = {
|
||||||
root: null,
|
root: null,
|
||||||
|
searchKey: "",
|
||||||
|
rightClickNode: null,
|
||||||
|
expandedKeys: [],
|
||||||
|
defaultExpandedKeys:[],
|
||||||
|
autoExpandParent: true,
|
||||||
};
|
};
|
||||||
|
|
||||||
curWorkdir: string = "";
|
curWorkdir: string = "";
|
||||||
@@ -158,7 +181,11 @@ export default class Properties extends Component<PropertiesProps> {
|
|||||||
}
|
}
|
||||||
const root = this.getRootNode(workdir);
|
const root = this.getRootNode(workdir);
|
||||||
root.expandSelf();
|
root.expandSelf();
|
||||||
this.setState({ root: root });
|
this.setState({
|
||||||
|
root: root ,
|
||||||
|
expandedKeys : [root.key],
|
||||||
|
defaultExpandedKeys: [root.key]
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
getRootNode(workdir: string) {
|
getRootNode(workdir: string) {
|
||||||
@@ -191,14 +218,61 @@ export default class Properties extends Component<PropertiesProps> {
|
|||||||
// );
|
// );
|
||||||
// }
|
// }
|
||||||
|
|
||||||
// renderNode(node:FileDataNode){
|
handleOnSearch(value: string, event: ChangeEvent) {
|
||||||
// return (<Dropdown
|
const expandedKeys = this.state.root
|
||||||
// overlay={this.renderContextMeun(node)}
|
.getList()
|
||||||
// trigger={["contextMenu"]}
|
.map((item) => {
|
||||||
// >
|
if(!item.isLeaf)
|
||||||
// <div>{node.title}</div>
|
return null;
|
||||||
// </Dropdown>)
|
const title = item.title as string;
|
||||||
// }
|
if (title.includes(value) && item.parent) {
|
||||||
|
return item.parent.key;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
})
|
||||||
|
.filter((item, i, self) => item && self.indexOf(item) === i);
|
||||||
|
if (value && value.length>0) {
|
||||||
|
this.setState({
|
||||||
|
searchKey: value,
|
||||||
|
expandedKeys: expandedKeys,
|
||||||
|
autoExpandParent: true,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
searchKey: "",
|
||||||
|
expandedKeys: this.state.defaultExpandedKeys,
|
||||||
|
autoExpandParent: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
this.forceUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
filterNode(node: EventDataNode): boolean {
|
||||||
|
const searchKey = this.state.searchKey;
|
||||||
|
const nodeKey = node.title as string;
|
||||||
|
|
||||||
|
return nodeKey.includes(searchKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
titleRender(node:DataNode):React.ReactNode{
|
||||||
|
const titleStr = node.title as string;
|
||||||
|
const searchKey = this.state.searchKey;
|
||||||
|
const index = titleStr.indexOf(searchKey);
|
||||||
|
const beforeStr = titleStr.substr(0, index);
|
||||||
|
const afterStr = titleStr.substr(index + searchKey.length);
|
||||||
|
|
||||||
|
//return (<span>{titleStr}</span>)
|
||||||
|
return index > -1 ? (
|
||||||
|
<span>
|
||||||
|
{beforeStr}
|
||||||
|
<span className="site-tree-search-value">{searchKey}</span>
|
||||||
|
{afterStr}
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
<span>{titleStr}</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
console.log("render Properties");
|
console.log("render Properties");
|
||||||
@@ -206,34 +280,47 @@ export default class Properties extends Component<PropertiesProps> {
|
|||||||
const root = this.state.root;
|
const root = this.state.root;
|
||||||
const nodes = root ? [root] : [];
|
const nodes = root ? [root] : [];
|
||||||
return nodes.length ? (
|
return nodes.length ? (
|
||||||
<DirectoryTree
|
<div>
|
||||||
selectable
|
<Search
|
||||||
showLine
|
allowClear
|
||||||
expandAction="click"
|
placeholder="Search"
|
||||||
treeData={nodes}
|
onSearch={this.handleOnSearch.bind(this)}
|
||||||
defaultExpandedKeys={[root.key]}
|
/>
|
||||||
onCheck={(node) => console.log("onCheck")}
|
<DirectoryTree
|
||||||
onSelect={(keys, info) => {
|
selectable
|
||||||
console.log("onSelect", keys, info);
|
// showLine
|
||||||
if (info.node.isLeaf) {
|
checkStrictly
|
||||||
onOpenTree(keys[0] as string);
|
expandAction="click"
|
||||||
}
|
expandedKeys={this.state.expandedKeys}
|
||||||
}}
|
autoExpandParent={this.state.autoExpandParent}
|
||||||
onExpand={(keys, info) => {
|
titleRender={this.titleRender.bind(this)}
|
||||||
console.log("onExpand", info);
|
treeData={nodes}
|
||||||
if (info.expanded && !info.node.expanded) {
|
filterTreeNode={this.filterNode.bind(this)}
|
||||||
//let newRoot = _.cloneDeep(root);
|
defaultExpandedKeys={[root.key]}
|
||||||
const node = root.findChild(info.node.key as string);
|
onSelect={(keys, info) => {
|
||||||
if (node) {
|
console.log("onSelect", keys, info);
|
||||||
node.expandSelf();
|
if (info.node.isLeaf) {
|
||||||
this.setState({ root: root });
|
onOpenTree(keys[0] as string);
|
||||||
this.forceUpdate();
|
|
||||||
}
|
}
|
||||||
}
|
}}
|
||||||
}}
|
onExpand={(keys, info) => {
|
||||||
onLoad={(keys, info) => console.log("onLoad", keys, info)}
|
console.log("onExpand", info);
|
||||||
onRightClick={(event) => console.log("onRightClick", event)}
|
this.setState({
|
||||||
></DirectoryTree>
|
expandedKeys:keys,
|
||||||
|
autoExpandParent:false
|
||||||
|
})
|
||||||
|
if (info.expanded && !info.node.expanded) {
|
||||||
|
//let newRoot = _.cloneDeep(root);
|
||||||
|
const node = root.findChild(info.node.key as string);
|
||||||
|
if (node) {
|
||||||
|
node.expandSelf();
|
||||||
|
this.setState({ root: root });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.forceUpdate();
|
||||||
|
}}
|
||||||
|
></DirectoryTree>
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
`Work Dir (${workdir}) Empty`
|
`Work Dir (${workdir}) Empty`
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -41,3 +41,11 @@ body {
|
|||||||
height : 50px;
|
height : 50px;
|
||||||
background-color: #818181;
|
background-color: #818181;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.site-tree-search-value {
|
||||||
|
color: #f50;
|
||||||
|
}
|
||||||
|
|
||||||
|
[data-theme="dark"] .site-tree-search-value {
|
||||||
|
color: #d84a1b;
|
||||||
|
}
|
||||||
Reference in new issue
Block a user