1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/0d44e35432ab/ Changeset: 0d44e35432ab User: guerler Date: 2014-10-16 16:43:39+00:00 Summary: ToolForm: Move dictionary building methods from mako to api. Affected #: 15 files diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 client/galaxy/scripts/mvc/tools/tools-content.js --- a/client/galaxy/scripts/mvc/tools/tools-content.js +++ b/client/galaxy/scripts/mvc/tools/tools-content.js @@ -22,7 +22,7 @@ // get history summary Utils.get({ - url : self.base_url + '?deleted=false', + url : self.base_url + '?deleted=false&state=ok', success : function(response) { // backup summary self.summary = response; diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 client/galaxy/scripts/mvc/tools/tools-form.js --- a/client/galaxy/scripts/mvc/tools/tools-form.js +++ b/client/galaxy/scripts/mvc/tools/tools-form.js @@ -27,10 +27,8 @@ this.modal = new Ui.Modal.View(); } - // link model/inputs and all options - this.options = options; - this.model = options.model; - this.inputs = options.model.inputs; + // link options + this.options = options; // set element this.setElement('<div/>'); @@ -53,9 +51,13 @@ // reset input element list, which contains the dom elements of each input element (includes also the input field) this.element_list = {}; - // initialize contents + // for now the initial tool model is parsed through the mako + this.model = this.options; + this.inputs = this.options.inputs; + + // request history content and build form this.content = new ToolContent({ - history_id : this.options.history_id, + history_id : self.options.history_id, success : function() { self._buildForm(); } @@ -89,6 +91,51 @@ console.debug('tools-form::refresh() - Recreated data structure. Refresh.'); }, + // build tool model through api call + _buildModel: function() { + // link this + var self = this; + + // construct url + var model_url = galaxy_config.root + 'api/tools/' + this.options.id + '/build?'; + if (this.options.job_id) { + model_url += 'job_id=' + this.options.job_id; + } else { + if (this.options.dataset_id) { + model_url += 'dataset_id=' + this.options.dataset_id; + } else { + var loc = top.location.href; + var pos = loc.indexOf('?'); + if (loc.indexOf('tool_id=') != -1 && pos !== -1) { + model_url += loc.slice(pos + 1); + } + } + } + + // get initial model + Utils.request({ + type : 'GET', + url : model_url, + success : function(response) { + // link model data update options + self.options = $.extend(self.options, response); + self.model = response; + self.inputs = response.inputs; + + // log success + console.debug('tools-form::initialize() - Initial tool model ready.'); + console.debug(response); + + // build form + self._buildForm(); + }, + error : function(response) { + console.debug('tools-form::initialize() - Initial tool model request failed.'); + console.debug(response); + } + }); + }, + // refresh form data _refreshForm: function() { // link this @@ -111,7 +158,7 @@ // post job Utils.request({ type : 'GET', - url : galaxy_config.root + 'tool_runner/index?tool_id=' + this.options.id + '&form_refresh=True', + url : galaxy_config.root + 'api/tools/' + this.options.id + '/build', data : current_state, success : function(response) { console.debug('tools-form::_refreshForm() - Refreshed inputs/states.'); diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 client/galaxy/scripts/mvc/tools/tools-select-content.js --- a/client/galaxy/scripts/mvc/tools/tools-select-content.js +++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js @@ -106,17 +106,17 @@ value : function (dict) { // update current value if (dict !== undefined) { - if (dict.values.length > 0 && dict.values[0] && dict.values[0].src) { + try { + // set source + this.current = dict.values[0].src; + this.refresh(); + // create list var list = []; for (var i in dict.values) { list.push(dict.values[i].id); } - // set source - this.current = dict.values[0].src; - this.refresh(); - // identify select element switch(this.current) { case 'hda': @@ -126,6 +126,8 @@ this.select_collection.value(list[0]); break; } + } catch (err) { + console.debug('tools-select-content::value() - Skipped.'); } } diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/tools/__init__.py --- a/lib/galaxy/tools/__init__.py +++ b/lib/galaxy/tools/__init__.py @@ -2175,7 +2175,7 @@ for expanded_incoming in expanded_incomings: state, state_new = self.__fetch_state( trans, expanded_incoming, history, all_pages=all_pages ) all_states.append( state ) - if state_new and "form_refresh" not in incoming: + if state_new: # This feels a bit like a hack. It allows forcing full processing # of inputs even when there is no state in the incoming dictionary # by providing either 'runtool_btn' (the name of the submit button @@ -2358,7 +2358,7 @@ message='Your upload was interrupted. If this was uninentional, please retry it.', refresh_frames=[], cont=None ) - def populate_state( self, trans, inputs, state, incoming, history, source, prefix="", context=None ): + def populate_state( self, trans, inputs, state, incoming, history=None, source="html", prefix="", context=None ): errors = dict() # Push this level onto the context stack context = ExpressionContext( state, context ) diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/webapps/galaxy/api/tools.py --- a/lib/galaxy/webapps/galaxy/api/tools.py +++ b/lib/galaxy/webapps/galaxy/api/tools.py @@ -10,8 +10,13 @@ from galaxy.visualization.genomes import GenomeRegion from galaxy.util.json import dumps from galaxy.visualization.data_providers.genome import * - +from galaxy.tools.parameters import params_to_incoming +from galaxy.tools.parameters import visit_input_values +from galaxy.tools.parameters.meta import expand_meta_parameters from galaxy.managers.collections_util import dictify_dataset_collection_instance +from galaxy.model import HistoryDatasetAssociation +from galaxy.util.expressions import ExpressionContext +from collections import Iterable import galaxy.queue_worker @@ -61,6 +66,15 @@ tool = self._get_tool( id ) return tool.to_dict( trans, io_details=io_details, link_details=link_details ) + @_future_expose_api_anonymous + def build( self, trans, id, **kwd ): + """ + GET /api/tools/{tool_id}/build + Returns a tool model including dynamic parameters and updated values, repeats block etc. + """ + tool = self._get_tool( id ) + return self._build_dict(trans, tool, kwd) + @_future_expose_api @web.require_admin def reload( self, trans, tool_id, **kwd ): @@ -464,3 +478,174 @@ dataset_dict[ 'id' ] = trans.security.encode_id( dataset_dict[ 'id' ] ) dataset_dict[ 'track_config' ] = self.get_new_track_config( trans, output_dataset ) return dataset_dict + + def _build_dict(self, trans, tool, kwd={}): + """ + Recursively creates a tool dictionary containing repeats, dynamic options and updated states. + """ + job_id = kwd.get('job_id', None) + dataset_id = kwd.get('dataset_id', None) + + # load job details if provided + job = None + if job_id: + try: + job_id = trans.security.decode_id( job_id ) + job = trans.sa_session.query( trans.app.model.Job ).get( job_id ) + except Exception, exception: + trans.response.status = 500 + return { 'error': 'Failed to retrieve job.' } + elif dataset_id: + try: + dataset_id = trans.security.decode_id( dataset_id ) + data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id ) + if not ( trans.user_is_admin() or trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), data.dataset ) ): + trans.response.status = 500 + return { 'error': 'User has no access to dataset.' } + job = data.creating_job + if not job: + trans.response.status = 500 + return { 'error': 'Creating job not found.' } + except Exception, exception: + trans.response.status = 500 + return { 'error': 'Failed to get job information.' } + + # check if job was identified + if job: + try: + job_params = job.get_param_values( trans.app, ignore_errors = True ) + job_messages = tool.check_and_update_param_values( job_params, trans, update_values=False ) + params_to_incoming( kwd, tool.inputs, job_params, trans.app ) + except Exception, exception: + trans.response.status = 500 + return { 'error': str( exception ) } + + # create parameter object + params = galaxy.util.Params( kwd, sanitize = False ) + + # convert value to jsonifiable value + def convert(v): + # check if value is numeric + isnumber = False + try: + float(v) + isnumber = True + except Exception: + pass + + # fix hda parsing + if isinstance(v, HistoryDatasetAssociation): + return { + 'id' : trans.security.encode_id(v.id), + 'src' : 'hda' + } + elif isinstance(v, basestring) or isnumber: + return v + else: + return None + + # ensures that input dictionary is jsonifiable + def sanitize(dict): + # get current value + value = dict['value'] if 'value' in dict else None + + # identify lists + if dict['type'] == 'data': + if isinstance(value, list): + value = [ convert(v) for v in value ] + else: + value = [ convert(value) ] + value = { + 'batch' : dict['multiple'], + 'values' : value + } + elif isinstance(value, list): + value = [ convert(v) for v in value ] + else: + value = convert(value) + + # update and return + dict['value'] = value + return dict + + # build model + def iterate(group_inputs, inputs, tool_state, errors, other_values=None): + other_values = ExpressionContext( tool_state, other_values ) + for input_index, input in enumerate( inputs.itervalues() ): + # create model dictionary + group_inputs[input_index] = input.to_dict(trans) + + # identify stat for subsection/group + group_state = tool_state[input.name] + + # iterate and update values + if input.type == 'repeat': + group_cache = group_inputs[input_index]['cache'] = {} + for i in range( len( group_state ) ): + group_cache[i] = {} + group_errors = errors[input.name][i] if input.name in errors else dict() + iterate( group_cache[i], input.inputs, group_state[i], group_errors, other_values ) + elif input.type == 'conditional': + # TODO: loop over all cases + try: + test_param = group_inputs[input_index]['test_param'] + test_param['value'] = group_state[test_param['name']] + except Exception: + pass + i = group_state['__current_case__'] + group_errors = errors.get( input.name, {} ) + iterate(group_inputs[input_index]['cases'][i]['inputs'], input.cases[i].inputs, group_state, group_errors, other_values) + else: + # create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options + try: + group_inputs[input_index] = input.to_dict(trans, other_values=other_values) + except Exception: + pass + + # update input value from tool state + try: + group_inputs[input_index]['value'] = tool_state[group_inputs[input_index]['name']] + except Exception: + pass + + # sanitize if value exists + if group_inputs[input_index]['value']: + group_inputs[input_index] = sanitize(group_inputs[input_index]) + + # do param translation here, used by datasource tools + if tool.input_translator: + tool.input_translator.translate( params ) + + # create tool state + state = tool.new_state(trans, all_pages=True) + errors = tool.populate_state( trans, tool.inputs, state.inputs, params.__dict__ ) + + # create basic tool model + tool_model = tool.to_dict(trans) + tool_model['inputs'] = {} + + # build tool model + iterate(tool_model['inputs'], tool.inputs, state.inputs, errors, '') + + # load tool help + tool_help = '' + if tool.help: + tool_help = tool.help + tool_help = tool_help.render( static_path=web.url_for( '/static' ), host_url=web.url_for('/', qualified=True) ) + if type( tool_help ) is not unicode: + tool_help = unicode( tool_help, 'utf-8') + + # check if citations exist + tool_citations = False + if tool.citations: + tool_citations = True + + # add additional properties + tool_model.update({ + 'help' : tool_help, + 'citations' : tool_citations, + 'biostar_url' : trans.app.config.biostar_url + }) + + # return enriched tool model + return tool_model diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/webapps/galaxy/buildapp.py --- a/lib/galaxy/webapps/galaxy/buildapp.py +++ b/lib/galaxy/webapps/galaxy/buildapp.py @@ -180,6 +180,7 @@ webapp.mapper.resource( 'ftp_file', 'ftp_files', path_prefix='/api' ) webapp.mapper.resource( 'group', 'groups', path_prefix='/api' ) webapp.mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' ) + webapp.mapper.connect( '/api/tools/{id:.+?}/build', action='build', controller="tools" ) webapp.mapper.connect( '/api/tools/{id:.+?}/reload', action='reload', controller="tools" ) webapp.mapper.connect( '/api/tools/{id:.+?}/citations', action='citations', controller="tools" ) webapp.mapper.connect( '/api/tools/{id:.+?}/download', action='download', controller="tools" ) diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/webapps/galaxy/controllers/tool_runner.py --- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py +++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py @@ -60,9 +60,6 @@ # so the default selected option should be the most recent version of the tool. The following # check will mae sure this occurs. refreshed_on_change = kwd.get( 'refresh', False ) - # This is the new tool forms equivalent to the 'refresh' parameter of the classic tool form - form_refresh = kwd.get( 'form_refresh', False ) - process_state = "populate" if form_refresh else "update" tool_version_select_field, tools, tool = self.__get_tool_components( tool_id, tool_version=None, get_loaded_tools_by_lineage=False, @@ -90,7 +87,7 @@ # We may be visiting Galaxy for the first time ( e.g., sending data from UCSC ), # so make sure to create a new history if we've never had one before. history = tool.get_default_history_by_trans( trans, create=True ) - template, vars = tool.handle_input( trans, params.__dict__, process_state=process_state) + template, vars = tool.handle_input( trans, params.__dict__ ) if len( params ) > 0: trans.log_event( "Tool params: %s" % ( str( params ) ), tool_id=tool_id ) add_frame = AddFrameData() @@ -98,8 +95,6 @@ if from_noframe is not None: add_frame.wiki_url = trans.app.config.wiki_url add_frame.from_noframe = True - if form_refresh: - template = "tool_form_refresh.mako" return trans.fill_template( template, history=history, toolbox=self.get_toolbox(), diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/mvc/tools/tools-content.js --- a/static/scripts/mvc/tools/tools-content.js +++ b/static/scripts/mvc/tools/tools-content.js @@ -22,7 +22,7 @@ // get history summary Utils.get({ - url : self.base_url + '?deleted=false', + url : self.base_url + '?deleted=false&state=ok', success : function(response) { // backup summary self.summary = response; diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/mvc/tools/tools-form.js --- a/static/scripts/mvc/tools/tools-form.js +++ b/static/scripts/mvc/tools/tools-form.js @@ -27,10 +27,8 @@ this.modal = new Ui.Modal.View(); } - // link model/inputs and all options - this.options = options; - this.model = options.model; - this.inputs = options.model.inputs; + // link options + this.options = options; // set element this.setElement('<div/>'); @@ -53,9 +51,13 @@ // reset input element list, which contains the dom elements of each input element (includes also the input field) this.element_list = {}; - // initialize contents + // for now the initial tool model is parsed through the mako + this.model = this.options; + this.inputs = this.options.inputs; + + // request history content and build form this.content = new ToolContent({ - history_id : this.options.history_id, + history_id : self.options.history_id, success : function() { self._buildForm(); } @@ -89,6 +91,51 @@ console.debug('tools-form::refresh() - Recreated data structure. Refresh.'); }, + // build tool model through api call + _buildModel: function() { + // link this + var self = this; + + // construct url + var model_url = galaxy_config.root + 'api/tools/' + this.options.id + '/build?'; + if (this.options.job_id) { + model_url += 'job_id=' + this.options.job_id; + } else { + if (this.options.dataset_id) { + model_url += 'dataset_id=' + this.options.dataset_id; + } else { + var loc = top.location.href; + var pos = loc.indexOf('?'); + if (loc.indexOf('tool_id=') != -1 && pos !== -1) { + model_url += loc.slice(pos + 1); + } + } + } + + // get initial model + Utils.request({ + type : 'GET', + url : model_url, + success : function(response) { + // link model data update options + self.options = $.extend(self.options, response); + self.model = response; + self.inputs = response.inputs; + + // log success + console.debug('tools-form::initialize() - Initial tool model ready.'); + console.debug(response); + + // build form + self._buildForm(); + }, + error : function(response) { + console.debug('tools-form::initialize() - Initial tool model request failed.'); + console.debug(response); + } + }); + }, + // refresh form data _refreshForm: function() { // link this @@ -111,7 +158,7 @@ // post job Utils.request({ type : 'GET', - url : galaxy_config.root + 'tool_runner/index?tool_id=' + this.options.id + '&form_refresh=True', + url : galaxy_config.root + 'api/tools/' + this.options.id + '/build', data : current_state, success : function(response) { console.debug('tools-form::_refreshForm() - Refreshed inputs/states.'); diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/mvc/tools/tools-select-content.js --- a/static/scripts/mvc/tools/tools-select-content.js +++ b/static/scripts/mvc/tools/tools-select-content.js @@ -106,17 +106,17 @@ value : function (dict) { // update current value if (dict !== undefined) { - if (dict.values.length > 0 && dict.values[0] && dict.values[0].src) { + try { + // set source + this.current = dict.values[0].src; + this.refresh(); + // create list var list = []; for (var i in dict.values) { list.push(dict.values[i].id); } - // set source - this.current = dict.values[0].src; - this.refresh(); - // identify select element switch(this.current) { case 'hda': @@ -126,6 +126,8 @@ this.select_collection.value(list[0]); break; } + } catch (err) { + console.debug('tools-select-content::value() - Skipped.'); } } diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/packed/mvc/tools/tools-content.js --- a/static/scripts/packed/mvc/tools/tools-content.js +++ b/static/scripts/packed/mvc/tools/tools-content.js @@ -1,1 +1,1 @@ -define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.base_url=galaxy_config.root+"api/histories/"+c.history_id+"/contents";this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:b.base_url+"?deleted=false",success:function(e){b.summary=e;b.summary.sort(function(g,f){return g.hid>f.hid?-1:(g.hid<f.hid?1:0)});console.debug("tools-content::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-content::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-content::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];var g="dataset";if(c.src=="hdca"){g="dataset_collection"}for(var d in this.summary){var e=this.summary[d];var f=false;for(var d in c.extensions){if(this._matchType(c.extensions[d],e.extension)){f=true;break}}if((e.history_content_type===g)&&(f||!c.extensions)){b.push(e)}}return b},get:function(b){return _.findWhere(this.summary,b)||{}},getDetails:function(b){if(!b.id||b.id==="null"){b.success&&b.success();return}var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){b.success&&b.success();console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-content::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})}); \ No newline at end of file +define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.base_url=galaxy_config.root+"api/histories/"+c.history_id+"/contents";this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:b.base_url+"?deleted=false&state=ok",success:function(e){b.summary=e;b.summary.sort(function(g,f){return g.hid>f.hid?-1:(g.hid<f.hid?1:0)});console.debug("tools-content::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-content::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-content::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];var g="dataset";if(c.src=="hdca"){g="dataset_collection"}for(var d in this.summary){var e=this.summary[d];var f=false;for(var d in c.extensions){if(this._matchType(c.extensions[d],e.extension)){f=true;break}}if((e.history_content_type===g)&&(f||!c.extensions)){b.push(e)}}return b},get:function(b){return _.findWhere(this.summary,b)||{}},getDetails:function(b){if(!b.id||b.id==="null"){b.success&&b.success();return}var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){b.success&&b.success();console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-content::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})}); \ No newline at end of file diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/packed/mvc/tools/tools-form.js --- a/static/scripts/packed/mvc/tools/tools-form.js +++ b/static/scripts/packed/mvc/tools/tools-form.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,h,l,j,a,e,d,f,k,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.model=n.model;this.inputs=n.model.inputs;this.setElement("<div/>");$(this.container).append(this.$el);this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.content=new f({history_id:this.options.history_id,success:function(){m._buildForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_refreshForm:function(){var m=this;var n=this.tree.finalize({data:function(o){if(o.values.length>0&&o.values[0]&&o.values[0].src==="hda"){return m.content.get({id:o.values[0].id}).dataset_id}return null}});console.debug("tools-form::_refreshForm() - Refreshing inputs/states.");console.debug(n);i.request({type:"GET",url:galaxy_config.root+"tool_runner/index?tool_id="+this.options.id+"&form_refresh=True",data:n,success:function(o){console.debug("tools-form::_refreshForm() - Refreshed inputs/states.");console.debug(o)},error:function(o){console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(o)}})},_buildForm:function(){var n=this;var p=new l.ButtonMenu({icon:"fa-gear",tooltip:"Click to see a list of options."});if(this.options.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+n.options.id)}});if(Galaxy.currUser.get("is_admin")){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.section=new k.View(n,{inputs:this.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new h.View({icon:"fa-wrench",title:"<b>"+this.model.name+"</b> "+this.model.description,operations:{menu:p},buttons:{execute:new l.Button({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){n.job_handler.submit()}})}});this.$el.append(this.portlet.$el);if(this.options.help!=""){this.$el.append(d.help(this.options.help))}if(this.options.citations){this.$el.append(d.citations());var m=new j.ToolCitationCollection();m.tool_id=this.options.id;var o=new a.CitationListView({collection:m});o.render();m.fetch()}this.portlet.append(this.section.$el);this.refresh()}});return{View:b}}); \ No newline at end of file +define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,h,l,j,a,e,d,f,k,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.model=this.options;this.inputs=this.options.inputs;this.content=new f({history_id:m.options.history_id,success:function(){m._buildForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_buildModel:function(){var m=this;var n=galaxy_config.root+"api/tools/"+this.options.id+"/build?";if(this.options.job_id){n+="job_id="+this.options.job_id}else{if(this.options.dataset_id){n+="dataset_id="+this.options.dataset_id}else{var o=top.location.href;var p=o.indexOf("?");if(o.indexOf("tool_id=")!=-1&&p!==-1){n+=o.slice(p+1)}}}i.request({type:"GET",url:n,success:function(q){m.options=$.extend(m.options,q);m.model=q;m.inputs=q.inputs;console.debug("tools-form::initialize() - Initial tool model ready.");console.debug(q);m._buildForm()},error:function(q){console.debug("tools-form::initialize() - Initial tool model request failed.");console.debug(q)}})},_refreshForm:function(){var m=this;var n=this.tree.finalize({data:function(o){if(o.values.length>0&&o.values[0]&&o.values[0].src==="hda"){return m.content.get({id:o.values[0].id}).dataset_id}return null}});console.debug("tools-form::_refreshForm() - Refreshing inputs/states.");console.debug(n);i.request({type:"GET",url:galaxy_config.root+"api/tools/"+this.options.id+"/build",data:n,success:function(o){console.debug("tools-form::_refreshForm() - Refreshed inputs/states.");console.debug(o)},error:function(o){console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(o)}})},_buildForm:function(){var n=this;var p=new l.ButtonMenu({icon:"fa-gear",tooltip:"Click to see a list of options."});if(this.options.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+n.options.id)}});if(Galaxy.currUser.get("is_admin")){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.section=new k.View(n,{inputs:this.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new h.View({icon:"fa-wrench",title:"<b>"+this.model.name+"</b> "+this.model.description,operations:{menu:p},buttons:{execute:new l.Button({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){n.job_handler.submit()}})}});this.$el.append(this.portlet.$el);if(this.options.help!=""){this.$el.append(d.help(this.options.help))}if(this.options.citations){this.$el.append(d.citations());var m=new j.ToolCitationCollection();m.tool_id=this.options.id;var o=new a.CitationListView({collection:m});o.render();m.fetch()}this.portlet.append(this.section.$el);this.refresh()}});return{View:b}}); \ No newline at end of file diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/packed/mvc/tools/tools-select-content.js --- a/static/scripts/packed/mvc/tools/tools-select-content.js +++ b/static/scripts/packed/mvc/tools/tools-select-content.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.content.filterType({src:"hda",extensions:h.extensions});var k=[];for(var j in l){k.push({label:l[j].hid+": "+l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.content.filterType({src:"hdca",extensions:h.extensions});var f=[];for(var j in m){f.push({label:m[j].hid+": "+m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(k){if(k!==undefined){if(k.values.length>0&&k.values[0]&&k.values[0].src){var j=[];for(var g in k.values){j.push(k.values[g].id)}this.current=k.values[0].src;this.refresh();switch(this.current){case"hda":this.select_datasets.value(j);break;case"hdca":this.select_collection.value(j[0]);break}}}var h=this._select().value();if(!(h instanceof Array)){h=[h]}var f={batch:!this.options.multiple,values:[]};for(var g in h){f.values.push({id:h[g],src:this.current})}return f},validate:function(){return this._select().validate()},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}},_select:function(){switch(this.current){case"hdca":return this.select_collection;default:return this.select_datasets}}});return{View:d}}); \ No newline at end of file +define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.content.filterType({src:"hda",extensions:h.extensions});var k=[];for(var j in l){k.push({label:l[j].hid+": "+l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.content.filterType({src:"hdca",extensions:h.extensions});var f=[];for(var j in m){f.push({label:m[j].hid+": "+m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(l){if(l!==undefined){try{this.current=l.values[0].src;this.refresh();var k=[];for(var g in l.values){k.push(l.values[g].id)}switch(this.current){case"hda":this.select_datasets.value(k);break;case"hdca":this.select_collection.value(k[0]);break}}catch(j){console.debug("tools-select-content::value() - Skipped.")}}var h=this._select().value();if(!(h instanceof Array)){h=[h]}var f={batch:!this.options.multiple,values:[]};for(var g in h){f.values.push({id:h[g],src:this.current})}return f},validate:function(){return this._select().validate()},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}},_select:function(){switch(this.current){case"hdca":return this.select_collection;default:return this.select_datasets}}});return{View:d}}); \ No newline at end of file diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 templates/webapps/galaxy/tool_form.mako --- a/templates/webapps/galaxy/tool_form.mako +++ b/templates/webapps/galaxy/tool_form.mako @@ -1,16 +1,27 @@ <%inherit file="/base.mako"/> -## initialize configuration -<%namespace name="tool_form_refresh" file="./webapps/galaxy/tool_form_refresh.mako" import="*" /> -${tool_form_refresh.init()} - ## new tool form +<% + ## TEMPORARY: create tool dictionary in mako while both tool forms are in use. + ## This avoids making two separate requests since the classic form requires the mako anyway. + from galaxy.webapps.galaxy.api.tools import ToolsController + controller = ToolsController(trans.app) + params = dict(trans.request.params) + if 'id' in params: + params['dataset_id'] = params['id'] + self.form_config = controller._build_dict(trans, tool, params) + self.form_config.update({ + 'id' : tool.id, + 'job_id' : trans.security.encode_id( job.id ) if job else None, + 'history_id' : trans.security.encode_id( trans.history.id ) + }) +%> ${h.js("libs/bibtex", "libs/jquery/jquery-ui")} ${h.css('base', 'jquery-ui/smoothness/jquery-ui')} <script> require(['mvc/tools/tools-form'], function(ToolsForm){ $(function(){ - var form = new ToolsForm.View(${ h.dumps(tool_form_refresh.form_config) }); + var form = new ToolsForm.View(${ h.dumps(self.form_config) }); }); }); </script> diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 templates/webapps/galaxy/tool_form_refresh.mako --- a/templates/webapps/galaxy/tool_form_refresh.mako +++ /dev/null @@ -1,138 +0,0 @@ -<%def name="init()"> -<% - ## create basic tool model - tool_model = tool.to_dict(trans) - tool_model['inputs'] = {} - - ## convert value to jsonifiable value - def convert(v): - # check if value is numeric - isnumber = False - try: - float(v) - isnumber = True - except Exception: - pass - - ## fix hda parsing - if isinstance(v, HistoryDatasetAssociation): - return { - 'id' : trans.security.encode_id(v.id), - 'src' : 'hda' - } - elif isinstance(v, basestring) or isnumber: - return v - else: - return None - - ## ensures that input dictionary is jsonifiable - from collections import Iterable - from galaxy.model import HistoryDatasetAssociation - def sanitize(dict): - ## quotations for Infinity so its jsonifiable - for name in dict: - if dict[name] == Infinity: - dict[name] = 'Infinity' - - ## get current value - value = dict['value'] if 'value' in dict else None - - ## identify lists - if dict['type'] == 'data': - if isinstance(value, list): - value = [ convert(v) for v in value ] - else: - value = [ convert(value) ] - value = { - 'batch' : dict['multiple'], - 'values' : value - } - elif isinstance(value, list): - value = [ convert(v) for v in value ] - else: - value = convert(value) - - ## update and return - dict['value'] = value - return dict - - ## build model - def build(group_inputs, inputs, tool_state, errors, other_values=None): - from galaxy.util.expressions import ExpressionContext - other_values = ExpressionContext( tool_state, other_values ) - for input_index, input in enumerate( inputs.itervalues() ): - ## create model dictionary - group_inputs[input_index] = input.to_dict(trans) - - ## identify stat for subsection/group - group_state = tool_state[input.name] - - ## iterate and update values - if input.type == "repeat": - group_cache = group_inputs[input_index]['cache'] = {} - for i in range( len( group_state ) ): - group_cache[i] = {} - group_errors = errors[input.name][i] if input.name in errors else dict() - build( group_cache[i], input.inputs, group_state[i], group_errors, other_values ) - elif input.type == "conditional": - try: - test_param = group_inputs[input_index]['test_param'] - test_param['value'] = group_state[test_param['name']] - except Exception: - pass - i = group_state['__current_case__'] - group_errors = errors.get( input.name, {} ) - build(group_inputs[input_index]['cases'][i]['inputs'], input.cases[i].inputs, group_state, group_errors, other_values) - else: - ## create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options - try: - group_inputs[input_index] = input.to_dict(trans, other_values=other_values) - except Exception: - pass - - ## update input value from tool state - try: - group_inputs[input_index]['value'] = tool_state[group_inputs[input_index]['name']] - group_inputs[input_index] = sanitize(group_inputs[input_index]) - except Exception: - pass - endif - endfor - build(tool_model['inputs'], tool.inputs, tool_state.inputs, errors, "") - - # load tool help - tool_help = '' - if tool.help: - if tool.has_multiple_pages: - tool_help = tool.help_by_page[tool_state.page] - else: - tool_help = tool.help - - # Help is Mako template, so render using current static path. - tool_help = tool_help.render( static_path=h.url_for( '/static' ), host_url=h.url_for('/', qualified=True) ) - - # Convert to unicode to display non-ascii characters. - if type( tool_help ) is not unicode: - tool_help = unicode( tool_help, 'utf-8') - endif - - # check if citations exist - tool_citations = False - if tool.citations: - tool_citations = True - - # form configuration - self.form_config = { - 'id' : tool.id, - 'model' : tool_model, - 'help' : tool_help, - 'citations' : tool_citations, - 'biostar_url' : trans.app.config.biostar_url, - 'history_id' : trans.security.encode_id( trans.history.id ), - 'job_id' : trans.security.encode_id( job.id ) if job else None - } -%> -</%def> - -${ init() } -${ h.dumps(self.form_config) } \ No newline at end of file Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.