diff --git a/lib/galaxy/jobs/actions/__init__.py b/lib/galaxy/jobs/actions/__init__.py
new file mode 100644
index 00000000000..9750741c2a6
--- /dev/null
+++ b/lib/galaxy/jobs/actions/__init__.py
@@ -0,0 +1,4 @@
+"""
+This package contains job action classes.
+
+"""
\ No newline at end of file
diff --git a/lib/galaxy/jobs/actions/post.py b/lib/galaxy/jobs/actions/post.py
new file mode 100644
index 00000000000..2a96cae7cb7
--- /dev/null
+++ b/lib/galaxy/jobs/actions/post.py
@@ -0,0 +1,196 @@
+import logging, threading, time
+from Queue import Queue, Empty
+
+from galaxy.util.json import from_json_string, to_json_string
+
+from galaxy.web.form_builder import *
+
+log = logging.getLogger( __name__ )
+
+# DBTODO This still needs refactoring and general cleanup.
+
+class DefaultJobAction(object):
+ name = "DefaultJobAction"
+
+ @classmethod
+ def execute(cls, job):
+ pass
+
+ @classmethod
+ def get_config_form(cls, trans):
+ return "
Default Job Action Config Form
"
+
+ @classmethod
+ def get_short_str(cls, pja):
+ if pja.action_arguments:
+ return "%s -> %s" % (pja.action_type, pja.action_arguments)
+ else:
+ return "%s" % pja.action_type
+
+
+class ChangeDatatypeAction(DefaultJobAction):
+ name = "ChangeDatatypeAction"
+
+ @classmethod
+ def execute(cls, trans, action, job):
+ for dataset_assoc in job.output_datasets:
+ if action.output_name == '' or dataset_assoc.name == action.output_name:
+ trans.app.datatypes_registry.change_datatype( dataset_assoc.dataset, action.action_arguments['newtype'])
+
+ @classmethod
+ def get_config_form(cls, trans):
+ dt_list = ""
+ dtnames = [ dtype_name for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems()]
+ dtnames.sort()
+ for dt_name in dtnames:
+ dt_list += """%s """ % (dt_name, dt_name, dt_name)
+ ps = """
+ if (pja.action_type == "ChangeDatatypeAction"){
+ p_str = "";
+ }
+ """ % dt_list
+ # Note the scrip + t hack above. Is there a better way?
+ return ps
+
+class RenameDatasetAction(DefaultJobAction):
+ name = "RenameDatasetAction"
+
+ @classmethod
+ def execute(cls, trans, action, job):
+ for dataset_assoc in job.output_datasets:
+ if action.output_name == '' or dataset_assoc.name == action.output_name:
+ dataset_assoc.dataset.name = action.action_arguments['newname']
+
+ @classmethod
+ def get_config_form(cls, trans):
+ return """
+ if (pja.action_type == "RenameDatasetAction"){
+ p_str = "";
+ }
+ """
+
+class HideDatasetAction(DefaultJobAction):
+ name = "HideDatasetAction"
+
+ @classmethod
+ def execute(cls, trans, action, job):
+ for dataset_assoc in job.output_datasets:
+ if action.output_name == '' or dataset_assoc.name == action.output_name:
+ dataset_assoc.dataset.visible=False
+
+ @classmethod
+ def get_config_form(cls, trans):
+ return """
+ if (pja.action_type == "HideDatasetAction"){
+ p_str = "";
+ }
+ """
+
+class SetMetadataAction(DefaultJobAction):
+ name = "SetMetadataAction"
+ # DBTODO Setting of Metadata is currently broken and disabled. It should not be used (yet).
+
+ @classmethod
+ def execute(cls, trans, action, job):
+ for data in self.job.output_datasets:
+ data.set_metadata( action.action_arguments['newtype'] )
+
+ @classmethod
+ def get_config_form(cls, trans):
+ dt_list = ""
+ mdict = {}
+ for dtype_name, dtype_value in trans.app.datatypes_registry.datatypes_by_extension.iteritems():
+ for mn, mt in dtype_value.metadata_spec.items():
+ if mt.visible:
+ mdict[mt.desc] = mt.param.get_html(value= mn).replace('"', "'").strip().replace('\n','')
+ for k, v in mdict.items():
+ dt_list += "" + k + ": " + v + "
"
+ return """
+ if (pja.action_type == "SetMetadataAction"){
+ p_str = "";
+ }
+ """ % dt_list
+
+ACTIONS = { "RenameDatasetAction" : RenameDatasetAction,
+ "HideDatasetAction" : HideDatasetAction,
+ "ChangeDatatypeAction": ChangeDatatypeAction,
+ # "SetMetadataAction" : SetMetadataAction,
+ }
+
+class ActionBox(object):
+ @classmethod
+ def execute(cls, action, job):
+ if action.action_type in ACTIONS:
+ ACTIONS[action.action_type].execute(action, job, trans)
+ else:
+ return False
+
+ @classmethod
+ def get_short_str(cls, action):
+ if action.action_type in ACTIONS:
+ return ACTIONS[action.action_type].get_short_str(action)
+ else:
+ return "Unknown PostJobAction"
+
+ @classmethod
+ def handle_incoming(cls, incoming):
+ npd = {}
+ for key, val in incoming.iteritems():
+ if key.startswith('pja'):
+ sp = key.split('__')
+ # flag / output_name / pjatype / desc
+ if not sp[2] in npd:
+ npd[sp[2]] = {'action_type' : sp[2],
+ 'output_name' : sp[1],
+ 'action_arguments' : {}}
+ if len(sp) > 3:
+ if sp[3] == 'output_name':
+ npd[sp[2]]['output_name'] = val
+ else:
+ npd[sp[2]]['action_arguments'][sp[3]] = val
+ else:
+ # Not pja stuff.
+ pass
+ return to_json_string(npd)
+
+ @classmethod
+ def get_add_list(cls):
+ addlist = ""
+ for action in ACTIONS:
+ addlist += "%s " % (ACTIONS[action].name, ACTIONS[action].name)
+ addlist += " "
+ return addlist
+
+ @classmethod
+ def get_forms(cls, trans):
+ forms = ""
+ for action in ACTIONS:
+ forms += ACTIONS[action].get_config_form(trans)
+ return forms
+
+ @classmethod
+ def execute(cls, trans, pja, job):
+ ACTIONS[pja.action_type].execute(trans, pja, job)
diff --git a/lib/galaxy/model/__init__.py b/lib/galaxy/model/__init__.py
index 5f77a398281..5ac3d9780af 100644
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -113,6 +113,8 @@ class Job( object ):
self.info = None
self.job_runner_name = None
self.job_runner_external_id = None
+ self.post_job_actions = None
+
def add_parameter( self, name, value ):
self.parameters.append( JobParameter( name, value ) )
def add_input_dataset( self, name, dataset ):
@@ -184,6 +186,13 @@ class JobToOutputLibraryDatasetAssociation( object ):
self.name = name
self.dataset = dataset
+class PostJobAction( object ):
+ def __init__( self, action_type, workflow_step, output_name = None, action_arguments = None):
+ self.action_type = action_type
+ self.output_name = output_name
+ self.action_arguments = action_arguments
+ self.workflow_step = workflow_step
+
class JobExternalOutputMetadata( object ):
def __init__( self, job = None, dataset = None ):
self.job = job
diff --git a/lib/galaxy/model/mapping.py b/lib/galaxy/model/mapping.py
index 1278a058fe8..1047865c780 100644
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -369,6 +369,13 @@ JobExternalOutputMetadata.table = Table( "job_external_output_metadata", metadat
Column( "filename_override_metadata", String( 255 ) ),
Column( "job_runner_external_pid", String( 255 ) ) )
+PostJobAction.table = Table("post_job_action", metadata,
+ Column("id", Integer, primary_key=True),
+ Column("workflow_step_id", Integer, ForeignKey( "workflow_step.id" ), index=True, nullable=False),
+ Column("action_type", String(255), nullable=False),
+ Column("output_name", String(255), nullable=True),
+ Column("action_arguments", JSONType, nullable=True))
+
Event.table = Table( "event", metadata,
Column( "id", Integer, primary_key=True ),
Column( "create_time", DateTime, default=now ),
@@ -1237,6 +1244,9 @@ assign_mapper( context, JobExternalOutputMetadata, JobExternalOutputMetadata.tab
history_dataset_association = relation( HistoryDatasetAssociation, lazy = False ),
library_dataset_dataset_association = relation( LibraryDatasetDatasetAssociation, lazy = False ) ) )
+assign_mapper( context, PostJobAction, PostJobAction.table,
+ properties=dict(workflow_step = relation( WorkflowStep, backref='post_job_actions', primaryjoin=(WorkflowStep.table.c.id == PostJobAction.table.c.workflow_step_id))))
+
assign_mapper( context, Job, Job.table,
properties=dict( galaxy_session=relation( GalaxySession ),
history=relation( History ),
@@ -1309,7 +1319,7 @@ assign_mapper( context, Workflow, Workflow.table,
assign_mapper( context, WorkflowStep, WorkflowStep.table,
properties=dict(
tags=relation(WorkflowStepTagAssociation, order_by=WorkflowStepTagAssociation.table.c.id, backref="workflow_steps"),
- annotations=relation( WorkflowStepAnnotationAssociation, order_by=WorkflowStepAnnotationAssociation.table.c.id, backref="workflow_steps" ) )
+ annotations=relation( WorkflowStepAnnotationAssociation, order_by=WorkflowStepAnnotationAssociation.table.c.id, backref="workflow_steps" ) )
)
assign_mapper( context, WorkflowStepConnection, WorkflowStepConnection.table,
diff --git a/lib/galaxy/model/migrate/versions/0046_post_job_actions.py b/lib/galaxy/model/migrate/versions/0046_post_job_actions.py
new file mode 100644
index 00000000000..9c4fcd93242
--- /dev/null
+++ b/lib/galaxy/model/migrate/versions/0046_post_job_actions.py
@@ -0,0 +1,49 @@
+"""
+Migration script to create tables for handling post-job actions.
+"""
+
+from sqlalchemy import *
+from sqlalchemy.orm import *
+from migrate import *
+from migrate.changeset import *
+
+import logging
+logging.basicConfig( level=logging.DEBUG )
+log = logging.getLogger( __name__ )
+
+# Need our custom types, but don't import anything else from model
+from galaxy.model.custom_types import *
+
+import datetime
+now = datetime.datetime.utcnow
+
+metadata = MetaData( migrate_engine )
+db_session = scoped_session( sessionmaker( bind=migrate_engine, autoflush=False, autocommit=True ) )
+
+PostJobAction_table = Table("post_job_action", metadata,
+ Column("id", Integer, primary_key=True),
+ Column("workflow_step_id", Integer, ForeignKey( "workflow_step.id" ), index=True, nullable=False),
+ Column("action_type", String(255), nullable=False),
+ Column("output_name", String(255), nullable=True),
+ Column("action_arguments", JSONType, nullable=True))
+
+# PostJobActionAssociation_table = Table("post_job_action_association", metadata,
+# Column("id", Integer, primary_key=True),
+# Column("post_job_action_id", Integer, ForeignKey("post_job_action.id"), index=True, nullable=False),
+# Column("job_id", Integer, ForeignKey("job.id"), index=True, nullable=False))
+
+tables = [PostJobAction_table]#, PostJobActionAssociation_table]
+
+def upgrade():
+ print __doc__
+ metadata.reflect()
+ for table in tables:
+ try:
+ table.create()
+ except:
+ log.warn( "Failed to create table '%s', ignoring (might result in wrong schema)" % table.name )
+
+def downgrade():
+ metadata.reflect()
+ for table in tables:
+ table.drop()
\ No newline at end of file
diff --git a/lib/galaxy/web/controllers/workflow.py b/lib/galaxy/web/controllers/workflow.py
index 4253483b126..ad9e7bd42a1 100644
--- a/lib/galaxy/web/controllers/workflow.py
+++ b/lib/galaxy/web/controllers/workflow.py
@@ -17,6 +17,7 @@ from galaxy.workflow.modules import *
from galaxy import model
from galaxy.model.mapping import desc
from galaxy.model.orm import *
+from galaxy.jobs.actions.post import *
import urllib2
@@ -387,7 +388,6 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
else:
stored.importable = importable
trans.sa_session.flush()
-
return
@web.expose
@@ -514,6 +514,7 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
This is used for the form shown in the right pane when a node
is selected.
"""
+
trans.workflow_building_mode = True
module = module_factory.from_dict( trans, {
'type': type,
@@ -521,14 +522,26 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
'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(),
- 'tool_errors': module.get_errors(),
- 'form_html': module.get_config_form(),
- 'annotation': annotation
- }
+
+ if type=='tool':
+ return {
+ 'tool_state': module.get_state(),
+ 'data_inputs': module.get_data_inputs(),
+ 'data_outputs': module.get_data_outputs(),
+ 'tool_errors': module.get_errors(),
+ 'form_html': module.get_config_form(),
+ 'annotation': annotation,
+ 'post_job_actions': module.get_post_job_actions()
+ }
+ else:
+ return {
+ 'tool_state': module.get_state(),
+ 'data_inputs': module.get_data_inputs(),
+ 'data_outputs': module.get_data_outputs(),
+ 'tool_errors': module.get_errors(),
+ 'form_html': module.get_config_form(),
+ 'annotation': annotation
+ }
@web.json
def get_new_module_info( self, trans, type, **kwargs ):
@@ -552,7 +565,7 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
'form_html': module.get_config_form(),
'annotation': ""
}
-
+
@web.json
def load_workflow( self, trans, id ):
"""
@@ -613,6 +626,13 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
# Filter
# FIXME: this removes connection without displaying a message currently!
input_connections = [ conn for conn in input_connections if conn.input_name in data_input_names ]
+ # post_job_actions
+ pja_dict = {}
+ for pja in step.post_job_actions:
+ pja_dict[pja.action_type+pja.output_name] = dict(action_type = pja.action_type,
+ output_name = pja.output_name,
+ action_arguments = pja.action_arguments)
+ step_dict['post_job_actions'] = pja_dict
# Encode input connections as dictionary
input_conn_dict = {}
for conn in input_connections:
@@ -665,7 +685,7 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
annotation = step_dict[ 'annotation' ]
if annotation:
annotation = sanitize_html( annotation, 'utf-8', 'text/html' )
- self.add_item_annotation( trans, step, annotation )
+ self.add_item_annotation( trans, step, annotation )
# Second pass to deal with connections between steps
for step in steps:
# Input connections
@@ -815,7 +835,7 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
annotation = step_dict[ 'annotation' ]
if annotation:
annotation = sanitize_html( annotation, 'utf-8', 'text/html' )
- self.add_item_annotation( trans, step, annotation )
+ self.add_item_annotation( trans, step, annotation )
# Second pass to deal with connections between steps
for step in steps:
# Input connections
@@ -1044,6 +1064,8 @@ class WorkflowController( BaseController, Sharable, UsesStoredWorkflow, UsesAnno
# Execute it
job, out_data = tool.execute( trans, step.state.inputs )
outputs[ step.id ] = out_data
+ for pja in step.post_job_actions:
+ ActionBox.execute(trans, pja, job)
else:
job, out_data = step.module.execute( trans, step.state )
outputs[ step.id ] = out_data
diff --git a/lib/galaxy/workflow/modules.py b/lib/galaxy/workflow/modules.py
index e4881f052d5..15aa9676a21 100644
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -6,7 +6,8 @@ from galaxy.tools import DefaultToolState
from galaxy.tools.parameters.grouping import Repeat, Conditional
from galaxy.util.bunch import Bunch
from galaxy.util.json import from_json_string, to_json_string
-
+from galaxy.jobs.actions.post import ActionBox
+from galaxy.model import PostJobAction
class WorkflowModule( object ):
@@ -163,6 +164,7 @@ class ToolModule( WorkflowModule ):
self.trans = trans
self.tool_id = tool_id
self.tool = trans.app.toolbox.tools_by_id[ tool_id ]
+ self.post_job_actions = {}
self.state = None
self.errors = None
@@ -171,6 +173,7 @@ class ToolModule( WorkflowModule ):
module = Class( trans, tool_id )
module.state = module.tool.new_state( trans, all_pages=True )
return module
+
@classmethod
def from_dict( Class, trans, d, secure=True ):
tool_id = d['tool_id']
@@ -178,6 +181,10 @@ class ToolModule( WorkflowModule ):
module.state = DefaultToolState()
module.state.decode( d["tool_state"], module.tool, module.trans.app, secure=secure )
module.errors = d.get( "tool_errors", None )
+ if 'post_job_actions' in d and d["post_job_actions"] != []:
+ module.post_job_actions = d["post_job_actions"]
+ else:
+ module.post_job_actions = {}
return module
@classmethod
@@ -187,6 +194,11 @@ class ToolModule( WorkflowModule ):
module.state = DefaultToolState()
module.state.inputs = module.tool.params_from_strings( step.tool_inputs, trans.app, ignore_errors=True )
module.errors = step.tool_errors
+ # module.post_job_actions = step.post_job_actions
+ pjadict = {}
+ for pja in step.post_job_actions:
+ pjadict[pja.action_type] = pja
+ module.post_job_actions = pjadict
return module
def save_to_step( self, step ):
@@ -194,6 +206,17 @@ class ToolModule( WorkflowModule ):
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
+ for k, v in self.post_job_actions.iteritems():
+ # Must have action_type, step. output and a_args are optional.
+ if 'output_name' in v:
+ output_name = v['output_name']
+ else:
+ output_name = None
+ if 'action_arguments' in v:
+ action_arguments = v['action_arguments']
+ else:
+ action_arguments = None
+ n_p = PostJobAction(v['action_type'], step, output_name, action_arguments)
def get_name( self ):
return self.tool.name
@@ -221,15 +244,23 @@ class ToolModule( WorkflowModule ):
for name, ( format, metadata_source, parent ) in self.tool.outputs.iteritems():
data_outputs.append( dict( name=name, extension=format ) )
return data_outputs
+
+ def get_post_job_actions( self ):
+ return self.post_job_actions
+
def get_config_form( self ):
self.add_dummy_datasets()
return self.trans.fill_template( "workflow/editor_tool_form.mako",
tool=self.tool, values=self.state.inputs, errors=( self.errors or {} ) )
+
def update_state( self, incoming ):
# Build a callback that handles setting an input to be required at
# runtime. We still process all other parameters the user might have
# set. We also need to make sure all datasets have a dummy value
# for dependencies to see
+
+ self.post_job_actions = ActionBox.handle_incoming(incoming)
+
make_runtime_key = incoming.get( 'make_runtime', None )
make_buildtime_key = incoming.get( 'make_buildtime', None )
def item_callback( trans, key, input, value, error, old_value, context ):
diff --git a/static/scripts/galaxy.workflow_editor.canvas.js b/static/scripts/galaxy.workflow_editor.canvas.js
index 3f7e84aa8aa..97a587603e4 100644
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -273,6 +273,7 @@ $.extend( Node.prototype, {
this.tool_errors = data.tool_errors;
this.tooltip = data.tooltip ? data.tooltip : ""
this.annotation = data.annotation;
+ this.post_job_actions = data.post_job_actions;
if ( this.tool_errors ) {
f.addClass( "tool-node-error" );
@@ -309,6 +310,7 @@ $.extend( Node.prototype, {
this.form_html = data.form_html;
this.tool_errors = data.tool_errors;
this.annotation = data['annotation'];
+ this.post_job_actions = $.parseJSON(data.post_job_actions);
if ( this.tool_errors ) {
el.addClass( "tool-node-error" );
} else {
@@ -400,6 +402,19 @@ $.extend( Workflow.prototype, {
input_connections[ t.name ] = { id: c.handle1.node.id, output_name: c.handle1.name };
});
});
+ var post_job_actions = {};
+ if (node.post_job_actions){
+ $.each( node.post_job_actions, function ( i, act ) {
+ var pja = {
+ job_id : act.id,
+ action_type : act.action_type,
+ output_name : act.output_name,
+ action_arguments : act.action_arguments
+ }
+ post_job_actions[ act.type + act.output_name ] = null;
+ post_job_actions[ act.type + act.output_name ] = pja;
+ });
+ }
var node_data = {
id : node.id,
type : node.type,
@@ -408,7 +423,8 @@ $.extend( Workflow.prototype, {
tool_errors : node.tool_errors,
input_connections : input_connections,
position : $(node.element).position(),
- annotation: node.annotation
+ annotation: node.annotation,
+ post_job_actions: node.post_job_actions
};
nodes[ node.id ] = node_data;
});
diff --git a/templates/workflow/editor.mako b/templates/workflow/editor.mako
index a5769109207..d8a1cdc17c1 100644
--- a/templates/workflow/editor.mako
+++ b/templates/workflow/editor.mako
@@ -128,7 +128,7 @@
show_modal( "Server error", message, { "Ignore error" : hide_modal } );
return false;
});
-
+
make_popupmenu( $("#workflow-options-button"), {
##"Create New" : create_new_workflow_dialog,
"Edit Attributes" : edit_workflow_attributes,
@@ -306,13 +306,63 @@
});
};
+<%
+ from galaxy.jobs.actions.post import ActionBox
+%>
+
+ // DBTODO Refactor to the post module.
+ // This function preloads how to display known pja's.
+ function display_pja(pja, node){
+ // DBTODO SANITIZE INPUTS. Way too easy to break the page right now with a change dataset name action.
+ p_str = '';
+ ${ActionBox.get_forms(trans)};
+ $("#pja_container").append(p_str);
+ $("#pja_container>.toolForm:last>.toolFormTitle>.buttons").click(function (){
+ action_to_rem = $(this).closest(".toolForm", ".action_tag").children(".action_tag:first").text();
+ $(this).closest(".toolForm").remove();
+ delete workflow.active_node.post_job_actions[action_to_rem];
+ workflow.active_form_has_changes = true;
+ });
+ }
+
+ function display_pja_list(){
+ return "${ActionBox.get_add_list()}";
+ }
+
+ function display_file_list(node){
+ addlist = "";
+ for (var out_terminal in node.output_terminals){
+ addlist += ""+ out_terminal +" ";
+ }
+ addlist += " ";
+ return addlist;
+ }
+
+ function new_pja(action_type, target, node){
+ if (node.post_job_actions == undefined){
+ //New tool node, set up dict.
+ node.post_job_actions = {};
+ }
+ if (node.post_job_actions[action_type+target] == undefined){
+ var new_pja = new Object();
+ new_pja.action_type = action_type;
+ new_pja.output_name = target;
+ node.post_job_actions[action_type+target] = null;
+ node.post_job_actions[action_type+target] = new_pja;
+ display_pja(new_pja, node);
+ workflow.active_form_has_changes = true;
+ return true;
+ }else{
+ return false;
+ }
+ }
+
function show_form_for_tool( text, node ) {
$("#edit-attributes").hide();
$("#right-content").show().html( text );
-
// Add metadata form to tool.
if (node) {
- $("#right-content").find(".toolForm").after( "
\
+ $("#right-content").find(".toolForm:first").after( "
" );
}
-
+ // Add step actions.
+ if (node && node.type=='tool'){
+ pjastr = "
";
+ $("#right-content").find(".toolForm").after( pjastr );
+ for (var key in node.post_job_actions){
+ if (key != "undefined"){ //To make sure we haven't just deleted it.
+ display_pja(node.post_job_actions[key], node);
+ }
+ }
+ $("#add_pja").click(function (){
+ new_pja($("#new_pja_list").val(),$("#node_data_list").val(), node);
+ });
+ }
$("#right-content").find( "form" ).ajaxForm( {
type: 'POST',
dataType: 'json',
@@ -355,7 +421,6 @@
$(this).remove();
make_popupmenu( b, options );
});
-
// Implements auto-saving based on whether the inputs change. We consider
// "changed" to be when a field is accessed and not necessarily modified
// because of an issue where "onchange" is not triggered when activating
@@ -612,6 +677,7 @@
.form-row {
}
+
div.toolFormInCanvas div.toolFormBody {
padding: 0;
}
@@ -630,7 +696,19 @@
position: absolute;
z-index: 10000;
}
-
+
+ .pjaForm {
+ margin-bottom:10px;
+ }
+
+ .pjaForm .toolFormBody{
+ padding:10px;
+ }
+
+ .pjaForm .toolParamHelp{
+ padding:5px;
+ }
+
.panel-header-button-group {
margin-right: 5px;
padding-right: 5px;
diff --git a/templates/workflow/run.mako b/templates/workflow/run.mako
index 93f464abbcc..8a84064404b 100644
--- a/templates/workflow/run.mako
+++ b/templates/workflow/run.mako
@@ -23,6 +23,7 @@
<%
from galaxy.tools.parameters import DataToolParameter, RuntimeValue
+from galaxy.jobs.actions.post import ActionBox
%>
<%def name="do_inputs( inputs, values, errors, prefix, step, other_values = None )">
@@ -136,6 +137,23 @@ from galaxy.tools.parameters import DataToolParameter, RuntimeValue
Step ${int(step.order_index)+1}: ${tool.name}
${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
+ % if step.post_job_actions:
+
+
+ % if len(step.post_job_actions) > 1:
+ Actions:
+ % else:
+ Action:
+ % endif
+ ${', '.join([ActionBox.get_short_str(pja) for pja in step.post_job_actions])}
+
+ % endif
+ % if step.annotations:
+
+
+ Annotation: ${step.annotations[0].annotation}
+
+ % endif
%else:
@@ -145,6 +163,12 @@ from galaxy.tools.parameters import DataToolParameter, RuntimeValue
Step ${int(step.order_index)+1}: ${module.name}
${do_inputs( module.get_runtime_inputs(), step.state.inputs, errors.get( step.id, dict() ), "", step )}
+ % if step.annotations:
+
+
+ Annotation: ${step.annotations[0].annotation}
+
+ % endif
%endif