Sidebar editing toggle and only scroll atlas content
This commit is contained in:
@ -22,7 +22,6 @@ class Layout extends React.Component {
|
||||
actions: React.PropTypes.node,
|
||||
title: React.PropTypes.node,
|
||||
titleText: React.PropTypes.node,
|
||||
fixed: React.PropTypes.bool,
|
||||
loading: React.PropTypes.bool,
|
||||
user: React.PropTypes.object.isRequired,
|
||||
search: React.PropTypes.bool,
|
||||
@ -59,7 +58,7 @@ class Layout extends React.Component {
|
||||
<LoadingIndicator />
|
||||
) : null }
|
||||
|
||||
<div className={ cx(styles.header, { fixed: this.props.fixed }) }>
|
||||
<div className={ cx(styles.header) }>
|
||||
<div className={ styles.headerLeft }>
|
||||
<Link to="/" className={ styles.team }>{ user.team.name }</Link>
|
||||
<span className={ styles.title }>
|
||||
@ -93,7 +92,9 @@ class Layout extends React.Component {
|
||||
</Flex>
|
||||
</div>
|
||||
|
||||
<div className={ cx(styles.content, { fixed: this.props.fixed }) }>
|
||||
<div
|
||||
className={ cx(styles.content) }
|
||||
>
|
||||
{ this.props.children }
|
||||
</div>
|
||||
</div>
|
||||
|
@ -6,6 +6,7 @@
|
||||
flex-direction: column;
|
||||
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -20,15 +21,6 @@
|
||||
|
||||
font-size: 14px;
|
||||
line-height: 1;
|
||||
|
||||
&.fixed {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 900;
|
||||
background: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.headerLeft {
|
||||
@ -73,8 +65,6 @@
|
||||
display: flex;
|
||||
flex: 1;
|
||||
justify-content: center;
|
||||
|
||||
&.fixed {
|
||||
padding-top: $headerHeight;
|
||||
}
|
||||
height: 100%;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
@ -1,14 +1,14 @@
|
||||
var React = require('react');
|
||||
import React from 'react';
|
||||
import history from 'utils/History';
|
||||
|
||||
import styles from './Tree.scss';
|
||||
import classNames from 'classnames/bind';
|
||||
const cx = classNames.bind(styles);
|
||||
|
||||
var Node = React.createClass({
|
||||
displayName: 'UITreeNode',
|
||||
class Node extends React.Component {
|
||||
displayName: 'UITreeNode'
|
||||
|
||||
renderCollapse() {
|
||||
renderCollapse = () => {
|
||||
var index = this.props.index;
|
||||
|
||||
if(index.children && index.children.length) {
|
||||
@ -26,9 +26,9 @@ var Node = React.createClass({
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
|
||||
renderChildren() {
|
||||
renderChildren = () => {
|
||||
var index = this.props.index;
|
||||
var tree = this.props.tree;
|
||||
var dragging = this.props.dragging;
|
||||
@ -51,6 +51,7 @@ var Node = React.createClass({
|
||||
index={childIndex}
|
||||
key={childIndex.id}
|
||||
dragging={dragging}
|
||||
allowUpdates={ this.props.allowUpdates }
|
||||
paddingLeft={this.props.paddingLeft}
|
||||
onCollapse={this.props.onCollapse}
|
||||
onDragStart={this.props.onDragStart}
|
||||
@ -62,14 +63,25 @@ var Node = React.createClass({
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
}
|
||||
|
||||
isModifying = () => {
|
||||
return this.props.allowUpdates && !this.props.rootNode;
|
||||
}
|
||||
|
||||
onClick = () => {
|
||||
const index = this.props.index;
|
||||
const node = index.node;
|
||||
|
||||
if (!this.isModifying()) history.push(node.url);
|
||||
}
|
||||
|
||||
render() {
|
||||
var tree = this.props.tree;
|
||||
var index = this.props.index;
|
||||
var dragging = this.props.dragging;
|
||||
var node = index.node;
|
||||
var style = {};
|
||||
const tree = this.props.tree;
|
||||
const index = this.props.index;
|
||||
const dragging = this.props.dragging;
|
||||
const node = index.node;
|
||||
const style = {};
|
||||
|
||||
return (
|
||||
<div className={cx(styles.node, {
|
||||
@ -79,12 +91,15 @@ var Node = React.createClass({
|
||||
<div
|
||||
className={ styles.inner }
|
||||
ref="inner"
|
||||
onMouseDown={this.props.rootNode ? (e) => e.stopPropagation() : this.handleMouseDown}
|
||||
onMouseDown={this.props.rootNode || !this.props.allowUpdates ? (e) => e.stopPropagation() : this.handleMouseDown}
|
||||
>
|
||||
{!this.props.rootNode && this.renderCollapse()}
|
||||
{ !this.props.rootNode && this.renderCollapse() }
|
||||
<span
|
||||
className={ cx(styles.nodeLabel, { rootLabel: this.props.rootNode }) }
|
||||
onClick={() => { history.push(node.url) }}
|
||||
className={ cx(styles.nodeLabel, {
|
||||
rootLabel: this.props.rootNode,
|
||||
isModifying: this.isModifying(),
|
||||
}) }
|
||||
onClick={ this.onClick }
|
||||
>
|
||||
{ node.title }
|
||||
</span>
|
||||
@ -92,15 +107,15 @@ var Node = React.createClass({
|
||||
{this.renderChildren()}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
handleCollapse(e) {
|
||||
handleCollapse = (e) => {
|
||||
e.stopPropagation();
|
||||
var nodeId = this.props.index.id;
|
||||
if(this.props.onCollapse) this.props.onCollapse(nodeId);
|
||||
},
|
||||
}
|
||||
|
||||
handleMouseDown(e) {
|
||||
handleMouseDown = (e) => {
|
||||
var nodeId = this.props.index.id;
|
||||
var dom = this.refs.inner;
|
||||
|
||||
@ -108,6 +123,6 @@ var Node = React.createClass({
|
||||
this.props.onDragStart(nodeId, dom, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = Node;
|
@ -7,9 +7,14 @@
|
||||
}
|
||||
|
||||
.tree {
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
@include no-select;
|
||||
padding: 20px 20px 20px 5px;
|
||||
overflow: scroll;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 40px;
|
||||
right: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.draggable {
|
||||
@ -71,6 +76,10 @@
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
|
||||
&.isModifying {
|
||||
cursor: move;
|
||||
}
|
||||
|
||||
&.isActive {
|
||||
background-color: #31363F;
|
||||
}
|
||||
|
@ -10,8 +10,8 @@ module.exports = React.createClass({
|
||||
propTypes: {
|
||||
tree: React.PropTypes.object.isRequired,
|
||||
paddingLeft: React.PropTypes.number,
|
||||
renderNode: React.PropTypes.func.isRequired,
|
||||
onCollapse: React.PropTypes.func,
|
||||
allowUpdates: React.PropTypes.bool,
|
||||
},
|
||||
|
||||
getDefaultProps() {
|
||||
@ -32,7 +32,6 @@ module.exports = React.createClass({
|
||||
init(props) {
|
||||
var tree = new Tree(props.tree);
|
||||
tree.isNodeCollapsed = props.isNodeCollapsed;
|
||||
tree.renderNode = props.renderNode;
|
||||
tree.changeNodeCollapsed = props.changeNodeCollapsed;
|
||||
tree.updateNodesPosition();
|
||||
|
||||
@ -61,11 +60,12 @@ module.exports = React.createClass({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className={ styles.draggable } style={draggingStyles}>
|
||||
<div className={ styles.draggable } style={ draggingStyles }>
|
||||
<Node
|
||||
tree={tree}
|
||||
index={draggingIndex}
|
||||
paddingLeft={this.props.paddingLeft}
|
||||
tree={ tree }
|
||||
index={ draggingIndex }
|
||||
paddingLeft={ this.props.paddingLeft }
|
||||
allowUpdates={ this.props.allowUpdates }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
@ -81,16 +81,17 @@ module.exports = React.createClass({
|
||||
|
||||
return (
|
||||
<div className={ styles.tree }>
|
||||
{draggingDom}
|
||||
{ draggingDom }
|
||||
<Node
|
||||
rootNode={ true }
|
||||
tree={tree}
|
||||
index={tree.getIndex(1)}
|
||||
key={1}
|
||||
paddingLeft={this.props.paddingLeft}
|
||||
onDragStart={this.dragStart}
|
||||
onCollapse={this.toggleCollapse}
|
||||
dragging={dragging && dragging.id}
|
||||
rootNode
|
||||
tree={ tree }
|
||||
index={ tree.getIndex(1) }
|
||||
key={ 1 }
|
||||
paddingLeft={ this.props.paddingLeft }
|
||||
allowUpdates={ this.props.allowUpdates }
|
||||
onDragStart={ this.dragStart }
|
||||
onCollapse={ this.toggleCollapse }
|
||||
dragging={ dragging && dragging.id }
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
|
@ -43,7 +43,7 @@ function requireAuth(nextState, replace) {
|
||||
}
|
||||
|
||||
render((
|
||||
<div style={{ display: 'flex', flex: 1, minHeight: '100%' }}>
|
||||
<div style={{ display: 'flex', flex: 1, height: '100%' }}>
|
||||
<Provider { ...stores }>
|
||||
<Router history={ History }>
|
||||
<Route path="/" component={ Application }>
|
||||
|
@ -1,15 +1,18 @@
|
||||
import React from "react";
|
||||
import React from 'react';
|
||||
import { observer } from 'mobx-react';
|
||||
import Helmet from "react-helmet";
|
||||
import Helmet from 'react-helmet';
|
||||
|
||||
const Application = observer((props) => {
|
||||
return (
|
||||
<div style={{ width: '100%', display: 'flex', flex: 1, }}>
|
||||
<div style={{ width: '100%', height: '100%', display: 'flex', flex: 1 }}>
|
||||
<Helmet
|
||||
title="Atlas"
|
||||
meta={[
|
||||
{"name": "viewport", "content": "width=device-width, initial-scale=1.0"},
|
||||
]}
|
||||
meta={ [
|
||||
{
|
||||
name: 'viewport',
|
||||
content: 'width=device-width, initial-scale=1.0',
|
||||
},
|
||||
] }
|
||||
/>
|
||||
{ props.children }
|
||||
</div>
|
||||
@ -18,6 +21,6 @@ const Application = observer((props) => {
|
||||
|
||||
Application.propTypes = {
|
||||
children: React.PropTypes.node.isRequired,
|
||||
}
|
||||
};
|
||||
|
||||
export default Application;
|
||||
|
@ -175,7 +175,7 @@ class DocumentScene extends React.Component {
|
||||
onNodeCollapse={ this.store.onNodeCollapse }
|
||||
/>
|
||||
) }
|
||||
<Flex flex justify="center" className={ styles.content }>
|
||||
<Flex auto justify="center" className={ styles.content }>
|
||||
<CenteredContent>
|
||||
{ this.store.updatingContent ? (
|
||||
<AtlasPreviewLoading />
|
||||
|
@ -5,4 +5,5 @@
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
overflow: scroll;
|
||||
}
|
||||
|
@ -8,10 +8,14 @@ import styles from './Sidebar.scss';
|
||||
import classNames from 'classnames/bind';
|
||||
const cx = classNames.bind(styles);
|
||||
|
||||
import treeStyles from 'components/Tree/Tree.scss';
|
||||
import SidebarStore from './SidebarStore';
|
||||
|
||||
// import treeStyles from 'components/Tree/Tree.scss';
|
||||
|
||||
@observer
|
||||
class Sidebar extends React.Component {
|
||||
static store;
|
||||
|
||||
static propTypes = {
|
||||
open: PropTypes.bool,
|
||||
onToggle: PropTypes.func.isRequired,
|
||||
@ -20,27 +24,39 @@ class Sidebar extends React.Component {
|
||||
onNodeCollapse: PropTypes.func.isRequired,
|
||||
}
|
||||
|
||||
renderNode = (node) => {
|
||||
return (
|
||||
<span className={ treeStyles.nodeLabel } onClick={ this.onClickNode.bind(null, node) }>
|
||||
{ node.module.name }
|
||||
</span>
|
||||
);
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
this.store = new SidebarStore();
|
||||
}
|
||||
|
||||
toggleEdit = (e) => {
|
||||
e.preventDefault();
|
||||
this.store.toggleEdit();
|
||||
}
|
||||
|
||||
render() {
|
||||
return (
|
||||
<Flex>
|
||||
{ this.props.open && (
|
||||
<div className={ cx(styles.sidebar) }>
|
||||
<Flex column className={ cx(styles.sidebar) }>
|
||||
<Flex auto className={ cx(styles.content) }>
|
||||
<Tree
|
||||
paddingLeft={ 10 }
|
||||
tree={ this.props.navigationTree }
|
||||
allowUpdates={ this.store.isEditing }
|
||||
onChange={ this.props.onNavigationUpdate }
|
||||
onCollapse={ this.props.onNodeCollapse }
|
||||
renderNode={ this.renderNode }
|
||||
/>
|
||||
</div>
|
||||
</Flex>
|
||||
<Flex auto className={ styles.actions }>
|
||||
<a
|
||||
href
|
||||
onClick={ this.toggleEdit }
|
||||
className={ cx(styles.action, { active: this.store.isEditing }) }
|
||||
>Edit</a>
|
||||
</Flex>
|
||||
</Flex>
|
||||
) }
|
||||
<div
|
||||
onClick={ this.props.onToggle }
|
||||
|
@ -1,7 +1,8 @@
|
||||
.sidebar {
|
||||
width: 250px;
|
||||
padding: 20px 20px 20px 5px;
|
||||
@import '~styles/constants.scss';
|
||||
|
||||
.sidebar {
|
||||
position: relative;
|
||||
width: 250px;
|
||||
border-right: 1px solid #eee;
|
||||
}
|
||||
|
||||
@ -26,3 +27,30 @@
|
||||
height: 28px;
|
||||
opacity: 0.15;
|
||||
}
|
||||
|
||||
.content {
|
||||
padding: 20px 20px 20px 5px;
|
||||
}
|
||||
|
||||
.tree {
|
||||
|
||||
}
|
||||
|
||||
.actions {
|
||||
position: absolute;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
background-color: #fff;
|
||||
padding: 10px 20px;
|
||||
height: 40px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.action {
|
||||
color: $darkGray;
|
||||
|
||||
&.active {
|
||||
color: $textColor;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,13 @@
|
||||
import { observable, action } from 'mobx';
|
||||
|
||||
class SidebarStore {
|
||||
@observable isEditing = false;
|
||||
|
||||
/* Actions */
|
||||
|
||||
@action toggleEdit = () => {
|
||||
this.isEditing = !this.isEditing;
|
||||
}
|
||||
}
|
||||
|
||||
export default SidebarStore;
|
@ -3,6 +3,9 @@ $lightGray: #eee;
|
||||
$textColor: #171B35;
|
||||
$actionColor: #2da9e1;
|
||||
|
||||
$darkGray: #ccc;
|
||||
$lightGray: #eee;
|
||||
|
||||
$headerHeight: 42px;
|
||||
|
||||
:export {
|
||||
|
@ -6,6 +6,7 @@
|
||||
<style>
|
||||
#root {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
@ -21,7 +22,7 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style='display: flex; width: 100%'>
|
||||
<body style='display: flex; width: 100%; height: 100%;'>
|
||||
<div id="root">
|
||||
<div class="container">
|
||||
<div class="header"></div>
|
||||
|
@ -5,6 +5,7 @@
|
||||
<style>
|
||||
#root {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
@ -20,7 +21,7 @@
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body style='display: flex; width: 100%'>
|
||||
<body style='display: flex; width: 100%; height: 100%;'>
|
||||
<div id="root">
|
||||
<div class="container">
|
||||
<div class="header"></div>
|
||||
|
Reference in New Issue
Block a user