jerosoler / Drawflow

Simple flow library 🖥️🖱️
https://jerosoler.github.io/Drawflow/
MIT License
4.53k stars 717 forks source link

Lock some nodes only #120

Closed dearsina closed 3 years ago

dearsina commented 3 years ago

Hello! First of all, I must say, I'm amazed by this library. It's so much better than anything else available. It's been a breeze to implement and it's so much fun to work with!

A quick question for you, is there a way (perhaps this is a feature request if not) to lock some nodes (and connections) and not others? Say you want to allow only portions of your flow to be editable, is there a way to do that currently?

I tried to look for a listener that would catch a remove before the node or connection was removed, but the only listener I can find is one that is triggered on removal, not before. Perhaps creating that listener would be an easier way to go about it?

jerosoler commented 3 years ago

Hello @dearsina

Thanks! 🎉 Yes, it is a simple library.

There is no method.

I show you an example of locking a node so that it is not draggable.

  editor.on("clickEnd", function(event) {
    if(editor.node_selected != null) {
      const nodeSelectedId = editor.ele_selected.id.slice(5);
      const dataNode = editor.getNodeFromId(nodeSelectedId);

      if(nodeSelectedId == 1) {
        editor.drag = false;
      }
    }
  });

For connections view: https://github.com/jerosoler/Drawflow/issues/113 (Implemented in 0.0.35)

And view #10 and #70

dearsina commented 3 years ago

Thank you for the prompt reply as always! I had a look at your suggestion, and while it works great for locking a node from moving, it's not so great from preventing a node from being deleted! I had a look at the suggested threads, and I found some code from thread #70 where I can prevent a node from being deleted. Thanks for that!

I looked at thread #113 , and thru some guesswork found the editor.removeConnection function. I've pieced together this code for anyone else who is looking to lock connections. I doubt it's the most efficient way of doing this. I've basically just taken the existing code and added in a check function.

    editor.removeConnection = function () {
        if(this.connection_selected != null) {
            var listclass = this.connection_selected.parentElement.classList;

            // Check to see if the connection is locked
            if(lockedConnection(listclass)){
                //If the connection is locked, don't remove it
                return true;
            }

            this.connection_selected.parentElement.remove();

            var index_out = this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.findIndex(function(item,i) {
                return item.node === listclass[1].slice(13) && item.output === listclass[4]
            });
            this.drawflow.drawflow[this.module].data[listclass[2].slice(14)].outputs[listclass[3]].connections.splice(index_out,1);

            var index_in = this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.findIndex(function(item,i) {
                return item.node === listclass[2].slice(14) && item.input === listclass[3]
            });

            this.drawflow.drawflow[this.module].data[listclass[1].slice(13)].inputs[listclass[4]].connections.splice(index_in,1);
            this.dispatch('connectionRemoved', { output_id: listclass[2].slice(14), input_id: listclass[1].slice(13), output_class: listclass[3], input_class: listclass[4] } );
            this.connection_selected = null;
        }
    }

The locked connection method relies on you having fed data variables to the node on creation:

/**
 * Check to see that based on the listclass of a connection,
 * whether both ends of the connection are locked. In which case
 * the connection itself cannot be removed.
 * 
 * Relies on the data.locked key to be set with true in each end
 * of the connection for the connection to be deemed locked also.
 * 
 * @param listclass
 * @returns {boolean}
 */
function lockedConnection(listclass){
    var nodeOutData = editor.getNodeFromId(listclass[2].slice(14)).data;
    var nodeInData = editor.getNodeFromId(listclass[1].slice(13)).data;
    return nodeInData.locked == true && nodeOutData.locked == true;
}

This is all very hack-y, but it works. @jerosoler please let me know if there is a better/cleaner way of doing this!