From 36fd1184f65f8782ff471c459757f97f018baaac Mon Sep 17 00:00:00 2001 From: cha0s Date: Sun, 28 Jun 2020 10:43:26 -0500 Subject: [PATCH] flow: resource tree --- src/client/index.scss | 3 +- src/client/sidebar.jsx | 75 +++++++++++++++++++++++++++++-------- src/client/sidebar.raw.scss | 64 ++++++++++++++++++++++++++++++- 3 files changed, 124 insertions(+), 18 deletions(-) diff --git a/src/client/index.scss b/src/client/index.scss index a9e2d54..c2ae35d 100644 --- a/src/client/index.scss +++ b/src/client/index.scss @@ -49,6 +49,7 @@ html { background-color: #212121; color: #FFFFFF; --active-color: rgb(0, 180, 204); + --title-font-family: Ubuntu, "Droid Sans", sans-serif; } body { scrollbar-width: thin; @@ -152,7 +153,7 @@ select { .react-tabs__tab-list { background-color: #272727; - font-family: Ubuntu, "Droid Sans", sans-serif; + font-family: var(--title-font-family); font-size: 0.9em; overflow-x: hidden; scrollbar-width: thin; diff --git a/src/client/sidebar.jsx b/src/client/sidebar.jsx index 99a5cbd..017920f 100644 --- a/src/client/sidebar.jsx +++ b/src/client/sidebar.jsx @@ -1,8 +1,9 @@ import {compose} from '@avocado/core'; +import classnames from 'classnames'; import contempo from 'contempo'; import React, {useState} from 'react'; import {useDispatch} from 'react-redux'; -import SortableTree, {changeNodeAtPath, getTreeFromFlatData} from 'react-sortable-tree'; +import SortableTree, {changeNodeAtPath, getTreeFromFlatData, toggleExpandedForAll} from 'react-sortable-tree'; import ResourcesPacket from '~/common/packets/resources.packet'; @@ -18,18 +19,56 @@ const decorate = compose( const rootUri = '/resources/cha0s/initial'; -const sortTree = (tree) => { - tree.sort((l, r) => l.title.localeCompare(r.title)); - if (tree.children) { - // eslint-disable-next-line no-param-reassign - tree.children = sortTree(tree.children); - } - return tree; -}; +const sortTree = (tree) => tree + .sort((l, r) => l.title.localeCompare(r.title)) + .map((node) => { + if (node.children) { + // eslint-disable-next-line no-param-reassign + node.children = sortTree(node.children); + } + return node; + }); + +const mapComponents = (tree) => tree.map((node) => ({ + ...node, + children: node.children ? mapComponents(node.children) : [], + rawTitle: node.title, + title: ( + + {node.uri && ( + + + + )} + {node.title} + + ), +})); + +const unmapComponents = (tree) => tree.map((node) => ({ + ...node, + children: node.children ? unmapComponents(node.children) : [], + title: node.rawTitle || node.title, +})); const Sidebar = () => { const dispatch = useDispatch(); - const [treeData, setTreeData] = useState([]); + const [treeData, setTreeDataInternal] = useState([]); + // eslint-disable-next-line no-shadow + const setTreeData = (treeData) => { + setTreeDataInternal(sortTree(unmapComponents(treeData))); + }; useSocket((socket) => socket.send(new ResourcesPacket(), (uris) => { const visited = {}; const nodes = uris @@ -60,17 +99,17 @@ const Sidebar = () => { visited[node.id] = true; return true; }); - setTreeData(sortTree(getTreeFromFlatData({ + setTreeData(getTreeFromFlatData({ flatData: nodes, rootKey: '', - }))); + })); })); return (
!node.uri} generateNodeProps={({node}) => ({ - onClick: () => { + onClick: (event) => { if (node.uri) { dispatch(setActiveResourceUri(node.uri)); } @@ -81,17 +120,21 @@ const Sidebar = () => { path: node.id.split('/'), newNode: { ...node, + children: (event.ctrlKey && event.altKey) + ? toggleExpandedForAll({treeData: node.children, expanded: !isExpanded}) + : node.children, expanded: !isExpanded, }, - getNodeKey: ({node: {id}}) => id, + getNodeKey: ({node: {title}}) => title, })); } }, })} // eslint-disable-next-line no-shadow - onChange={(treeData) => setTreeData(sortTree(treeData))} + onChange={(treeData) => setTreeData(treeData)} + scaffoldBlockPxWidth={20} theme={FileExplorerTheme} - treeData={treeData} + treeData={mapComponents(treeData)} />
); diff --git a/src/client/sidebar.raw.scss b/src/client/sidebar.raw.scss index 8f8c010..e9c0e77 100644 --- a/src/client/sidebar.raw.scss +++ b/src/client/sidebar.raw.scss @@ -1,6 +1,6 @@ :scope { background-color: #242424; - padding: 1em; + padding: 0.5em; width: 100%; height: 100%; } @@ -9,6 +9,68 @@ box-shadow: none; } +.rstcustom__lineBlock { + border-left: 1px solid #666666; + height: 1.6em; + left: 2px; +} + +.rstcustom__row { + left: -1.5em; + padding: 0.25em 0; +} + .rstcustom__rowWrapper { cursor: pointer; + padding-left: 0.5em; + &:hover { + opacity: 1; + } + > div > .rstcustom__lineBlock:nth-last-of-type(2) { + border-left: none; + } +} + +.rstcustom__rowLabel { + font-size: 0.9em; + .title { + align-items: center; + color: #ffffff; + display: flex; + font-family: var(--title-font-family); + padding: 0.25em 0 0; + svg { + fill: #aaaaaa; + } + &.directory { + left: 1.5em; + position: relative; + } + } + .resource .text { + margin-left: 0.5em; + } +} + +.rstcustom__node { + &:hover { + background-color: rgba(0, 0, 0, 0.05); + } + button { + top: 0.75em; + transform: translate3d(-33%, -50%, 0) scale(0.75); + } +} + +.rstcustom__collapseButton, +.rstcustom__expandButton { + &:focus { + box-shadow: none; + } + &::after { + border-top-color: #999999; + &:hover { + border-top-color: #999999; + } + } }