diff --git a/lib/galaxy/web/controllers/workflow.py b/lib/galaxy/web/controllers/workflow.py
index 5e8ba6342ca..b885285ce71 100644
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -9,6 +9,7 @@ from galaxy.datatypes.data import Data
from galaxy.util.odict import odict
from galaxy.util.bunch import Bunch
from galaxy.util.topsort import topsort, topsort_levels, CycleError
+from galaxy.workflow.modules import *
class WorkflowController( BaseController ):
beta = True
@@ -31,7 +32,7 @@ class WorkflowController( BaseController ):
"""
user = trans.get_user()
if not workflow_name:
- return error( "Must provide a name for the new workflow" )
+ error( "Must provide a name for the new workflow" )
# Create the new stored workflow
stored_workflow = model.StoredWorkflow()
stored_workflow.name = workflow_name
@@ -70,13 +71,12 @@ class WorkflowController( BaseController ):
rendered by `editor_canvas`.
"""
if not id:
- return trans.show_error_message( "Invalid workflow id" )
+ error( "Invalid workflow id" )
id = trans.security.decode_id( id )
- return trans.fill_template( "workflow/editor.mako",
- workflow_id=id )
+ return trans.fill_template( "workflow/editor.mako", workflow_id=id )
@web.json
- def editor_tool_form( self, trans, tool_id=None, **incoming ):
+ def editor_tool_form( self, trans, type='tool', tool_id=None, **incoming ):
"""
Accepts a tool state and incoming values, and generates a new tool
form and some additional information, packed into a json dictionary.
@@ -84,59 +84,39 @@ class WorkflowController( BaseController ):
is selected.
"""
trans.workflow_building_mode = True
- tool = trans.app.toolbox.tools_by_id[tool_id]
- state = DefaultToolState()
- state.decode( incoming.pop("tool_state"), tool, trans.app )
- errors = tool.update_state( trans, tool.inputs, state.inputs, incoming )
- rval = {}
- rval['form_html'] = trans.fill_template( "workflow/editor_tool_form.mako",
- tool=tool, as_html=as_html, values=state.inputs, errors=errors )
- if errors:
- rval['tool_errors'] = errors
- else:
- rval['tool_errors'] = None
- # Updated data_inputs
- rval['data_inputs'] = get_data_inputs( tool.inputs, state.inputs )
- rval['state'] = state.encode( tool, trans.app )
- return rval
+ module = module_factory.from_dict( trans, {
+ 'type': type,
+ 'tool_id': tool_id,
+ 'tool_state': incoming.pop("tool_state")
+ } )
+ module.update_state( incoming )
+ return {
+ 'tool_state': module.get_state(),
+ 'data_inputs': module.get_data_inputs(),
+ 'data_outputs': module.get_data_outputs(),
+ 'form_html': module.get_config_form()
+ }
@web.json
- def get_tool_info( self, trans, tool_id ):
+ def get_new_module_info( self, trans, type, **kwargs ):
"""
- Generate a json dictionary containing info about the tool specified by
- `tool_id`. Info includes data inputs and outputs, html representation
+ Get the info for a new instance of a module initialized with default
+ paramters (any keyword arguments will be passed along to the module).
+ Result includes data inputs and outputs, html representation
of the initial form, and the initial tool state (with default values).
This is called asynchronously whenever a new node is added.
"""
trans.workflow_building_mode = True
- tool = trans.app.toolbox.tools_by_id[tool_id]
- rval = {}
- rval['name'] = tool.name
- rval['tool_id'] = tool.id
- data_outputs = []
- for name, ( format, metadata_source, parent ) in tool.outputs.iteritems():
- data_outputs.append( dict( name=name, extension=format ) )
- rval['data_outputs'] = data_outputs
- state = tool.new_state( trans, all_pages=True )
- rval['form_html'] = trans.fill_template( "workflow/editor_tool_form.mako",
- tool=tool, as_html=as_html, values=state.inputs, errors={} )
- rval['tool_state'] = state.encode( tool, trans.app )
- rval['data_inputs'] = get_data_inputs( tool.inputs, state.inputs )
- return rval
-
- @web.json
- def get_module_info( self, trans, type ):
- module = module_types[type]()
- rval = {}
- rval['name'] = module.name
- rval['type'] = module.type
- rval['tool_state'] = state = module.get_state()
- rval['data_inputs'] = module.get_data_inputs()
- rval['data_outputs'] = module.get_data_outputs()
- rval['form_html'] = trans.fill_template(
- "workflow/editor_generic_form.mako",
- form = module.get_config_form() )
- return rval
+ module = module_factory.new( trans, type, **kwargs )
+ return {
+ 'type': module.type,
+ 'name': module.get_name(),
+ 'tool_id': module.get_tool_id(),
+ 'tool_state': module.get_state(),
+ 'data_inputs': module.get_data_inputs(),
+ 'data_outputs': module.get_data_outputs(),
+ 'form_html': module.get_config_form()
+ }
@web.json
def load_workflow( self, trans, id ):
@@ -158,39 +138,18 @@ class WorkflowController( BaseController ):
data['steps'] = {}
# For each step, rebuild the form and encode the state
for step in workflow.steps:
- step_dict = {}
- step_dict['id'] = step.order_index
- step_dict['type'] = step_type = ( step.type or "tool" )
- if step_type == 'tool':
- step_dict['tool_id'] = tool_id = step.tool_id
- # Load tool
- tool = trans.app.toolbox.tools_by_id[tool_id]
- # Build a state from the tool_inputs dict
- state = DefaultToolState()
- state.inputs = tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
- step_dict['tool_state'] = state.encode( tool, trans.app )
- # Error messages for the tool
- step_dict['tool_errors'] = ( step.tool_errors or None )
- # Input and output specs
- step_dict['data_inputs'] = get_data_inputs( tool.inputs, state.inputs )
- data_outputs = []
- for name, ( format, metadata_source, parent ) in tool.outputs.iteritems():
- data_outputs.append( dict( name=name, extension=format ) )
- step_dict['data_outputs'] = data_outputs
- # Build the tool form html
- errors = step.tool_errors
- step_dict['form_html'] = trans.fill_template( "workflow/editor_tool_form.mako",
- tool=tool, as_html=as_html, values=state.inputs, errors=( step.tool_errors or {} ) )
- step_dict['name'] = tool.name
- else:
- module = module_types[step.type].from_workflow_step( step )
- step_dict['name'] = module.name
- step_dict['tool_state'] = state = module.get_state()
- step_dict['data_inputs'] = module.get_data_inputs()
- step_dict['data_outputs'] = module.get_data_outputs()
- step_dict['form_html'] = trans.fill_template(
- "workflow/editor_generic_form.mako",
- form = module.get_config_form() )
+ module = module_factory.from_workflow_step( trans, step )
+ step_dict = {
+ 'id': step.order_index,
+ 'type': module.type,
+ 'tool_id': module.get_tool_id(),
+ 'name': module.get_name(),
+ 'tool_state': module.get_state(),
+ 'tool_errors': module.get_errors(),
+ 'data_inputs': module.get_data_inputs(),
+ 'data_outputs': module.get_data_outputs(),
+ 'form_html': module.get_config_form()
+ }
# Connections
input_conn_dict = {}
for conn in step.input_connections:
@@ -229,25 +188,14 @@ class WorkflowController( BaseController ):
for key, step_dict in data['steps'].iteritems():
# Create the model class for the step
step = model.WorkflowStep()
- step.type = step_type = step_dict['type']
steps.append( step )
steps_by_external_id[ step_dict['id' ] ] = step
+ # FIXME: Position should be handled inside module
step.position = step_dict['position']
- if step_type == 'tool':
- step.tool_id = step_dict['tool_id']
- # Decode the tool state from the step dict
- tool = trans.app.toolbox.tools_by_id[ step_dict['tool_id'] ]
- state = DefaultToolState()
- state.decode( step_dict['tool_state'], tool, trans.app )
- # Convert back to strings for database
- tool_inputs = tool.params_to_strings( state.inputs, trans.app )
- step.tool_inputs = tool_inputs
- step.tool_errors = step_dict.get( 'tool_errors', None )
- if step.tool_errors:
- workflow.has_errors = True
- else:
- module = module_types[step_type].from_state( step_dict['tool_state'] )
- module.save_to_step( step )
+ module = module_factory.from_dict( trans, step_dict )
+ module.save_to_step( step )
+ if step.tool_errors:
+ workflow.has_errors = True
# Stick this in the step temporarily
step.temp_input_connections = step_dict['input_connections']
# Second pass to deal with connections between steps
@@ -405,15 +353,12 @@ class WorkflowController( BaseController ):
workflow = stored.latest_workflow
# It is possible for a workflow to have 0 steps
if len( workflow.steps ) == 0:
- return trans.show_error_message(
- "Workflow cannot be run because it does not have any steps" )
+ error( "Workflow cannot be run because it does not have any steps" )
#workflow = Workflow.from_simple( simplejson.loads( stored.encoded_value ), trans.app )
if workflow.has_cycles:
- return trans.show_error_message(
- "Workflow cannot be run because it contains cycles" )
+ error( "Workflow cannot be run because it contains cycles" )
if workflow.has_errors:
- return trans.show_error_message(
- "Workflow cannot be run because of validation errors in some steps" )
+ error( "Workflow cannot be run because of validation errors in some steps" )
# Build the state for each step
errors = {}
if kwargs:
@@ -438,7 +383,7 @@ class WorkflowController( BaseController ):
step_errors = tool.update_state( trans, tool.inputs, step.state.inputs, step_args,
update_only=True, old_errors=old_errors )
else:
- module = step.module = WorkflowModule.from_workflow_step( step )
+ module = step.module = module_factory.from_workflow_step( trans, step )
state = step.state = module.decode_runtime_state( trans, step_args.pop( "tool_state" ) )
step_errors = module.update_runtime_state( trans, state, step_args )
if step_errors:
@@ -495,7 +440,7 @@ class WorkflowController( BaseController ):
errors[step.id] = step.tool_errors
else:
## Non-tool specific stuff?
- step.module = WorkflowModule.from_workflow_step( step )
+ step.module = module_factory.from_workflow_step( trans, step )
step.state = step.module.get_runtime_state()
# Connections by input name
step.input_connections_by_name = dict( ( conn.input_name, conn ) for conn in step.input_connections )
@@ -505,70 +450,6 @@ class WorkflowController( BaseController ):
steps=workflow.steps,
workflow=stored,
errors=errors )
-
-## ---- Workflow modules (to be factored out) ---------------------------------
-
-from elementtree.ElementTree import Element
-
-## TODO: 'Tool' should be a module rather than a special case
-
-class WorkflowModule( object ):
- @classmethod
- def from_workflow_step( cls, step ):
- assert step.type in module_types, "Unknown module type"
- return module_types[ step.type ].from_workflow_step( step )
-
-class InputDataModule( WorkflowModule ):
- type = "data_input"
- name = "Input dataset"
- _inputs = {
- 'input' : DataToolParameter( None, Element( "param", name="input", label="Input Dataset", type="data", format="data" ) )
- }
- @classmethod
- def from_state( cls, state ):
- return cls()
- @classmethod
- def from_workflow_step( cls, step ):
- return cls()
- def get_state( self ):
- return None
- def save_to_step( self, step ):
- pass
-
- def get_data_inputs( self ):
- return []
- def get_data_outputs( self ):
- return [ dict( name='output', extension='input' ) ]
- def get_config_form( self ):
- return web.FormBuilder( title=self.name )
-
- def get_runtime_inputs( self ):
- return self._inputs
- def get_runtime_state( self ):
- state = DefaultToolState()
- state.inputs = dict( input=None )
- return state
- def encode_runtime_state( self, trans, state ):
- fake_tool = Bunch( inputs = self.get_runtime_inputs() )
- return state.encode( fake_tool, trans.app )
- def decode_runtime_state( self, trans, string ):
- fake_tool = Bunch( inputs = self.get_runtime_inputs() )
- state = DefaultToolState()
- state.decode( string, fake_tool, trans.app )
- return state
- def update_runtime_state( self, trans, state, values ):
- errors = {}
- for name, param in self._inputs.iteritems():
- value, error = check_param( trans, param, values[name], values )
- state.inputs[ name ] = value
- if error:
- errors[ name ] = error
- return errors
-
- def execute( self, trans, state ):
- return dict( output=state.inputs['input'])
-
-module_types = dict( data_input=InputDataModule )
## ---- Utility methods -------------------------------------------------------
@@ -589,12 +470,6 @@ def get_stored_workflow( trans, id ):
error( "Workflow is not owned by current user" )
# Looks good
return stored
-
-def as_html( param, value, trans, prefix ):
- if type( param ) is DataToolParameter:
- return "Data input '" + param.name + "' (" + ( " or ".join( param.extensions ) ) + ")"
- else:
- return param.get_html_field( trans, value ).get_html( prefix )
def attach_ordered_steps( workflow, steps ):
ordered_steps = order_workflow_steps( steps )
@@ -700,32 +575,4 @@ def cleanup_param_values( inputs, values ):
prefix = "%s|" % ( key )
cleanup( prefix, input.cases[current_case].inputs, group_values )
cleanup( "", inputs, values )
- return associations
-
-def get_data_inputs( inputs, input_values ):
- """
- For a set of input definitions and a tool state, find all of the dataset
- inputs
- """
- data_inputs = []
- def visitor( inputs, input_values, name_prefix, label_prefix ):
- for input in inputs.itervalues():
- if isinstance( input, Repeat ):
- for i, d in enumerate( input_values[ input.name ] ):
- index = d['__index__']
- new_name_prefix = name_prefix + "%s_%d|" % ( input.name, index )
- new_label_prefix = label_prefix + "%s %d > " % ( input.title, i + 1 )
- visitor( input.inputs, d, new_name_prefix, new_label_prefix )
- elif isinstance( input, Conditional ):
- values = input_values[ input.name ]
- current = values["__current_case__"]
- label_prefix = label_prefix
- name_prefix = name_prefix + "|" + input.name
- visitor( input.cases[current].inputs, values, name_prefix, label_prefix )
- else:
- if isinstance( input, DataToolParameter ):
- data_inputs.append( dict( name=name_prefix+input.name, label=label_prefix+input.label, extensions=input.extensions ) )
- visitor( inputs, input_values, "", "" )
- return data_inputs
-
-
+ return associations
\ No newline at end of file
diff --git a/lib/galaxy/workflow/__init__.py b/lib/galaxy/workflow/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py
new file mode 100644
index 00000000000..5e9c98e8324
--- /dev/null
+++ b/lib/galaxy/workflow/modules.py
@@ -0,0 +1,232 @@
+from elementtree.ElementTree import Element
+
+from galaxy import web
+from galaxy.tools.parameters import DataToolParameter, check_param
+from galaxy.tools import DefaultToolState
+from galaxy.tools.parameters.grouping import Repeat, Conditional
+from galaxy.util.bunch import Bunch
+
+class WorkflowModule( object ):
+
+ def __init__( self, trans ):
+ self.trans = trans
+
+ ## ---- Creating modules from various representations ---------------------
+
+ @classmethod
+ def new( Class, trans, tool_id=None ):
+ """
+ Create a new instance of the module with default state
+ """
+ return Class( trans )
+ @classmethod
+ def from_dict( Class, trans, d ):
+ """
+ Create a new instance of the module initialized from values in the
+ dictionary `d`.
+ """
+ return Class( trans )
+ @classmethod
+ def from_workflow_step( Class, trans, step ):
+ return Class( trans )
+
+ ## ---- Saving in various forms ------------------------------------------
+
+ def save_to_step( self, step ):
+ step.type = self.type
+
+ ## ---- General attributes -----------------------------------------------
+
+ def get_type( self ):
+ return self.type
+ def get_name( self ):
+ return self.name
+ def get_tool_id( self ):
+ return None
+
+ ## ---- Configuration time -----------------------------------------------
+
+ def get_state( self ):
+ return None
+ def get_errors( self ):
+ return None
+ def get_data_inputs( self ):
+ return []
+ def get_data_outputs( self ):
+ return []
+ def update_state( self ):
+ pass
+ def get_config_form( self ):
+ raise TypeError( "Abstract method" )
+
+ ## ---- Run time ---------------------------------------------------------
+
+ def get_runtime_inputs( self ):
+ raise TypeError( "Abstract method" )
+ def get_runtime_state( self ):
+ raise TypeError( "Abstract method" )
+ def encode_runtime_state( self, trans, state ):
+ raise TypeError( "Abstract method" )
+ def decode_runtime_state( self, trans, string ):
+ raise TypeError( "Abstract method" )
+ def update_runtime_state( self, trans, state, values ):
+ raise TypeError( "Abstract method" )
+
+ def execute( self, trans, state ):
+ raise TypeError( "Abstract method" )
+
+class InputDataModule( WorkflowModule ):
+ type = "data_input"
+ name = "Input dataset"
+ _runtime_inputs = {
+ 'input' : DataToolParameter( None, Element( "param", name="input", label="Input Dataset", type="data", format="data" ) )
+ }
+
+ def get_data_inputs( self ):
+ return []
+ def get_data_outputs( self ):
+ return [ dict( name='output', extension='input' ) ]
+ def get_config_form( self ):
+ return self.trans.fill_template( "workflow/editor_generic_form.mako",
+ form = web.FormBuilder( title=self.name ) )
+
+ def get_runtime_inputs( self ):
+ return self._runtime_inputs
+ def get_runtime_state( self ):
+ state = DefaultToolState()
+ state.inputs = dict( input=None )
+ return state
+ def encode_runtime_state( self, trans, state ):
+ fake_tool = Bunch( inputs = self.get_runtime_inputs() )
+ return state.encode( fake_tool, trans.app )
+ def decode_runtime_state( self, trans, string ):
+ fake_tool = Bunch( inputs = self.get_runtime_inputs() )
+ state = DefaultToolState()
+ state.decode( string, fake_tool, trans.app )
+ return state
+ def update_runtime_state( self, trans, state, values ):
+ errors = {}
+ for name, param in self._runtime_inputs.iteritems():
+ value, error = check_param( trans, param, values.get( name, None ), values )
+ state.inputs[ name ] = value
+ if error:
+ errors[ name ] = error
+ return errors
+
+ def execute( self, trans, state ):
+ return dict( output=state.inputs['input'])
+
+class ToolModule( object ):
+
+ type = "tool"
+
+ def __init__( self, trans, tool_id ):
+ self.trans = trans
+ self.tool_id = tool_id
+ self.tool = trans.app.toolbox.tools_by_id[ tool_id ]
+ self.state = None
+ self.errors = None
+
+ @classmethod
+ def new( Class, trans, tool_id=None ):
+ module = Class( trans, tool_id )
+ module.state = module.tool.new_state( trans, all_pages=True )
+ return module
+ @classmethod
+ def from_dict( Class, trans, d ):
+ tool_id = d['tool_id']
+ module = Class( trans, tool_id )
+ module.state = DefaultToolState()
+ module.state.decode( d["tool_state"], module.tool, module.trans.app )
+ module.errors = d.get( "tool_errors", None )
+ return module
+
+ @classmethod
+ def from_workflow_step( Class, trans, step ):
+ tool_id = step.tool_id
+ module = Class( trans, tool_id )
+ module.state = DefaultToolState()
+ print step.tool_inputs
+ module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app )
+ module.errors = step.tool_errors
+ return module
+
+ def save_to_step( self, step ):
+ step.type = self.type
+ step.tool_id = self.tool_id
+ step.tool_inputs = self.tool.params_to_strings( self.state.inputs, self.trans.app )
+ step.tool_errors = self.errors
+
+ def get_name( self ):
+ return self.tool.name
+ def get_tool_id( self ):
+ return self.tool_id
+ def get_state( self ):
+ return self.state.encode( self.tool, self.trans.app )
+ def get_errors( self ):
+ return self.errors
+
+ def get_data_inputs( self ):
+ data_inputs = []
+ def visitor( inputs, input_values, name_prefix, label_prefix ):
+ for input in inputs.itervalues():
+ if isinstance( input, Repeat ):
+ for i, d in enumerate( input_values[ input.name ] ):
+ index = d['__index__']
+ new_name_prefix = name_prefix + "%s_%d|" % ( input.name, index )
+ new_label_prefix = label_prefix + "%s %d > " % ( input.title, i + 1 )
+ visitor( input.inputs, d, new_name_prefix, new_label_prefix )
+ elif isinstance( input, Conditional ):
+ values = input_values[ input.name ]
+ current = values["__current_case__"]
+ label_prefix = label_prefix
+ name_prefix = name_prefix + "|" + input.name
+ visitor( input.cases[current].inputs, values, name_prefix, label_prefix )
+ else:
+ if isinstance( input, DataToolParameter ):
+ data_inputs.append( dict( name=name_prefix+input.name, label=label_prefix+input.label, extensions=input.extensions ) )
+ visitor( self.tool.inputs, self.state.inputs, "", "" )
+ return data_inputs
+ def get_data_outputs( self ):
+ data_outputs = []
+ for name, ( format, metadata_source, parent ) in self.tool.outputs.iteritems():
+ data_outputs.append( dict( name=name, extension=format ) )
+ return data_outputs
+ def get_config_form( self ):
+ def as_html( param, value, trans, prefix ):
+ if type( param ) is DataToolParameter:
+ return "Data input '" + param.name + "' (" + ( " or ".join( param.extensions ) ) + ")"
+ else:
+ return param.get_html_field( trans, value ).get_html( prefix )
+ return self.trans.fill_template( "workflow/editor_tool_form.mako",
+ tool=self.tool, as_html=as_html, values=self.state.inputs, errors=( self.errors or {} ) )
+ def update_state( self, incoming ):
+ errors = self.tool.update_state( self.trans, self.tool.inputs, self.state.inputs, incoming )
+ self.errors = errors or None
+
+
+class WorkflowModuleFactory( object ):
+ def __init__( self, module_types ):
+ self.module_types = module_types
+ def new( self, trans, type, tool_id=None ):
+ """
+ Return module for type and (optional) tool_id intialized with
+ new / default state.
+ """
+ assert type in self.module_types
+ return self.module_types[type].new( trans, tool_id )
+ def from_dict( self, trans, d ):
+ """
+ Return module initialized from the data in dictionary `d`.
+ """
+ type = d['type']
+ assert type in self.module_types
+ return self.module_types[type].from_dict( trans, d )
+ def from_workflow_step( self, trans, step ):
+ """
+ Return module initializd from the WorkflowStep object `step`.
+ """
+ type = step.type
+ return self.module_types[type].from_workflow_step( trans, step )
+
+module_factory = WorkflowModuleFactory( dict( data_input=InputDataModule, tool=ToolModule ) )
\ No newline at end of file
diff --git a/static/scripts/galaxy.ui.scrollPanel.js b/static/scripts/galaxy.ui.scrollPanel.js
index 5ff7c2a93c4..d4834cb88db 100644
--- a/static/scripts/galaxy.ui.scrollPanel.js
+++ b/static/scripts/galaxy.ui.scrollPanel.js
@@ -66,15 +66,15 @@ $.ui.plugin.add("draggable", "scrollPanel", {
ui.position.top += amount_moved;
moved = true;
}
- // Update offsets
- if ( moved ) {
- $.ui.ddmanager.prepareOffsets( instance, e );
- }
// Still contain in panel
ui.position.left = Math.max( ui.position.left, 0 );
ui.position.top = Math.max( ui.position.top, 0 );
ui.position.left = Math.min( ui.position.left, panel_w - element_w );
ui.position.top = Math.min( ui.position.top, panel_h - element_h );
+ // Update offsets
+ if ( moved ) {
+ $.ui.ddmanager.prepareOffsets( instance, e );
+ }
// Keep moving even if mouse doesn't move
if ( moved ) {
instance.old_e = e;
diff --git a/static/scripts/galaxy.workflow_editor.canvas.js b/static/scripts/galaxy.workflow_editor.canvas.js
index 424ee85761b..74cf5467c94 100644
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -295,9 +295,9 @@ $.extend( Node.prototype, {
update_field_data : function( data ) {
var el = $(this.element),
node = this;
- this.tool_state = data.state;
+ this.tool_state = data.tool_state;
this.form_html = data.form_html;
- this.tool_errors = data.tool_errors;
+ this.tool_errors = data.tool_errors;
if ( this.tool_errors ) {
el.addClass( "tool-node-error" );
} else {
@@ -493,27 +493,28 @@ function prebuild_node( type, title_text, tool_id ) {
scrollSpeed: 20,
// containment: $("#shim"),
// grow: true,
- click: function( _, ui ) {
+ click: function( e, ui ) {
var element = $(this).data("draggable").element.get(0);
(function(p) { p.removeChild( element ); p.appendChild( element ) })(element.parentNode)
workflow.activate_node( node );
},
- start: function() {
+ start: function( e, ui ) {
workflow.activate_node( node );
$(this).css( 'z-index', '1000' );
},
- drag: function() {
+ drag: function( e, ui ) {
$(this).find( ".terminal" ).each( function() {
this.terminal.redraw();
})
},
- stop: function( _, ui ) {
+ stop: function( e, ui ) {
var element = $(this).data("draggable").element.get(0);
(function(p) { p.removeChild( element ); p.appendChild( element ) })(element.parentNode)
$(this).css( 'z-index', '100' );
$(this).find( ".terminal" ).each( function() {
this.terminal.redraw();
});
+ workflow.node_changed( this );
}
});
return node;
diff --git a/templates/workflow/editor.mako b/templates/workflow/editor.mako
index 81e36ae6a0e..6816c0a0bfa 100644
--- a/templates/workflow/editor.mako
+++ b/templates/workflow/editor.mako
@@ -28,7 +28,7 @@
$(".dialog-box-container" ).fadeOut( function() { $("#overlay").hide(); } );
};
- function show_modal( title, body, buttons ) {
+ function show_modal( title, body, buttons, extra_buttons ) {
$( ".dialog-box" ).find( ".title" ).html( title );
var b = $( ".dialog-box" ).find( ".buttons" ).html( "" );
if ( buttons ) {
@@ -40,6 +40,16 @@
} else {
b.hide();
}
+ var b = $( ".dialog-box" ).find( ".extra_buttons" ).html( "" );
+ if ( extra_buttons ) {
+ $.each( extra_buttons, function( name, value ) {
+ b.append( $( '' ).text( name ).click( value ) );
+ b.append( " " );
+ });
+ b.show();
+ } else {
+ b.hide();
+ }
if ( body == "progress" ) {
body = $( "" );
}
@@ -100,8 +110,8 @@
## "Load a stored workflow" : load_workflow
## });
- $("#save-button").click( save_current_workflow );
- $("#close-button").click( close_editor );
+ $("#save-button").click( function() { save_current_workflow(); } );
+ $("#close-button").click( function() { close_editor(); } );
// Unload handler
window.onbeforeunload = function() {
@@ -162,7 +172,7 @@
var x = 5000, y = 5000;
$("div.toolFormInCanvas").each( function() {
x = Math.min( x, $(this).position().left );
- y = Math.min( x, $(this).position().left );
+ y = Math.min( y, $(this).position().top );
});
x = Math.min( - x + 20, 0 );
y = Math.min( - y + 20, 0 );
@@ -176,8 +186,8 @@
workflow.add_node( node );
workflow.activate_node( node );
$.ajax( {
- url: "${h.url_for( action='get_tool_info' )}",
- data: { tool_id: id, "_": "true" },
+ url: "${h.url_for( action='get_new_module_info' )}",
+ data: { type: "tool", tool_id: id, "_": "true" },
global: false,
dataType: "json",
success: function( data ) {
@@ -198,7 +208,7 @@
workflow.add_node( node );
workflow.activate_node( node );
$.ajax( {
- url: "${h.url_for( action='get_module_info' )}",
+ url: "${h.url_for( action='get_new_module_info' )}",
data: { type: type, "_": "true" },
dataType: "json",
success: function( data ) {
@@ -226,7 +236,7 @@
$("#right-content").find( "form" ).ajaxForm( {
type: 'POST',
dataType: 'json',
- success: function( data ) {
+ success: function( data ) {
node.update_field_data( data );
},
beforeSubmit: function( data ) {
@@ -247,21 +257,26 @@
var close_editor = function() {
if ( workflow && workflow.has_changes ) {
+ do_close = function() {
+ window.onbeforeunload = undefined;
+ window.document.location = "${h.url_for( controller='root' )}"
+ };
show_modal( "Close workflow editor",
"There are unsaved changes to your workflow which will be lost.",
{
"Cancel" : hide_modal,
- "Close": function() {
- window.onbeforeunload = undefined;
- window.document.location = "${h.url_for( controller='root' )}"
+ "Save Changes" : function() {
+ save_current_workflow( do_close );
}
+ }, {
+ "Don't Save": do_close,
} );
} else {
window.document.location = "${h.url_for( controller='root' )}"
}
}
- var save_current_workflow = function () {
+ var save_current_workflow = function ( success_callback ) {
show_modal( "Saving workflow", "progress" );
$.ajax( {
url: "${h.url_for( action='save_workflow' )}",
@@ -287,13 +302,22 @@
workflow.name = data.name;
workflow.has_changes = false;
workflow.stored = true;
- show_modal( "Workflow saved", body, {
- "Ok" : function () { hide_modal(); }
- });
+ if ( success_callback ) {
+ success_callback();
+ }
+ hide_modal();
}
});
}
+ ## var update_canvas_map = function() {
+ ## var c = $("#canvas-map-canvas").get(0).getContext("2d");
+ ## var cp = $("#canvas-container").position();
+ ## c.clearRect( 0, 0, 100, 100 );
+ ## c.strokeStyle = "rgb(200,0,0)";
+ ## c.strokeRect ( -cp.left / 50, -cp.top / 50, $("#canvas-viewport").width() / 50, $("#canvas-viewport").height() / 50 );
+ ## }
+
%def>
@@ -485,7 +509,11 @@
})