stitch-ui
Version:
188 lines (174 loc) • 6.28 kB
JavaScript
import React from "react";
import PropTypes from "prop-types";
import { findDOMNode } from "react-dom";
import { DragSource, DropTarget } from "react-dnd";
import classNames from "classnames";
import { Button, Banner, DragHandle } from "../../core";
import { PipelineStage, PipelineStageEditState } from "../../models";
import PipelineStageEditor from "./PipelineStageEditor";
/* drag and drop boilerplate */
const stageSource = {
beginDrag(props) {
return { index: props.index };
}
};
const stageTarget = {
hover(props, monitor, component) {
const dragIndex = monitor.getItem().index;
const hoverIndex = props.index;
if (dragIndex === hoverIndex) {
return;
}
// eslint-disable-next-line react/no-find-dom-node
const hoverBoundingRect = findDOMNode(component).getBoundingClientRect();
const hoverMiddleY = (hoverBoundingRect.bottom - hoverBoundingRect.top) / 2;
const clientOffset = monitor.getClientOffset();
const hoverClientY = clientOffset.y - hoverBoundingRect.top;
if (dragIndex < hoverIndex && hoverClientY < hoverMiddleY) {
return;
}
if (dragIndex > hoverIndex && hoverClientY > hoverMiddleY) {
return;
}
component.props.moveToIndex(dragIndex);
const item = monitor.getItem();
item.index = hoverIndex;
}
};
const collectDrag = (connect, monitor) => ({
connectDragSource: connect.dragSource(),
connectDragPreview: connect.dragPreview(),
isDragging: monitor.isDragging()
});
const collectDrop = connect => ({
connectDropTarget: connect.dropTarget()
});
class PipelineStageDisplay extends React.Component {
constructor(props) {
super(props);
this.state = { editorOpen: false };
}
render() {
// drag/drop properties
const {
isDragging,
connectDragSource,
connectDragPreview,
connectDropTarget
} = this.props;
// data properties
const {
services,
stage,
editState,
removeStage,
setStage,
applyEditChange
} = this.props;
// editor actions
const { openEditor, closeEditor } = this.props;
return connectDropTarget(
connectDragPreview(
<div
className={classNames("pipeline-editor-stage-container", {
"pipeline-editor-stage-container-is-dragging": isDragging
})}
>
<Banner message={stage.error} error />
<div
className={classNames("pipeline-editor-stage", {
"pipeline-editor-stage-is-dragging": isDragging
})}
>
{connectDragSource(
<div
className={classNames("pipeline-editor-stage-draghandle", {
"pipeline-editor-stage-draghandle-is-hidden": !!editState
})}
>
<DragHandle />
</div>
)}
{editState
? <div className="pipeline-editor-stage-contents pipeline-editor-stage-contents-editing">
<PipelineStageEditor
services={services}
editState={editState}
setStage={setStage}
applyEditChange={applyEditChange}
onClose={closeEditor}
/>
</div>
: <div className="pipeline-editor-stage-contents">
<div className="pipeline-editor-stage-labelwrapper">
<div className="pipeline-editor-stage-label">Service</div>
<div className="pipeline-editor-stage-label-text">
{stage.service || "built-in"}
</div>
</div>
<div className="pipeline-editor-stage-labelwrapper">
<div className="pipeline-editor-stage-label">Action</div>
<div className="pipeline-editor-stage-label-text">
{stage.action}
</div>
</div>
<div className="pipeline-editor-stage-labelwrapper pipeline-editor-stage-labelwrapper-args">
<div className="pipeline-editor-stage-label">Args</div>
<div className="pipeline-editor-stage-label-text pipeline-editor-stage-label-text-is-mono">
{JSON.stringify(stage.args)}
</div>
{stage.let &&
<div className="pipeline-editor-stage-label"> let </div>}
{stage.let &&
<div className="pipeline-editor-stage-label-text pipeline-editor-stage-label-text-is-mono">
{JSON.stringify(stage.let)}
</div>}
</div>
</div>}
<div className="pipeline-editor-stage-controls">
<Button small onClick={openEditor}>
<i className="fa fa-pencil-square-o" /> Edit
</Button>
<Button small onClick={removeStage}>
<i className="fa fa-trash" /> Delete
</Button>
</div>
</div>
<div className="pipeline-editor-downarrow">
<i className="fa fa-long-arrow-down" />
</div>
</div>
)
);
}
}
export default DragSource("stage", stageSource, collectDrag)(
DropTarget("stage", stageTarget, collectDrop)(PipelineStageDisplay)
);
PipelineStageDisplay.propTypes = {
isDragging: PropTypes.bool,
connectDragSource: PropTypes.func,
connectDragPreview: PropTypes.func,
connectDropTarget: PropTypes.func,
services: PropTypes.objectOf(
PropTypes.shape({
type: PropTypes.string.isRequired,
config: PropTypes.object,
rules: PropTypes.object.isRequired
})
).isRequired,
stage: PropTypes.instanceOf(PipelineStage).isRequired,
editState: PropTypes.instanceOf(PipelineStageEditState),
removeStage: PropTypes.func.isRequired,
setStage: PropTypes.func.isRequired,
applyEditChange: PropTypes.func.isRequired,
openEditor: PropTypes.func.isRequired,
closeEditor: PropTypes.func.isRequired
};
PipelineStageDisplay.defaultProps = {
isDragging: false,
connectDragSource: x => x,
connectDragPreview: x => x,
connectDropTarget: x => x,
editState: null
};