2018-02-17 21:30:16 +00:00
|
|
|
// @flow
|
2018-02-18 16:13:29 +00:00
|
|
|
import React, {Component} from "react";
|
|
|
|
import {buildTree} from "./commitUtils";
|
|
|
|
import type {CommitData, FileTree} from "./commitUtils";
|
2018-02-17 00:11:59 +00:00
|
|
|
|
2018-02-17 21:30:16 +00:00
|
|
|
export class FileExplorer extends Component<{
|
2018-02-18 16:13:29 +00:00
|
|
|
selectedPath: string,
|
|
|
|
onSelectPath: (newPath: string) => void,
|
|
|
|
data: CommitData,
|
2018-02-17 21:30:16 +00:00
|
|
|
}> {
|
2018-02-16 23:35:22 +00:00
|
|
|
render() {
|
|
|
|
// within the FileExplorer, paths start with "./", outside they don't
|
|
|
|
// which is hacky and should be cleaned up
|
|
|
|
const fileNames = Object.keys(this.props.data.fileToCommits).sort();
|
|
|
|
const tree = buildTree(fileNames);
|
|
|
|
const selectPath = (path) => {
|
|
|
|
if (path.startsWith("./")) {
|
|
|
|
path = path.slice(2);
|
|
|
|
}
|
|
|
|
this.props.onSelectPath(path);
|
2018-02-18 16:13:29 +00:00
|
|
|
};
|
|
|
|
return (
|
|
|
|
<div className="file-explorer plugin-pane">
|
|
|
|
<h3 style={{textAlign: "center"}}>File Explorer</h3>
|
|
|
|
<div style={{fontFamily: "monospace"}}>
|
|
|
|
<FileEntry
|
|
|
|
alwaysExpand={true}
|
|
|
|
name=""
|
|
|
|
path="."
|
|
|
|
tree={tree}
|
|
|
|
onSelectPath={selectPath}
|
|
|
|
selectedPath={`./${this.props.selectedPath}`}
|
|
|
|
/>
|
|
|
|
</div>
|
2018-02-18 10:00:11 +00:00
|
|
|
</div>
|
2018-02-18 16:13:29 +00:00
|
|
|
);
|
2018-02-16 23:35:22 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-18 16:13:29 +00:00
|
|
|
class FileEntry extends Component<
|
|
|
|
{
|
|
|
|
name: string,
|
|
|
|
path: string,
|
|
|
|
alwaysExpand: boolean,
|
|
|
|
tree: FileTree,
|
|
|
|
selectedPath: string,
|
|
|
|
onSelectPath: (newPath: string) => void,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
expanded: boolean,
|
|
|
|
}
|
|
|
|
> {
|
2018-02-16 23:35:22 +00:00
|
|
|
constructor() {
|
|
|
|
super();
|
2018-02-18 16:13:29 +00:00
|
|
|
this.state = {expanded: false};
|
2018-02-16 23:35:22 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
render() {
|
|
|
|
const topLevels = Object.keys(this.props.tree);
|
2018-02-18 16:13:29 +00:00
|
|
|
const subEntries = topLevels.map((x) => (
|
2018-02-16 23:35:22 +00:00
|
|
|
<FileEntry
|
|
|
|
key={x}
|
|
|
|
name={x}
|
|
|
|
path={`${this.props.path}/${x}`}
|
|
|
|
alwaysExpand={false}
|
|
|
|
tree={this.props.tree[x]}
|
|
|
|
selectedPath={this.props.selectedPath}
|
|
|
|
onSelectPath={this.props.onSelectPath}
|
|
|
|
/>
|
2018-02-18 16:13:29 +00:00
|
|
|
));
|
2018-02-16 23:35:22 +00:00
|
|
|
const isFolder = topLevels.length > 0 && !this.props.alwaysExpand;
|
|
|
|
const toggleExpand = () => this.setState({expanded: !this.state.expanded});
|
|
|
|
const isSelected = this.props.path === this.props.selectedPath;
|
|
|
|
const selectTarget = isSelected ? "." : this.props.path;
|
|
|
|
const onClick = () => this.props.onSelectPath(selectTarget);
|
2018-02-18 16:13:29 +00:00
|
|
|
return (
|
|
|
|
<div
|
|
|
|
className={isSelected ? "selected-path" : ""}
|
2018-02-16 23:35:22 +00:00
|
|
|
style={{marginLeft: this.props.path === "." ? 0 : 25}}
|
|
|
|
>
|
2018-02-18 16:13:29 +00:00
|
|
|
<p>
|
|
|
|
{isFolder && (
|
|
|
|
<button style={{marginRight: 3}} onClick={toggleExpand}>
|
|
|
|
»
|
|
|
|
</button>
|
|
|
|
)}
|
|
|
|
<a href="javascript: void 0" onClick={onClick}>
|
|
|
|
{this.props.name}
|
|
|
|
</a>
|
|
|
|
</p>
|
|
|
|
{(this.state.expanded || this.props.alwaysExpand) && subEntries}
|
|
|
|
</div>
|
|
|
|
);
|
2018-02-16 23:35:22 +00:00
|
|
|
}
|
|
|
|
}
|