2018-08-30 12:13:37 +00:00
|
|
|
import React from 'react';
|
|
|
|
import PropTypes from 'prop-types';
|
|
|
|
import {Treebeard, decorators} from 'react-treebeard';
|
2018-10-08 05:43:51 +00:00
|
|
|
import {Form} from 'tabler-react';
|
2018-08-30 12:13:37 +00:00
|
|
|
|
|
|
|
const Header = ({style, node}) => {
|
|
|
|
const iconType = node.children ? 'folder' : 'file';
|
|
|
|
const iconClass = `fe fe-${iconType}`;
|
|
|
|
const iconStyle = {marginRight: '5px'};
|
|
|
|
|
|
|
|
return (
|
2018-10-09 06:01:48 +00:00
|
|
|
<div style={style.base}>
|
|
|
|
<div style={style.title}>
|
|
|
|
<i className={iconClass} style={iconStyle} />
|
|
|
|
{node.name}
|
2018-08-30 12:13:37 +00:00
|
|
|
</div>
|
2018-10-09 06:01:48 +00:00
|
|
|
</div>
|
2018-08-30 12:13:37 +00:00
|
|
|
);
|
|
|
|
};
|
|
|
|
|
|
|
|
Header.propTypes = {
|
|
|
|
style: PropTypes.object,
|
|
|
|
node: PropTypes.object
|
|
|
|
};
|
|
|
|
|
|
|
|
decorators.Header = Header;
|
|
|
|
|
|
|
|
class FileExplorer extends React.Component {
|
2018-10-09 06:01:48 +00:00
|
|
|
constructor(props) {
|
2018-08-30 12:13:37 +00:00
|
|
|
super(props);
|
2018-10-08 05:43:51 +00:00
|
|
|
this.state = {
|
2018-10-09 06:01:48 +00:00
|
|
|
showHidden: false
|
2018-10-08 05:43:51 +00:00
|
|
|
};
|
2018-08-30 12:13:37 +00:00
|
|
|
}
|
2018-08-30 12:13:37 +00:00
|
|
|
|
2018-10-09 06:01:48 +00:00
|
|
|
onToggle(node, toggled) {
|
2018-08-30 12:13:37 +00:00
|
|
|
node.active = true;
|
2018-10-09 06:01:48 +00:00
|
|
|
if (node.children) {
|
2018-08-30 12:13:37 +00:00
|
|
|
node.toggled = toggled;
|
2018-08-30 12:13:37 +00:00
|
|
|
} else {
|
|
|
|
this.props.fetchFile(node);
|
2018-08-30 12:13:37 +00:00
|
|
|
}
|
2018-10-09 06:01:48 +00:00
|
|
|
this.setState({cursor: node});
|
|
|
|
}
|
|
|
|
|
|
|
|
onHiddenToggle(e) {
|
|
|
|
this.setState({showHidden: e.target.checked});
|
|
|
|
}
|
|
|
|
|
|
|
|
nodeEquals(a, b) {
|
|
|
|
return a && b && a.path && b.path && a.name && b.name &&
|
|
|
|
a.path === b.path &&
|
|
|
|
a.name === b.name;
|
2018-08-30 12:13:37 +00:00
|
|
|
}
|
2018-08-30 12:13:37 +00:00
|
|
|
|
2018-10-09 06:01:48 +00:00
|
|
|
isNodeInPath(a, b) {
|
|
|
|
return a && b && a.path && b.path &&
|
|
|
|
a.path !== b.path &&
|
|
|
|
b.path.indexOf(a.path) > -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
filterHidden(nodes) {
|
|
|
|
let filtered = [];
|
|
|
|
if (!Array.isArray(nodes)) return filtered;
|
|
|
|
|
|
|
|
// we need a foreach to build an array instead of a
|
|
|
|
// filter to prevent mutating the original object (in props)
|
|
|
|
nodes.forEach(node => {
|
|
|
|
const {showHidden, cursor} = this.state;
|
|
|
|
if (!showHidden && node.isHidden) return;
|
|
|
|
let updatedNode = {...node};
|
|
|
|
|
|
|
|
// if it's a folder, filter the children
|
|
|
|
if (node.children) {
|
|
|
|
let children = this.filterHidden(node.children);
|
|
|
|
if (children.length) {
|
|
|
|
updatedNode.children = children;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// if this is the selected node, set it as active
|
|
|
|
if (this.nodeEquals(node, cursor)) {
|
|
|
|
updatedNode.active = cursor.active;
|
|
|
|
// if this node has children, set it as toggled
|
|
|
|
if (node.children) updatedNode.toggled = cursor.toggled;
|
|
|
|
}
|
|
|
|
// if this is a directory, and it lies in the path
|
|
|
|
// of the selected node, ensure it's toggled
|
|
|
|
if (node.children && this.isNodeInPath(node, cursor)) {
|
|
|
|
updatedNode.toggled = true;
|
|
|
|
}
|
|
|
|
filtered.push(updatedNode);
|
2018-10-08 05:43:51 +00:00
|
|
|
});
|
2018-10-09 06:01:48 +00:00
|
|
|
|
|
|
|
return filtered;
|
2018-10-08 05:43:51 +00:00
|
|
|
}
|
|
|
|
|
2018-10-09 06:01:48 +00:00
|
|
|
render() {
|
2018-08-30 12:13:37 +00:00
|
|
|
return (
|
2018-10-08 05:43:51 +00:00
|
|
|
<React.Fragment>
|
2018-10-09 06:01:48 +00:00
|
|
|
<Form.Switch type="checkbox" name="toggle" value={true} label="Show hidden files" onChange={this.onHiddenToggle.bind(this)} />
|
2018-10-08 05:43:51 +00:00
|
|
|
<Treebeard
|
2018-10-09 06:01:48 +00:00
|
|
|
data={this.filterHidden(this.props.files)}
|
2018-10-08 05:43:51 +00:00
|
|
|
decorators={decorators}
|
|
|
|
onToggle={this.onToggle.bind(this)}
|
|
|
|
/>
|
|
|
|
</React.Fragment>
|
2018-08-30 12:13:37 +00:00
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
FileExplorer.propTypes = {
|
2018-08-30 12:13:37 +00:00
|
|
|
files: PropTypes.array,
|
|
|
|
fetchFile: PropTypes.func
|
2018-08-30 12:13:37 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
export default FileExplorer;
|