127 lines
2.7 KiB
JavaScript
127 lines
2.7 KiB
JavaScript
|
|
const {
|
|
map,
|
|
values,
|
|
flatten,
|
|
merge,
|
|
indexBy,
|
|
} = require('ramda');
|
|
|
|
const React = require('react');
|
|
|
|
const r = require('r-dom');
|
|
|
|
const { connect } = require('react-redux');
|
|
|
|
const {
|
|
jsPlumb,
|
|
} = require('jsplumb');
|
|
|
|
const key = pao => `${pao.type}-${pao.index}`;
|
|
|
|
class Graph extends React.Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.container = React.createRef();
|
|
|
|
this.connectionToPao = new WeakMap();
|
|
}
|
|
|
|
componentDidMount() {
|
|
this.jsPlumb = jsPlumb.getInstance({
|
|
Container: this.container.current,
|
|
});
|
|
}
|
|
|
|
_connectSinkInput(sinkInput) {
|
|
const connection = this.jsPlumb.connect({
|
|
source: `client-${sinkInput.info.clientIndex}`,
|
|
target: `sink-${sinkInput.info.sinkIndex}`,
|
|
anchor: 'Continuous',
|
|
overlays: [ [ 'Arrow', { location: -1 } ] ],
|
|
});
|
|
this.connectionToPao.set(connection, sinkInput);
|
|
}
|
|
|
|
_connectSourceOutput(sourceOutput) {
|
|
const connection = this.jsPlumb.connect({
|
|
source: `source-${sourceOutput.info.sourceIndex}`,
|
|
target: `client-${sourceOutput.info.clientIndex}`,
|
|
anchor: 'Continuous',
|
|
overlays: [ [ 'Arrow', { location: -1 } ] ],
|
|
});
|
|
this.connectionToPao.set(connection, sourceOutput);
|
|
}
|
|
|
|
_connectByType(pao) {
|
|
if (pao.type === 'sinkInput') {
|
|
this._connectSinkInput(pao);
|
|
} else {
|
|
this._connectSourceOutput(pao);
|
|
}
|
|
}
|
|
|
|
componentDidUpdate() {
|
|
this.jsPlumb.batch(() => {
|
|
const propsPaos = merge(
|
|
indexBy(key, values(this.props.sinkInputs)),
|
|
indexBy(key, values(this.props.sourceOutputs)),
|
|
);
|
|
this.jsPlumb.getAllConnections().forEach(connection => {
|
|
const connectionPao = this.connectionToPao.get(connection);
|
|
const k = key(connectionPao);
|
|
const propsPao = propsPaos[k];
|
|
if (!propsPao) {
|
|
this.jsPlumb.deleteConnection(connection);
|
|
} else if (propsPao === connectionPao) {
|
|
// Noop
|
|
} else if (propsPao.info) {
|
|
this.jsPlumb.deleteConnection(connection);
|
|
this._connectByType(propsPao);
|
|
}
|
|
delete propsPaos[k];
|
|
});
|
|
values(propsPaos).forEach(propsPao => {
|
|
if (propsPao.info) {
|
|
this._connectByType(propsPao);
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
render() {
|
|
return r.div({
|
|
ref: this.container,
|
|
style: { position: 'relative' },
|
|
}, flatten(
|
|
map(paos => map(pao => r.div({
|
|
id: key(pao),
|
|
key: key(pao),
|
|
className: 'jtk-node',
|
|
style: {
|
|
border: '1px solid black',
|
|
userSelect: 'none',
|
|
cursor: 'default',
|
|
},
|
|
ref: el => {
|
|
if (el) {
|
|
this.jsPlumb.draggable(el, {});
|
|
/// this.jsPlumb.addEndpoint();
|
|
}
|
|
},
|
|
}, [
|
|
key(pao),
|
|
]), values(paos)), [
|
|
this.props.sinks,
|
|
this.props.sources,
|
|
this.props.clients,
|
|
]),
|
|
));
|
|
}
|
|
}
|
|
|
|
module.exports = connect(
|
|
state => state.pulse,
|
|
)(Graph);
|