Skip to content

Instantly share code, notes, and snippets.

@zushenyan
Last active August 16, 2017 12:34
Show Gist options
  • Save zushenyan/f051eb64df4eb01afafc5b60f6f6bcac to your computer and use it in GitHub Desktop.
Save zushenyan/f051eb64df4eb01afafc5b60f6f6bcac to your computer and use it in GitHub Desktop.
import React, { PureComponent } from 'react';
import PropTypes from 'prop-types';
import {
SortableTreeWithoutDndContext as SortableTree,
dndWrapExternalSource,
insertNode
} from 'react-sortable-tree';
import HTML5Backend from 'react-dnd-html5-backend';
import { DropTarget, DragDropContext } from 'react-dnd';
const level = {
'main-section': 1,
'sub-section': 2,
'question': 3
};
const TYPE = 'meow!';
class _DiscardTray extends PureComponent {
static propTypes = {
connectDropTarget: PropTypes.func.isRequired
}
render(){
const { connectDropTarget, children } = this.props;
const style = {
'border': '1px solid black',
'padding': '20px',
'backgroundColor': 'lightgreen'
};
return connectDropTarget(
<div style={style}>
{children}
</div>
);
}
}
const DiscardTray = DropTarget(
TYPE,
{
drop: (props, monitor, component) => {
console.log(monitor.getItem());
}
},
(connect, monitor) => ({
connectDropTarget: connect.dropTarget()
})
)(_DiscardTray);
class _Question extends PureComponent {
static propTypes = {
node: PropTypes.object,
}
render(){
const { node } = this.props;
const style = {
'border': '1px solid black',
'padding': '5px',
'backgroundColor': 'lightyellow'
};
return (
<div style={style}>
{node.title}
</div>
);
}
}
const Question = dndWrapExternalSource(_Question, TYPE);
const tree = [
{
title: 'section 1',
level: level['main-section'],
children: [
{
title: 'sub section 1',
level: level['sub-section'],
children: [{
title: 'question 1',
level: level['question']
}]
}
]
},
{
title: 'section 2',
level: level['main-section'],
children: [
{
title: 'sub section 2',
level: level['sub-section'],
children: [{
title: 'question 2',
level: level['question']
}]
}
]
},
{
title: 'section 3',
level: level['main-section'],
children: [
{
title: 'sub section 3',
level: level['sub-section'],
children: [{
title: 'question 3',
level: level['question']
}]
}
]
},
];
class App extends PureComponent {
constructor(props){
super(props);
this.state = {
treeData: tree
};
}
handleTreeChange = (data) => {
this.setState({ treeData: data });
}
handleDropCancelled = () => {
this.setState((state) => ({ treeData: state.treeData.concat() }))
}
render(){
const { treeData } = this.state;
const style = {
'width': '500px',
'height': '500px',
'backgroundColor': 'lightblue',
'border': '1px solid black'
};
return (
<div style={style}>
<SortableTree
treeData={treeData}
onChange={this.handleTreeChange}
canDrop={(props) => {
// console.log(props);
const { node, nextParent } = props;
const { level: targetLevel = 0 } = nextParent || {};
const { level: sourceLevel } = node || {};
// console.log(`sourceLevel: ${sourceLevel}, targetLevel: ${targetLevel}`);
return (sourceLevel - 1) === targetLevel;
}}
dndType={TYPE}
/>
<DiscardTray>
<Question
node={{
title: 'question',
level: level['question']
}}
addNewItem={(newItem) => {
// console.log(newItem);
const { treeData } = insertNode({
treeData: this.state.treeData,
newNode: newItem.node,
depth: newItem.depth,
minimumTreeIndex: newItem.minimumTreeIndex,
expandParent: true,
getNodeKey: ({ treeIndex }) => treeIndex
});
this.setState({ treeData });
}}
dropCancelled={this.handleDropCancelled}
/>
</DiscardTray>
</div>
);
}
}
export default DragDropContext(HTML5Backend)(App);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment