Skip to content

Instantly share code, notes, and snippets.

@SergProduction
Created December 9, 2016 17:13
Show Gist options
  • Save SergProduction/8ddacf29fdbe936639dc93e378f28ee0 to your computer and use it in GitHub Desktop.
Save SergProduction/8ddacf29fdbe936639dc93e378f28ee0 to your computer and use it in GitHub Desktop.
import React, {Component} from 'react';
import { connect } from 'react-redux';
function mapDispatchToProps(dispatch){
return {
action: (x) => {
dispatch(x)
},
}
}
function mapStateToProps(store) {
return {
tree: store.tree
};
}
class Structure extends Component {
state = {
update: false,
drag: false,
popup: {display:'none', position: 'fixed', left:0, top:0, zIndex: 10}
}
componentDidMount(){/*
let interval = 1500;
setInterval(()=>{
this.setState({ update: !this.state.update })
}, interval);*/
window.document.addEventListener('click', this.contextMenuHide.bind(this), false);
this.refs.main.setAttribute('onclick', 'tree_toggle(arguments[0])');
}
update(){
this.setState({ update: !this.state.update })
}
contextMenuShow(id, e) {
e.preventDefault();
this.refs.create.setAttribute('data-create', id);
this.refs.edit.setAttribute('data-edit', id);
this.refs.del.setAttribute('data-del', id);
let pos = {display:'block', position: 'fixed', left: e.pageX+'px', top: e.pageY-window.scrollY+'px'};
this.setState({popup: pos})
}
contextMenuHide(e) {
let pos = {display:'none', position: 'fixed', left: e.pageX+'px', top: e.pageY+'px'};
this.setState({popup: pos})
}
getPropId(){
let id = this.refs.edit.getAttribute('data-edit');
this.editFree(id)
}
editFree(id){
this.props.action({
type: 'editId',
data: id
})
this.props.action({
type: 'newBranch',
data: null
})
}
addBranch0(){
this.props.action({
type: 'editId',
data: '0'
})
this.props.action({
type: 'newBranch',
data: '0'
})
}
addBranch(){
let id = this.refs.create.getAttribute('data-create');
this.props.action({
type: 'editId',
data: id
})
this.props.action({
type: 'newBranch',
data: id
})
}
delBranch(){
let id = this.refs.del.getAttribute('data-del');
this.props.action({
type: 'delBranch',
data: { id: id }
})
}
DragStart(el, e){
let img = e.target.getElementsByClassName('Content')[0];
e.dataTransfer.effectAllowed = 'move';
e.dataTransfer.setDragImage(img,10,5);
e.dataTransfer.setData('application/text', JSON.stringify(el) );
this.setState({ drag: true });
e.stopPropagation();
}
DragEnter(e){
if (e.target.className != 'Content') return false;
e.target.style.color = '#f00';
}
DragLeave(e){
if (e.target.className != 'Content') return false;
e.target.style.color = '#000'
}
DragEnd(e){
}
DragOver(e){
e.preventDefault();
}
onDrop(parent, e){
if (!e) return;
let elMv = JSON.parse(e.dataTransfer.getData('application/text') );
if (parent.id == elMv.id) return;
e.target.style.color = '#000';
if (parent == 'del') {
this.props.action({
type: 'delBranch',
data: elMv
})
}
else {
this.props.action({
type: 'editParent',
data: {
parent: parent,
children: elMv
}
})
}
this.setState({ drag: false });
e.preventDefault();
e.stopPropagation();
}
DragSpace(){
return(
<div>
<div className="drag"
onDragOver={this.DragOver.bind(this)}
onDrop={this.onDrop.bind(this, { id: 0} )} >
<strong>Переместить в корень</strong>
</div>
<div className="drag"
onDragOver={this.DragOver.bind(this)}
onDrop={this.onDrop.bind(this, 'del')} >
<strong>Удалить</strong>
</div>
</div>
)
}
renderTree(id){
const {tree} = this.props;
return tree.map((el, i, arr) => {
if (id == el.parent) {
let nextPar = arr[i+1] ? arr[i+1].parent : null;
function Parent(){
let last = true;
tree.map(el_2 => {
if (el.id == el_2.parent) {
last = false
}
})
if (last) {
if (el.parent == nextPar) {
return 'Node ExpandLeaf'
}
else {
return 'Node ExpandLeaf IsLast'
}
}
if (el.parent == nextPar) {
return 'Node ExpandClosed'
}
else {
return 'Node ExpandClosed IsLast'
}
}
return(
<ul className="Container" key={el.id} >
<li className={Parent()} draggable="true"
onDragStart={this.DragStart.bind(this, el)}
onDragEnter={this.DragEnter.bind(this)}
onDragLeave={this.DragLeave.bind(this)}
onDragEnd={this.DragEnd.bind(this)}
onDragOver={this.DragOver.bind(this)}
onDrop={this.onDrop.bind(this, el)} >
<div className="Expand"></div>
<div className="Content" onContextMenu={this.contextMenuShow.bind(this, el.id)} onClick={this.editFree.bind(this, el.id)}>{el.key}</div>
{ this.renderTree(el.id) }
</li>
</ul>
)
}
})
}
renderRoot(){
let tree = this.props.tree.sort((a, b) => {
if( a.parent == b.parent ){
return a.id - b.id
}
else{
return a.parent - b.parent
}
});
return tree.map((el, i, tree) => {
let nextPar = tree[i+1] ? tree[i+1].parent : null;
let check = 'ExpandLeaf';
tree.forEach(el_2 => {
if(el.id == el_2.parent)
check = 'ExpandClosed';
})
if (!el.parent)
return(
<li className={el.parent == nextPar ? 'Node IsRoot '+check : 'Node IsRoot '+check+' IsLast'} key={i}
draggable="true"
onDragStart={this.DragStart.bind(this, el)}
onDragEnter={this.DragEnter.bind(this)}
onDragLeave={this.DragLeave.bind(this)}
onDragEnd={this.DragEnd.bind(this)}
onDragOver={this.DragOver.bind(this)}
onDrop={this.onDrop.bind(this, el)} >
<div className="Expand"></div>
<div className="Content" onContextMenu={this.contextMenuShow.bind(this, el.id)} onClick={this.editFree.bind(this, el.id)}>{el.key}</div>
{this.renderTree( el.id)}
</li>
)
})
}
render(){
return(
<div ref="main">
<div style={{cursor: 'pointer'}} onClick={ function(){this.update(); this.addBranch0() }.bind(this) }>Скрипт диалогов</div>
<ul className="Container">
{this.renderRoot()}
</ul>
{this.state.drag ? this.DragSpace() : null}
<ul className="list-ul" style={this.state.popup}>
<li ref="edit" data-edit="" onClick={this.getPropId.bind(this)}>Редактировать</li>
<li ref="create" data-create="" onClick={this.addBranch.bind(this)}>Создать дочерний элемент</li>
<li ref="del" data-del="" onClick={this.delBranch.bind(this)}>Удалить</li>
</ul>
</div>
)
}
}
export default connect(mapStateToProps,mapDispatchToProps)(Structure)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment