refactor: tree

This commit is contained in:
cha0s 2021-04-02 16:42:49 -05:00
parent 2771776d32
commit 64488e5d46
7 changed files with 117 additions and 74 deletions

View File

@ -9,6 +9,7 @@
'@avocado/math/persea': {}
'@avocado/persea': {}
'@avocado/physics': {}
'@avocado/react': {}
'@avocado/resource': {
'persea.controllers': [
'@avocado/graphics/persea',

View File

@ -42,6 +42,7 @@
"react-hex-editor": "^0.3.0",
"react-hot-loader": "^4.13.0",
"react-modal": "^3.12.1",
"react-resize-panel": "^0.3.5",
"react-router-dom": "^5.2.0",
"react-ui-tree": "^4.0.0"
},

View File

@ -1,56 +1,24 @@
import './index.scss';
import {join} from 'path';
import {PropTypes, React} from '@latus/react';
import {Link, Route} from 'react-router-dom';
import Tree from 'react-ui-tree';
import ResizePanel from 'react-resize-panel';
import {Route} from 'react-router-dom';
import {ProjectContext} from '@avocado/persea';
import ResourceRoute from '../resource/route';
const renderNode = ({isFile, label, path}) => (
isFile
? <Link to={path}>{label}</Link>
: <span>{label}</span>
);
const treeFromResourcePath = (tree, uuid, [isFile, resourcePath]) => {
const parts = resourcePath.split('/');
parts.shift();
let walk = tree;
parts.forEach((part) => {
let index = walk.children.findIndex(({label}) => label === part);
if (-1 === index) {
index = walk.children.length;
walk.children.push({
children: [],
isFile,
label: part,
path: join('/project', uuid, resourcePath),
});
}
walk = walk.children[index];
});
};
const treeFromResourcePaths = (label, uuid, resourcePaths) => {
const tree = {label, children: []};
resourcePaths
.forEach((resourcePath) => treeFromResourcePath(tree, uuid, resourcePath));
return tree;
};
import Sidebar from './sidebar';
const Project = ({structure: {label, resourcePaths}, uuid}) => (
<div className="project">
<ProjectContext.Provider value={uuid}>
<div className="sidebar">
<Tree
paddingLeft={20}
tree={treeFromResourcePaths(label, uuid, resourcePaths)}
renderNode={renderNode}
<ResizePanel direction="e">
<Sidebar
label={label}
uuid={uuid}
resourcePaths={resourcePaths}
/>
</div>
</ResizePanel>
<div className="resource-container">
<Route path="/project/:uuid:uri(/*)" component={ResourceRoute} />
</div>

View File

@ -1,38 +1,9 @@
$sidebar-basis: 10rem;
.project {
display: flex;
width: 100vw;
height: 100vh;
.sidebar {
height: 100%;
min-width: 25rem;
overflow: auto;
padding: 1em;
}
.m-tree {
user-select: none;
> .m-node {
> .children {
margin-left: -20px;
}
> .inner {
display: none;
}
}
}
.m-node {
font-family: monospace;
.inner {
padding: 0.25em;
}
.caret-right::before {
content: "\25B8";
padding-right: 0.5em;
}
.caret-down::before {
content: "\25BE";
padding-right: 0.5em;
}
}
.resource-container {
background-color: rgba(0, 0, 0, 0.2);
flex-grow: 1;
@ -40,3 +11,10 @@
}
}
[class*="ResizePanel-module_ResizeHandleHorizontal"] {
display: none;
}
[class*="ResizePanel-module_ResizeContent"] {
min-width: $sidebar-basis;
}

View File

@ -0,0 +1,63 @@
import './index.scss';
import {join} from 'path';
import {Tree} from '@avocado/react';
import {PropTypes, React} from '@latus/react';
import {useHistory} from 'react-router-dom';
const treeFromResourcePath = (tree, uuid, [isFile, resourcePath]) => {
const parts = resourcePath.split('/');
parts.shift();
let walk = tree;
parts.forEach((part) => {
let index = walk.nodes.findIndex(({label}) => label === part);
if (-1 === index) {
index = walk.nodes.length;
walk.nodes.push({
...(isFile ? {} : {nodes: []}),
label: part,
value: join(uuid, resourcePath),
});
}
walk = walk.nodes[index];
});
};
const nodesFromResourcePaths = (label, uuid, resourcePaths) => {
const tree = {label, nodes: []};
resourcePaths
.forEach((resourcePath) => treeFromResourcePath(tree, uuid, resourcePath));
return tree.nodes;
};
const Sidebar = ({label, resourcePaths, uuid}) => {
const history = useHistory();
return (
<div className="sidebar">
<Tree
activate={(item, nodes) => {
if (!nodes) {
history.push(join('/project', item));
}
}}
label={label}
nodes={nodesFromResourcePaths(label, uuid, resourcePaths)}
value={uuid}
/>
</div>
);
};
Sidebar.defaultProps = {};
Sidebar.propTypes = {
label: PropTypes.string.isRequired,
// eslint-disable-next-line react/no-unused-prop-types
resourcePaths: PropTypes.arrayOf(PropTypes.any).isRequired,
uuid: PropTypes.string.isRequired,
};
Sidebar.displayName = 'Sidebar';
export default Sidebar;

View File

@ -0,0 +1,9 @@
$sidebar-basis: 10rem;
.sidebar {
height: 100%;
min-width: $sidebar-basis;
overflow-x: hidden;
overflow-y: auto;
width: 100%;
}

View File

@ -2566,6 +2566,11 @@ caseless@~0.12.0:
resolved "http://npm.cha0sdev/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=
cash-dom@^4.1.5:
version "4.1.5"
resolved "http://npm.cha0sdev/cash-dom/-/cash-dom-4.1.5.tgz#0ef0cf205bc7603aa4e2dfada5808442a7a0e6ca"
integrity sha512-E6MO0A6ms5iZPtexznQXWRkFEvqdPqCmdx/SiJr2PnhOQNhZNfALkLG5t83Hk3J5JELzED7PJuzhMoS2tT64XA==
chai@4.2.0:
version "4.2.0"
resolved "http://npm.cha0sdev/chai/-/chai-4.2.0.tgz#760aa72cf20e3795e84b12877ce0e83737aa29e5"
@ -7050,7 +7055,7 @@ promise-inflight@^1.0.1:
resolved "http://npm.cha0sdev/promise-inflight/-/promise-inflight-1.0.1.tgz#98472870bf228132fcbdd868129bad12c3c029e3"
integrity sha1-mEcocL8igTL8vdhoEputEsPAKeM=
prop-types@^15.5.10, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
prop-types@^15.5.10, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2"
resolved "http://npm.cha0sdev/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@ -7300,6 +7305,14 @@ react-dom@^17.0.1:
object-assign "^4.1.1"
scheduler "^0.20.2"
react-draggable@^4.0.3:
version "4.4.3"
resolved "http://npm.cha0sdev/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3"
integrity sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w==
dependencies:
classnames "^2.2.5"
prop-types "^15.6.0"
react-hex-editor@^0.3.0:
version "0.3.0"
resolved "http://npm.cha0sdev/react-hex-editor/-/react-hex-editor-0.3.0.tgz#4133715faa9eb46ea3f373ec0c81a2e379fe6575"
@ -7356,6 +7369,16 @@ react-redux@^7.2.2:
prop-types "^15.7.2"
react-is "^16.13.1"
react-resize-panel@^0.3.5:
version "0.3.5"
resolved "http://npm.cha0sdev/react-resize-panel/-/react-resize-panel-0.3.5.tgz#43aa3450bf5b5a2566b40c4201445ced96c2a905"
integrity sha512-iyHOFTrSt+WV4Ilzi81x6KH3FU7VsGP736rmxepwGrgAEATmCvXzZdluTm3NpsptP7aC3hLODmXwnxusyA393A==
dependencies:
cash-dom "^4.1.5"
classnames "^2.2.6"
lodash.debounce "^4.0.8"
react-draggable "^4.0.3"
react-router-dom@^5.2.0:
version "5.2.0"
resolved "http://npm.cha0sdev/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"