mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-21 13:50:20 +08:00
Merge with cde78bdeaca823b011477498a4dfd1466d20c0c0
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
"""
|
||||
This package contains job action classes.
|
||||
|
||||
"""
|
||||
@@ -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 "<p>Default Job Action Config Form</p>"
|
||||
|
||||
@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 += """<option id='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype__%s' value='%s'>%s</option>""" % (dt_name, dt_name, dt_name)
|
||||
ps = """
|
||||
if (pja.action_type == "ChangeDatatypeAction"){
|
||||
p_str = "<div class='pjaForm toolForm'><span class='action_tag' style='display:none'>"+ pja.action_type + pja.output_name + "</span><div class='toolFormTitle'>" + pja.action_type + " <br/> on " + pja.output_name + "\
|
||||
<div style='float: right;' class='buttons'><img src='../images/delete_icon.png'></div></div>\
|
||||
<div class='toolFormBody'><label for='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype'>New Datatype:</label><select id='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype' name='pja__"+pja.output_name+"__ChangeDatatypeAction__newtype'>\
|
||||
%s\
|
||||
</select>";
|
||||
if (pja.action_arguments != undefined && pja.action_arguments.newtype != undefined){
|
||||
p_str += "<scrip" + "t type='text/javascript'>$('#pja__" + pja.output_name + "__ChangeDatatypeAction__newtype').val('" + pja.action_arguments.newtype + "');</scrip" + "t>"
|
||||
}
|
||||
p_str += "</div><div class='toolParamHelp'>This action will change the datatype of the output to the indicated value.</div></div>";
|
||||
}
|
||||
""" % 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 = "<div class='pjaForm toolForm'><span class='action_tag' style='display:none'>"+ pja.action_type + pja.output_name + "</span><div class='toolFormTitle'>"+ pja.action_type + " <br/> on " + pja.output_name + "\
|
||||
<div style='float: right;' class='buttons'><img src='../images/delete_icon.png'></div></div><div class='toolFormBody'>";
|
||||
if ((pja.action_arguments != undefined) && (pja.action_arguments.newname != undefined)){
|
||||
p_str += "<label for='pja__"+pja.output_name+"__RenameDatasetAction__newname'>New output name:</label><input type='text' name='pja__"+pja.output_name+"__RenameDatasetAction__newname' value='"+pja.action_arguments.newname + "'/>";
|
||||
}
|
||||
else{
|
||||
p_str += "<label for='pja__"+pja.output_name+"__RenameDatasetAction__newname'>New output name:</label><input type='text' name='pja__"+pja.output_name+"__RenameDatasetAction__newname' value='New Name'/>";
|
||||
}
|
||||
p_str += "</div><div class='toolParamHelp'>This action will rename the result dataset.</div></div>";
|
||||
}
|
||||
"""
|
||||
|
||||
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 = "<div class='pjaForm toolForm'><span class='action_tag' style='display:none'>"+ pja.action_type + pja.output_name + "</span><div class='toolFormTitle'>"+ pja.action_type + " <br/> on " + pja.output_name + "\
|
||||
<div style='float: right;' class='buttons'><img src='../images/delete_icon.png'></div></div><div class='toolFormBody'>";
|
||||
p_str += "<label for='pja__"+pja.output_name+"__HideDatasetAction'>There are no additional options for this action.</label><input type='hidden' name='pja__"+pja.output_name+"__HideDatasetAction'/>";
|
||||
p_str += "</div><div class='toolParamHelp'>This action will *hide* the result dataset from your history.</div></div>";
|
||||
}
|
||||
"""
|
||||
|
||||
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 += "<p><strong>" + k + ":</strong><br/>" + v + "</p>"
|
||||
return """
|
||||
if (pja.action_type == "SetMetadataAction"){
|
||||
p_str = "<div class='pjaForm toolForm'><span class='action_tag' style='display:none'>"+ pja.action_type + pja.output_name + "</span><div class='toolFormTitle'>"+ pja.action_type + " <br/> on " + pja.output_name + "\
|
||||
<div style='float: right;' class='buttons'><img src='../images/delete_icon.png'></div></div>\
|
||||
<div class='toolFormBody'>\
|
||||
%s\
|
||||
</div><div class='toolParamHelp'>This tool sets metadata in output.</div></div>";
|
||||
}
|
||||
""" % 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 = "<select id='new_pja_list' name='new_pja_list'>"
|
||||
for action in ACTIONS:
|
||||
addlist += "<option value='%s'>%s</option>" % (ACTIONS[action].name, ACTIONS[action].name)
|
||||
addlist += "</select>"
|
||||
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)
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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()
|
||||
@@ -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
|
||||
|
||||
@@ -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 ):
|
||||
|
||||
@@ -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;
|
||||
});
|
||||
|
||||
@@ -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 = "<select id='node_data_list' name='node_data_list'>";
|
||||
for (var out_terminal in node.output_terminals){
|
||||
addlist += "<option value='" + out_terminal + "'>"+ out_terminal +"</option>";
|
||||
}
|
||||
addlist += "</select>";
|
||||
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( "<p><div class='metadataForm'> \
|
||||
$("#right-content").find(".toolForm:first").after( "<p><div class='metadataForm'> \
|
||||
<div class='metadataFormTitle'>Edit Step Attributes</div> \
|
||||
<div class='form-row'> \
|
||||
<label>Annotation / Notes:</label> \
|
||||
@@ -323,7 +373,23 @@
|
||||
</div> \
|
||||
</div>" );
|
||||
}
|
||||
|
||||
// Add step actions.
|
||||
if (node && node.type=='tool'){
|
||||
pjastr = "<p><div class='metadataForm'><div class='metadataFormTitle'>Edit Step Actions</div><div class='form-row'> \
|
||||
<label>New Actions:</label><br/>" + display_pja_list() + display_file_list(node) + " <div class='action-button' style='border:1px solid black;display:inline;' id='add_pja'>Create</div>\
|
||||
</div><div class='form-row'>\
|
||||
<div style='margin-right: 10px;'><span id='pja_container'></span>";
|
||||
pjastr += "<div class='toolParamHelp'>Add actions to this step; actions are applied when this workflow step completes.</div></div></div></div>";
|
||||
$("#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;
|
||||
|
||||
@@ -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
|
||||
<div class="toolFormTitle">Step ${int(step.order_index)+1}: ${tool.name}</div>
|
||||
<div class="toolFormBody">
|
||||
${do_inputs( tool.inputs, step.state.inputs, errors.get( step.id, dict() ), "", step )}
|
||||
% if step.post_job_actions:
|
||||
<hr/>
|
||||
<div class='form-row'>
|
||||
% if len(step.post_job_actions) > 1:
|
||||
<label>Actions:</label>
|
||||
% else:
|
||||
<label>Action:</label>
|
||||
% endif
|
||||
${', '.join([ActionBox.get_short_str(pja) for pja in step.post_job_actions])}
|
||||
</div>
|
||||
% endif
|
||||
% if step.annotations:
|
||||
<hr/>
|
||||
<div class='form-row'>
|
||||
<label>Annotation:</label> ${step.annotations[0].annotation}
|
||||
</div>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
%else:
|
||||
@@ -145,6 +163,12 @@ from galaxy.tools.parameters import DataToolParameter, RuntimeValue
|
||||
<div class="toolFormTitle">Step ${int(step.order_index)+1}: ${module.name}</div>
|
||||
<div class="toolFormBody">
|
||||
${do_inputs( module.get_runtime_inputs(), step.state.inputs, errors.get( step.id, dict() ), "", step )}
|
||||
% if step.annotations:
|
||||
<hr/>
|
||||
<div class='form-row'>
|
||||
<label>Annotation:</label> ${step.annotations[0].annotation}
|
||||
</div>
|
||||
% endif
|
||||
</div>
|
||||
</div>
|
||||
%endif
|
||||
|
||||
Reference in New Issue
Block a user