Skip to content

Commit

Permalink
Unify tool parameter visitor
Browse files Browse the repository at this point in the history
  • Loading branch information
guerler committed Apr 7, 2016
1 parent 41a281b commit d554895
Show file tree
Hide file tree
Showing 12 changed files with 98 additions and 118 deletions.
78 changes: 28 additions & 50 deletions client/galaxy/scripts/mvc/form/form-data.js
Expand Up @@ -122,7 +122,10 @@ define([ 'utils/utils' ], function( Utils ) {
/** Matches a new tool model to the current input elements e.g. used to update dynamic options
*/
matchModel: function( model, callback ) {
return matchIds( model.inputs, this.flat_dict, callback );
var self = this;
return visitInputs( model.inputs, function( name, input ) {
self.flat_dict[ name ] && callback ( self.flat_dict[ name ], input );
});
},

/** Matches identifier from api response to input elements e.g. used to display validation errors
Expand Down Expand Up @@ -191,66 +194,41 @@ define([ 'utils/utils' ], function( Utils ) {
return -1;
};

/** Match context
/** Visits tool inputs
* @param{dict} inputs - Nested dictionary of input elements
* @param{dict} key - Reference key which is matched to an input name e.g. data_ref
* @param{dict} callback - Called with matched context i.e. callback( input, referenced_input )
* @param{dict} callback - Called with the mapped dictionary object and corresponding model node
*/
var matchContext = function( inputs, key, callback, context ) {
var visitInputs = function( inputs, callback, prefix, context ) {
prefix = prefix || '';
context = $.extend( true, {}, context );
_.each( inputs, function ( input ) {
input && input.type && ( context[ input.name ] = input );
});
_.each( inputs, function ( input ) {
if ( _.isObject( input ) ) {
if ( input.type && context[ input[ key ] ] ) {
callback ( input, context[ input[ key ] ] );
} else {
matchContext( input, key, callback, context );
}
}
});
};

/** Matches a tool model to a dictionary, indexed with flat ids
* @param{dict} inputs - Nested dictionary of input elements
* @param{dict} mapping - Dictionary containing prefixed/flat ids i.e. parameter_0|parameter_1
* @param{dict} callback - Called with the mapped dictionary object and corresponding model node
*/
var matchIds = function( inputs, mapping, callback ) {
var result = {};
var self = this;
function search ( id, head ) {
for ( var i in head ) {
var node = head[ i ];
var index = node.name;
id != '' && ( index = id + '|' + index );
switch ( node.type ) {
case 'repeat':
for ( var j in node.cache ) {
search ( index + '_' + j, node.cache[ j ] );
}
break;
case 'conditional':
var selectedCase = matchCase( node, node.test_param && node.test_param.value );
selectedCase != -1 && search ( index, node.cases[ selectedCase ].inputs );
break;
case 'section':
search ( index, node.inputs );
break;
default:
var mapped = mapping[ index ];
mapped && callback( mapped, node );
}
for ( var i in inputs ) {
var node = inputs[ i ];
var name = node.name;
prefix != '' && ( name = prefix + '|' + name );
switch ( node.type ) {
case 'repeat':
_.each( node.cache, function( cache, j ) {
visitInputs( cache, callback, name + '_' + j, context );
});
break;
case 'conditional':
var selectedCase = matchCase( node, node.test_param && node.test_param.value );
selectedCase != -1 && visitInputs( node.cases[ selectedCase ].inputs, callback, name, context );
break;
case 'section':
visitInputs( node.inputs, callback, name, context )
break;
default:
callback( name, node, context );
}
}
search( '', inputs );
return result;
};

return {
Manager : Manager,
matchIds : matchIds,
matchContext : matchContext
visitInputs : visitInputs
}
});
18 changes: 9 additions & 9 deletions client/galaxy/scripts/mvc/form/form-input.js
Expand Up @@ -73,21 +73,21 @@ define([], function() {
help_text += ' (' + help_argument + ')';
}
this.$info.html( help_text );
// render input field
this.field.collapsed ? this.$field.hide() : this.$field.fadeIn( 'fast' );
// render preview view for collapsed fields
this.$preview[ this.field.collapsed && this.model.get( 'collapsible_preview' ) ? 'show' : 'hide' ]()
.html( this.model.get( 'text_value' ) );
// render error messages
var error_text = this.model.get( 'error_text' );
this.$error[ error_text ? 'show' : 'hide' ]();
this.$el[ error_text ? 'addClass' : 'removeClass' ]( 'ui-error' );
this.$error_text.html( error_text );
// render backdrop to disable field
// render backdrop
this.$backdrop.removeClass()
.addClass( 'ui-form-backdrop' )
.addClass( 'ui-form-backdrop-' + this.model.get( 'backdrop' ) );
// render collapsible state and title
.addClass( 'ui-form-backdrop' )
.addClass( 'ui-form-backdrop-' + this.model.get( 'backdrop' ) );
// render input field
this.field.collapsed || this.model.get( 'disabled' ) ? this.$field.hide() : this.$field.fadeIn( 'fast' );
// render preview
this.$preview[ ( this.field.collapsed && this.model.get( 'collapsible_preview' ) || this.model.get( 'disabled' ) ) ? 'show' : 'hide' ]()
.text( this.model.get( 'text_value' ) );
// render collapsible options
if ( !this.model.get( 'disabled' ) && this.model.get( 'collapsible_value' ) !== undefined ) {
var collapsible_state = this.field.collapsed ? 'enable' : 'disable';
this.$title_text.hide();
Expand Down
102 changes: 52 additions & 50 deletions client/galaxy/scripts/mvc/tool/tool-form-composite.js
Expand Up @@ -38,57 +38,54 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
cls_enable : 'fa fa-edit',
cls_disable : 'fa fa-undo'
}, step );
// convert all connected data inputs to hidden fields with proper labels
_.each( self.model.get( 'steps' ), function( sub_step ) {
self.steps[ i ] = step;
self.links[ i ] = [];
});

// convert all connected data inputs to hidden fields with proper labels
_.each( this.steps, function( step, i ) {
_.each( self.steps, function( sub_step ) {
var connections_by_name = {};
_.each( step.output_connections, function( connection ) {
sub_step.step_id === connection.input_step_id && ( connections_by_name[ connection.input_name ] = connection );
});
FormData.matchIds( sub_step.inputs, connections_by_name, function( connection, input ) {
if ( !input.linked ) {
input.linked = step.step_type;
input.type = 'hidden';
input.help = '';
} else {
input.help += ', ';
FormData.visitInputs( sub_step.inputs, function( name, input ) {
var connection = connections_by_name[ name ];
if ( connection ) {
if ( !input.linked ) {
input.linked = step.step_type;
input.type = 'hidden';
input.help = '';
} else {
input.help += ', ';
}
input.help += 'Output dataset \'' + connection.output_name + '\' from step ' + ( parseInt( i ) + 1 );
}
input.help += 'Output dataset \'' + connection.output_name + '\' from step ' + ( parseInt( i ) + 1 );
});
});
self.steps[ i ] = step;
self.links[ i ] = [];
});

// select fields are shown for dynamic fields if all putative data inputs are available,
// or if a particular reference is specified and available
// or if an explicit reference is specified as data_ref and available
_.each( this.steps, function( step, i ) {
if ( step.step_type == 'tool' ) {
function visitor( inputs, data_resolved ) {
data_resolved === undefined && ( data_resolved = true );
_.each( inputs, function ( input ) {
if ( _.isObject( input ) ) {
if ( input.type ) {
var is_data_input = [ 'data', 'data_collection' ].indexOf( input.type ) !== -1;
var is_workflow_parameter = self._isWorkflowParameter( input.value );
is_data_input && input.linked && !input.linked.startsWith( 'data' ) && ( data_resolved = false );
input.options && ( ( input.options.length == 0 && !data_resolved ) || is_workflow_parameter ) && ( input.is_workflow = true );
(is_data_input || input.value && input.value.__class__ == 'RuntimeValue' ) && ( step.collapsed = false );
input.value && input.value.__class__ == 'RuntimeValue' && ( input.value = null );
input.flavor = 'workflow';
if ( !is_data_input && input.type !== 'hidden' && !is_workflow_parameter ) {
if ( input.optional || ( Utils.validate( input.value ) && input.value !== '' ) ) {
input.collapsible_value = input.value;
input.collapsible_preview = true;
}
}
}
visitor( input, data_resolved );
var data_resolved = true;
FormData.visitInputs( step.inputs, function ( name, input, context ) {
var is_data_input = ([ 'data', 'data_collection' ]).indexOf( input.type ) != -1;
var is_workflow_parameter = self._isWorkflowParameter( input.value );
var data_ref = context[ input.data_ref ];
input.linked && !input.linked.startsWith( 'data' ) && ( data_resolved = false );
input.options && ( ( input.options.length == 0 && !data_resolved ) || is_workflow_parameter ) && ( input.is_workflow = true );
data_ref && ( input.is_workflow = ( data_ref.linked && !data_ref.linked.startsWith( 'data' ) ) || is_workflow_parameter );
( is_data_input || ( input.value && input.value.__class__ == 'RuntimeValue' && !input.linked ) ) && ( step.collapsed = false );
input.value && input.value.__class__ == 'RuntimeValue' && ( input.value = null );
input.flavor = 'workflow';
if ( !is_data_input && input.type !== 'hidden' && !is_workflow_parameter ) {
if ( input.optional || ( Utils.validate( input.value ) && input.value !== '' ) ) {
input.collapsible_value = input.value;
input.collapsible_preview = true;
}
});
};
visitor( step.inputs );
FormData.matchContext( step.inputs, 'data_ref', function( input, reference ) {
input.is_workflow = ( reference.linked && !reference.linked.startsWith( 'data' ) ) || self._isWorkflowParameter( input.value );
}
});
}
});
Expand Down Expand Up @@ -148,11 +145,13 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
$wp_input.addClass( wp_cls ).css({ 'color': wp_color, 'border-color': wp_color });
}
_.each( this.steps, function( step, i ) {
_.each( step.inputs, function( input ) {
var form = self.forms[ i ];
FormData.visitInputs( step.inputs, function( name, input ) {
var wp_name = self._isWorkflowParameter( input.value );
var input_id = form.data.match( name );
if ( wp_name ) {
var wp_field = self.forms[ i ].field_list[ input.id ];
var wp_element = self.forms[ i ].element_list[ input.id ];
var wp_field = form.field_list[ input_id ];
var wp_element = form.element_list[ input_id ];
wp_fields[ wp_name ] = wp_fields[ wp_name ] || [];
wp_fields[ wp_name ].push( wp_field );
wp_field.value( wp_name );
Expand Down Expand Up @@ -281,20 +280,23 @@ define([ 'utils/utils', 'mvc/ui/ui-misc', 'mvc/form/form-view', 'mvc/form/form-d
var input_id = form.data.match( job_input_id );
var input_field = form.field_list[ input_id ];
var input_def = form.input_list[ input_id ];
if ( String( step_type ).startsWith( 'data' ) ) {
validated = input_value && input_value.values && input_value.values.length > 0;
} else {
validated = input_def.optional || ( input_def.is_workflow && input_value !== '' ) || ( !input_def.is_workflow && input_value !== null );
}
if ( !validated ) {
form.highlight( input_id );
break;
if ( !input_def.linked ) {
if ( step_type.startsWith( 'data' ) ) {
validated = input_value && input_value.values && input_value.values.length > 0;
} else {
validated = input_def.optional || ( input_def.is_workflow && input_value !== '' ) || ( !input_def.is_workflow && input_value !== null );
}
if ( !validated ) {
form.highlight( input_id );
break;
}
job_def.inputs[ step_id ] = job_def.inputs[ step_id ] || {};
job_def.inputs[ step_id ][ job_input_id ] = job_inputs[ job_input_id ];
}
}
if ( !validated ) {
break;
}
job_def.inputs[ step_id ] = job_inputs;
}
if ( !validated ) {
self._enabled( true );
Expand Down
2 changes: 1 addition & 1 deletion client/galaxy/scripts/mvc/tool/tool-form-workflow.js
Expand Up @@ -49,7 +49,7 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
if ( input.type ) {
if ( [ 'data', 'data_collection' ].indexOf( input.type ) != -1 ) {
input.type = 'hidden';
input.info = 'Data input \'' + input.name + '\' (' + Utils.textify( input.extensions && input.extensions.toString() ) + ')';
input.info = 'Data input \'' + input.name + '\' (' + Utils.textify( input.extensions ) + ')';
input.value = { '__class__': 'RuntimeValue' };
} else {
input.collapsible_value = { '__class__': 'RuntimeValue' };
Expand Down

0 comments on commit d554895

Please sign in to comment.