UNPKG

plot-plan-designer

Version:

Design Editor Tools with React.js + ant.design + fabric.js

183 lines (182 loc) 8.62 kB
import React, { Component } from 'react'; import PropTypes from 'prop-types'; import { Collapse, Input } from 'antd'; import { v4 } from 'uuid'; import i18n from 'i18next'; import classnames from 'classnames'; import Icon from '../icon/Icon'; import { NODE_COLORS } from './constant/constants'; import { Flex } from '../flex'; import { getNode } from './configuration/NodeConfiguration'; import Scrollbar from '../common/Scrollbar'; import CommonButton from '../common/CommonButton'; class WorkflowItems extends Component { constructor() { super(...arguments); this.state = { activeKey: [], collapse: false, textSearch: '', descriptors: {}, filteredDescriptors: [], }; this.handlers = { onAddItem: (item, centered) => { const { canvasRef } = this.props; const id = v4(); const option = Object.assign({}, item, { id, subType: item.type, type: getNode(item.nodeClazz), configuration: item.defaultConfiguration, description: '', }); canvasRef.handler.add(option, centered); }, onChangeActiveKey: (activeKey) => { this.setState({ activeKey, }); }, onCollapse: () => { this.setState({ collapse: !this.state.collapse, }); }, onSearchNode: (e) => { const { descriptors } = this.state; const filteredDescriptors = descriptors.filter((descriptor) => descriptor.name.toLowerCase().includes(e.target.value.toLowerCase())); this.setState({ textSearch: e.target.value, filteredDescriptors, }); }, }; this.events = { onDragStart: (e, item) => { this.item = item; const { target } = e; target.classList.add('dragging'); }, onDragOver: (e) => { if (e.preventDefault) { e.preventDefault(); } e.dataTransfer.dropEffect = 'copy'; return false; }, onDragEnter: (e) => { const { target } = e; target.classList.add('over'); }, onDragLeave: (e) => { const { target } = e; target.classList.remove('over'); }, onDrop: (e) => { e = e || window.event; if (e.preventDefault) { e.preventDefault(); } if (e.stopPropagation) { e.stopPropagation(); } const { layerX, layerY } = e; const option = Object.assign({}, this.item, { left: layerX, top: layerY }); this.handlers.onAddItem(option, false); return false; }, onDragEnd: (e) => { this.item = null; e.target.classList.remove('dragging'); }, }; this.waitForCanvasRender = (canvas) => { setTimeout(() => { if (canvas) { this.attachEventListener(canvas); return; } const { canvasRef } = this.props; this.waitForCanvasRender(canvasRef); }, 5); }; this.attachEventListener = (canvasRef) => { canvasRef.canvas.wrapperEl.addEventListener('dragenter', this.events.onDragEnter, false); canvasRef.canvas.wrapperEl.addEventListener('dragover', this.events.onDragOver, false); canvasRef.canvas.wrapperEl.addEventListener('dragleave', this.events.onDragLeave, false); canvasRef.canvas.wrapperEl.addEventListener('drop', this.events.onDrop, false); }; this.detachEventListener = (canvasRef) => { canvasRef.canvas.wrapperEl.removeEventListener('dragenter', this.events.onDragEnter); canvasRef.canvas.wrapperEl.removeEventListener('dragover', this.events.onDragOver); canvasRef.canvas.wrapperEl.removeEventListener('dragleave', this.events.onDragLeave); canvasRef.canvas.wrapperEl.removeEventListener('drop', this.events.onDrop); }; this.renderItems = (items) => (React.createElement(Flex, { flexWrap: "wrap", flexDirection: "column", style: { width: '100%' } }, items.map((item) => (React.createElement("div", { key: item.name, draggable: true, onClick: () => this.handlers.onAddItem(item), onDragStart: (e) => this.events.onDragStart(e, item), onDragEnd: (e) => this.events.onDragEnd(e, item), className: "rde-editor-items-item", style: { justifyContent: this.state.collapse ? 'center' : null } }, React.createElement("span", { className: "rde-editor-items-item-icon" }, React.createElement(Icon, { name: item.icon && item.icon.length ? item.icon : 'image', color: NODE_COLORS[item.type].fill })), this.state.collapse ? null : React.createElement("span", { className: "rde-editor-items-item-text" }, item.name)))))); } componentDidMount() { const { canvasRef } = this.props; this.waitForCanvasRender(canvasRef); } UNSAFE_componentWillReceiveProps(nextProps) { if (JSON.stringify(this.props.descriptors) !== JSON.stringify(nextProps.descriptors)) { const descriptors = Object.keys(nextProps.descriptors).reduce((prev, key) => { return prev.concat(nextProps.descriptors[key]); }, []); this.setState({ descriptors, }); } } shouldComponentUpdate(nextProps, nextState) { if (JSON.stringify(this.props.descriptors) !== JSON.stringify(nextProps.descriptors)) { return true; } else if (JSON.stringify(this.state.filteredDescriptors) !== JSON.stringify(nextState.filteredDescriptors)) { return true; } else if (this.state.textSearch !== nextState.textSearch) { return true; } else if (JSON.stringify(this.state.activeKey) !== JSON.stringify(nextState.activeKey)) { return true; } else if (this.state.collapse !== nextState.collapse) { return true; } return false; } componentWillUnmount() { const { canvasRef } = this.props; this.detachEventListener(canvasRef); } render() { const { descriptors } = this.props; const { activeKey, filteredDescriptors, collapse, textSearch } = this.state; const className = classnames('rde-editor-items', { minimize: collapse, }); return (React.createElement("div", { className: className }, React.createElement(Flex, { flex: "1", flexDirection: "column", style: { height: '100%' } }, React.createElement(Flex, { justifyContent: "center", alignItems: "center", style: { height: 40 } }, React.createElement(CommonButton, { icon: collapse ? 'angle-double-right' : 'angle-double-left', shape: "circle", className: "rde-action-btn", style: { margin: '0 4px' }, onClick: this.handlers.onCollapse }), collapse ? null : (React.createElement(Input, { style: { margin: '8px' }, placeholder: i18n.t('action.search-list'), onChange: this.handlers.onSearchNode, value: textSearch, allowClear: true }))), React.createElement(Scrollbar, null, React.createElement(Flex, { flex: "1", style: { overflowY: 'hidden' } }, textSearch.length ? (this.renderItems(filteredDescriptors)) : (React.createElement(Collapse, { style: { width: '100%' }, activeKey: activeKey.length ? activeKey : Object.keys(descriptors), onChange: this.handlers.onChangeActiveKey, items: Object.keys(descriptors).map((key) => ({ key, label: collapse ? '' : key, showArrow: !collapse, style: { background: NODE_COLORS[key].fill }, children: this.renderItems(descriptors[key]), })) }))))))); } } WorkflowItems.propTypes = { canvasRef: PropTypes.any, descriptors: PropTypes.object, }; export default WorkflowItems;