galaxy-commits
Threads by month
- ----- 2025 -----
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
January 2015
- 2 participants
- 248 discussions
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4ceb95d03fc6/
Changeset: 4ceb95d03fc6
User: dannon
Date: 2015-01-07 19:51:11+00:00
Summary: Slightly bump the width of the Message field for bug reports.
Affected #: 1 file
diff -r 8c57fc528cb7255ab11d20b03b5dd8509e3ea5a0 -r 4ceb95d03fc6554aad5d63e5ab8be6da948121e8 templates/webapps/galaxy/dataset/errors.mako
--- a/templates/webapps/galaxy/dataset/errors.mako
+++ b/templates/webapps/galaxy/dataset/errors.mako
@@ -99,7 +99,7 @@
</div><div class="form-row"><label>Message</label>
- <textarea name="message" rows="10" cols="40"></textarea>
+ <textarea name="message" rows="10" cols="60"></textarea></div><div class="form-row"><input type="submit" name="submit_error_report" value="Report" onclick="return sendReport( this, this.form, '_self' );"/>
https://bitbucket.org/galaxy/galaxy-central/commits/23fddbbd5153/
Changeset: 23fddbbd5153
User: dannon
Date: 2015-01-07 19:51:24+00:00
Summary: Strip whitespace.
Affected #: 1 file
diff -r 4ceb95d03fc6554aad5d63e5ab8be6da948121e8 -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e templates/webapps/galaxy/dataset/errors.mako
--- a/templates/webapps/galaxy/dataset/errors.mako
+++ b/templates/webapps/galaxy/dataset/errors.mako
@@ -32,7 +32,7 @@
{
form.elements[i].disabled = true;
}
-
+
}
var hiddenInput = document.createElement('input');
hiddenInput.type = 'hidden';
@@ -52,7 +52,7 @@
<p><b>Dataset ${hda.hid}: ${hda.display_name() | h}</b></p><% job = hda.creating_job %>
%if job:
-
+
%if job.traceback:
The Galaxy framework encountered the following error while attempting to run the tool:
<pre>${ util.unicodify( job.traceback ) | h}</pre>
@@ -82,8 +82,8 @@
%><h2>Report this error to the Galaxy Team</h2><p>
- The Galaxy team regularly reviews errors that occur in the application.
- However, if you would like to provide additional information (such as
+ The Galaxy team regularly reviews errors that occur in the application.
+ However, if you would like to provide additional information (such as
what you were trying to do when the error occurred) and a contact e-mail
address, we will be better able to investigate your problem and get back
to you.
https://bitbucket.org/galaxy/galaxy-central/commits/85e8fb54b285/
Changeset: 85e8fb54b285
User: dannon
Date: 2015-01-12 13:59:51+00:00
Summary: Merge.
Affected #: 62 files
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/galaxy.workflow_editor.canvas.js
--- a/client/galaxy/scripts/galaxy.workflow_editor.canvas.js
+++ b/client/galaxy/scripts/galaxy.workflow_editor.canvas.js
@@ -805,7 +805,7 @@
nodeView.addDataOutput( output );
} );
nodeView.render();
- workflow.node_changed( this );
+ workflow.node_changed( this, true);
},
update_field_data : function( data ) {
var node = this;
@@ -1094,9 +1094,9 @@
this.active_node = node;
}
},
- node_changed : function ( node ) {
+ node_changed : function ( node, force ) {
this.has_changes = true;
- if ( this.active_node == node ) {
+ if ( this.active_node == node && (!parent.__NEWTOOLFORM__ || force)) {
// Reactive with new form_html
this.check_changes_in_active_form(); //Force changes to be saved even on new connection (previously dumped)
parent.show_form_for_tool( node.form_html + node.tooltip, node );
@@ -1305,6 +1305,12 @@
return node;
}
+function update_node( data ) {
+ var node = workflow.active_node;
+ if (node) {
+ node.update_field_data(data, true);
+ }
+}
var ext_to_type = null;
var type_to_type = null;
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/tools/tools-form-base.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -0,0 +1,315 @@
+/**
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
+define(['utils/utils', 'utils/deferred', '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'],
+ function(Utils, Deferred, Portlet, Ui, CitationModel, CitationView,
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree) {
+
+ // create form view
+ return Backbone.View.extend({
+ // initialize
+ initialize: function(options) {
+ // log options
+ console.debug(options);
+
+ // link galaxy modal or create one
+ var galaxy = parent.Galaxy;
+ if (galaxy && galaxy.modal) {
+ this.modal = galaxy.modal;
+ } else {
+ this.modal = new Ui.Modal.View();
+ }
+
+ // check if the user is an admin
+ if (galaxy && galaxy.currUser) {
+ this.is_admin = galaxy.currUser.get('is_admin');
+ } else {
+ this.is_admin = false;
+ }
+
+ // link options
+ this.options = options;
+
+ // link container
+ this.container = this.options.container || 'body';
+
+ // create deferred processing queue handler
+ // this handler reduces the number of requests to the api by filtering redundant requests
+ this.deferred = new Deferred();
+
+ // set element
+ this.setElement('<div/>');
+
+ // add to main element
+ $(this.container).append(this.$el);
+
+ // build this form
+ this._buildForm();
+ },
+
+ /** Shows the final message (usually upon successful job submission)
+ */
+ reciept: function($el) {
+ $(this.container).empty();
+ $(this.container).append($el);
+ },
+
+ /** Highlight and scroll to input element (currently only used for error notifications)
+ */
+ highlight: function (input_id, message, silent) {
+ // get input field
+ var input_element = this.element_list[input_id];
+
+ // check input element
+ if (input_element) {
+ // mark error
+ input_element.error(message || 'Please verify this parameter.');
+
+ // scroll to first input element
+ if (!silent) {
+ $(this.container).animate({
+ scrollTop: input_element.$el.offset().top - 20
+ }, 500);
+ }
+ }
+ },
+
+ /** Main tool form build function. This function is called once a new model is available.
+ */
+ _buildForm: function() {
+ // link this
+ var self = this;
+
+ // reset events
+ this.off('refresh');
+ this.off('reset');
+
+ // reset field list, which contains the input field elements
+ this.field_list = {};
+
+ // reset sequential input definition list, which contains the input definitions as provided from the api
+ this.input_list = {};
+
+ // reset input element list, which contains the dom elements of each input element (includes also the input field)
+ this.element_list = {};
+
+ // creates a tree/json data structure from the input form
+ this.tree = new ToolTree(this);
+
+ // request history content and build form
+ this.content = new ToolContent(this);
+
+ // link model options
+ var options = this.options;
+
+ // create ui elements
+ this._renderForm(options);
+
+ // rebuild the underlying data structure
+ this.tree.finalize();
+
+ // show errors
+ if (!this.workflow && options.errors) {
+ var error_messages = this.tree.matchResponse(options.errors);
+ for (var input_id in error_messages) {
+ this.highlight(input_id, error_messages[input_id], true);
+ }
+ }
+
+ // add refresh listener
+ this.on('refresh', function() {
+ // by using/reseting the deferred ajax queue the number of redundant calls is reduced
+ self.deferred.reset();
+ self.deferred.execute(function(){self._updateModel()});
+ });
+
+ // add reset listener
+ this.on('reset', function() {
+ for (var i in this.element_list) {
+ this.element_list[i].reset();
+ }
+ });
+ },
+
+ /** Renders the UI elements required for the form
+ */
+ _renderForm: function(options) {
+ // link this
+ var self = this;
+
+ // create message view
+ this.message = new Ui.Message();
+
+ // button for version selection
+ var requirements_button = new Ui.ButtonIcon({
+ icon : 'fa-info-circle',
+ title : 'Requirements',
+ tooltip : 'Display tool requirements',
+ onclick : function() {
+ if (!this.visible) {
+ this.visible = true;
+ self.message.update({
+ persistent : true,
+ message : ToolTemplate.requirements(options),
+ status : 'info'
+ });
+ } else {
+ this.visible = false;
+ self.message.update({
+ message : ''
+ });
+ }
+ }
+ });
+ if (!options.requirements || options.requirements.length == 0) {
+ requirements_button.$el.hide();
+ }
+
+ // button for version selection
+ var versions_button = new Ui.ButtonMenu({
+ icon : 'fa-cubes',
+ title : 'Versions',
+ tooltip : 'Select another tool version'
+ });
+ if (options.versions && options.versions.length > 1) {
+ for (var i in options.versions) {
+ var version = options.versions[i];
+ if (version != options.version) {
+ versions_button.addMenu({
+ title : 'Switch to ' + version,
+ version : version,
+ icon : 'fa-cube',
+ onclick : function() {
+ // here we update the tool version (some tools encode the version also in the id)
+ options.id = options.id.replace(options.version, this.version);
+ options.version = this.version;
+
+ // rebuild the model and form
+ self.deferred.reset();
+ self.deferred.execute(function(){self._buildModel()});
+ }
+ });
+ }
+ }
+ } else {
+ versions_button.$el.hide();
+ }
+
+ // button menu
+ var menu_button = new Ui.ButtonMenu({
+ icon : 'fa-caret-down',
+ title : 'Options',
+ tooltip : 'View available options'
+ });
+
+ // configure button selection
+ if(options.biostar_url) {
+ // add question option
+ menu_button.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu_button.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(options.biostar_url + '/t/' + options.id + '/');
+ }
+ });
+ };
+
+ // create share button
+ menu_button.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=' + options.id);
+ }
+ });
+
+ // add admin operations
+ if (this.is_admin) {
+ // create download button
+ menu_button.addMenu({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + options.id + '/download';
+ }
+ });
+ }
+
+ // create tool form section
+ this.section = new ToolSection.View(self, {
+ inputs : options.inputs,
+ cls : 'ui-table-plain'
+ });
+
+ // switch to classic tool form mako if the form definition is incompatible
+ if (this.incompatible) {
+ this.$el.hide();
+ $('#tool-form-classic').show();
+ return;
+ }
+
+ // create portlet
+ this.portlet = new Portlet.View({
+ icon : 'fa-wrench',
+ title : '<b>' + options.name + '</b> ' + options.description + ' (Galaxy Tool Version ' + options.version + ')',
+ cls : 'ui-portlet-slim',
+ operations: {
+ requirements : requirements_button,
+ menu : menu_button,
+ versions : versions_button
+ },
+ buttons : this.buttons
+ });
+
+ // append message
+ this.portlet.append(this.message.$el, true);
+
+ // append tool section
+ this.portlet.append(this.section.$el);
+
+ // start form
+ this.$el.empty();
+ this.$el.append(this.portlet.$el);
+
+ // append help
+ if (options.help != '') {
+ this.$el.append(ToolTemplate.help(options.help));
+ }
+
+ // append citations
+ if (options.citations) {
+ var $citations = $('<div/>');
+ var citations = new CitationModel.ToolCitationCollection();
+ citations.tool_id = options.id;
+ var citation_list_view = new CitationView.CitationListView({ el: $citations, collection: citations } );
+ citation_list_view.render();
+ citations.fetch();
+ this.$el.append($citations);
+ }
+
+ // show message if available in model
+ if (options.message) {
+ this.message.update({
+ persistent : true,
+ status : 'warning',
+ message : options.message
+ });
+ }
+ }
+ });
+});
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/tools/tools-form-workflow.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -0,0 +1,66 @@
+/**
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
+define(['utils/utils', 'mvc/tools/tools-form-base'],
+ function(Utils, ToolFormBase) {
+
+ // create form view
+ var View = ToolFormBase.extend({
+ initialize: function(options) {
+ this.workflow = true;
+ ToolFormBase.prototype.initialize.call(this, options);
+ },
+
+ /** Builds a new model through api call and recreates the entire form
+ */
+ _buildModel: function() {
+ },
+
+ /** Request a new model for an already created tool form and updates the form inputs
+ */
+ _updateModel: function() {
+ // create the request dictionary
+ var self = this;
+ var current_state = this.tree.finalize();
+
+ // log tool state
+ console.debug('tools-form-workflow::_refreshForm() - Refreshing states.');
+ console.debug(current_state);
+
+ // register process
+ var process_id = this.deferred.register();
+
+ // build model url for request
+ var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id;
+
+ // post job
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ data : current_state,
+ success : function(node) {
+ parent.update_node(node);
+
+ // process completed
+ self.deferred.done(process_id);
+
+ // log success
+ console.debug('tools-form::_refreshForm() - States refreshed.');
+ console.debug(node);
+ },
+ error : function(response) {
+ // process completed
+ self.deferred.done(process_id);
+
+ // log error
+ console.debug('tools-form::_refreshForm() - Refresh request failed.');
+ console.debug(response);
+ }
+ });
+ }
+ });
+
+ return {
+ View: View
+ };
+});
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 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
@@ -1,79 +1,28 @@
/**
This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
*/
-define(['utils/utils', 'utils/deferred', '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(Utils, Deferred, Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/tools/tools-form-base', 'mvc/tools/tools-jobs'],
+ function(Utils, Ui, ToolFormBase, ToolJobs) {
// create form view
- var View = Backbone.View.extend({
- // base element
- container: 'body',
-
+ var View = ToolFormBase.extend({
// initialize
initialize: function(options) {
- // log options
- console.debug(options);
-
- // link galaxy modal or create one
- var galaxy = parent.Galaxy;
- if (galaxy && galaxy.modal) {
- this.modal = galaxy.modal;
- } else {
- this.modal = new Ui.Modal.View();
+ var self = this;
+ this.job_handler = new ToolJobs(this);
+ this.buttons = {
+ execute : new Ui.Button({
+ icon : 'fa-check',
+ tooltip : 'Execute: ' + options.name,
+ title : 'Execute',
+ cls : 'btn btn-primary',
+ floating : 'clear',
+ onclick : function() {
+ self.job_handler.submit();
+ }
+ })
}
-
- // check if the user is an admin
- if (galaxy && galaxy.currUser) {
- this.is_admin = galaxy.currUser.get('is_admin')
- } else {
- this.is_admin = false;
- }
-
- // link options
- this.options = options;
-
- // create deferred processing queue handler
- // this handler reduces the number of requests to the api by filtering redundant requests
- this.deferred = new Deferred();
-
- // set element
- this.setElement('<div/>');
-
- // add to main element
- $(this.container).append(this.$el);
-
- // build this form
- this._buildForm();
- },
-
- /** Shows the final message (usually upon successful job submission)
- */
- reciept: function($el) {
- $(this.container).empty();
- $(this.container).append($el);
- },
-
- /** Highlight and scroll to input element (currently only used for error notifications)
- */
- highlight: function (input_id, message, silent) {
- // get input field
- var input_element = this.element_list[input_id];
-
- // check input element
- if (input_element) {
- // mark error
- input_element.error(message || 'Please verify this parameter.');
-
- // scroll to first input element
- if (!silent) {
- $(this.container).animate({
- scrollTop: input_element.$el.offset().top - 20
- }, 500);
- }
- }
+ ToolFormBase.prototype.initialize.call(this, options);
},
/** Builds a new model through api call and recreates the entire form
@@ -250,256 +199,6 @@
console.debug(response);
}
});
- },
-
- /** Main tool form build function. This function is called once a new model is available.
- */
- _buildForm: function() {
- // link this
- var self = this;
-
- // reset events
- this.off('refresh');
- this.off('reset');
-
- // reset field list, which contains the input field elements
- this.field_list = {};
-
- // reset sequential input definition list, which contains the input definitions as provided from the api
- this.input_list = {};
-
- // reset input element list, which contains the dom elements of each input element (includes also the input field)
- this.element_list = {};
-
- // creates a tree/json data structure from the input form
- this.tree = new ToolTree(this);
-
- // creates the job handler
- this.job_handler = new ToolJobs(this);
-
- // request history content and build form
- this.content = new ToolContent(this);
-
- // link model options
- var options = this.options;
-
- // create ui elements
- this._renderForm(options);
-
- // rebuild the underlying data structure
- this.tree.finalize();
-
- // show errors
- if (options.errors) {
- var error_messages = this.tree.matchResponse(options.errors);
- for (var input_id in error_messages) {
- this.highlight(input_id, error_messages[input_id], true);
- }
- }
-
- // add refresh listener
- this.on('refresh', function() {
- // by using/reseting the deferred ajax queue the number of redundant calls is reduced
- self.deferred.reset();
- self.deferred.execute(function(){self._updateModel()});
- });
-
- // add reset listener
- this.on('reset', function() {
- for (var i in this.element_list) {
- this.element_list[i].reset();
- }
- });
- },
-
- /** Renders the UI elements required for the form
- */
- _renderForm: function(options) {
- // link this
- var self = this;
-
- // create message view
- this.message = new Ui.Message();
-
- // button for version selection
- var requirements_button = new Ui.ButtonIcon({
- icon : 'fa-info-circle',
- title : 'Requirements',
- tooltip : 'Display tool requirements',
- onclick : function() {
- if (!this.visible) {
- this.visible = true;
- self.message.update({
- persistent : true,
- message : ToolTemplate.requirements(options),
- status : 'info'
- });
- } else {
- this.visible = false;
- self.message.update({
- message : ''
- });
- }
- }
- });
- if (!options.requirements || options.requirements.length == 0) {
- requirements_button.$el.hide();
- }
-
- // button for version selection
- var versions_button = new Ui.ButtonMenu({
- icon : 'fa-cubes',
- title : 'Versions',
- tooltip : 'Select another tool version'
- });
- if (options.versions && options.versions.length > 1) {
- for (var i in options.versions) {
- var version = options.versions[i];
- if (version != options.version) {
- versions_button.addMenu({
- title : 'Switch to ' + version,
- version : version,
- icon : 'fa-cube',
- onclick : function() {
- // here we update the tool version (some tools encode the version also in the id)
- options.id = options.id.replace(options.version, this.version);
- options.version = this.version;
-
- // rebuild the model and form
- self.deferred.reset();
- self.deferred.execute(function(){self._buildModel()});
- }
- });
- }
- }
- } else {
- versions_button.$el.hide();
- }
-
- // button menu
- var menu_button = new Ui.ButtonMenu({
- icon : 'fa-caret-down',
- title : 'Options',
- tooltip : 'View available options'
- });
-
- // configure button selection
- if(options.biostar_url) {
- // add question option
- menu_button.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu_button.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(options.biostar_url + '/t/' + options.id + '/');
- }
- });
- };
-
- // create share button
- menu_button.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=' + options.id);
- }
- });
-
- // add admin operations
- if (this.is_admin) {
- // create download button
- menu_button.addMenu({
- icon : 'fa-download',
- title : 'Download',
- tooltip : 'Download this tool',
- onclick : function() {
- window.location.href = galaxy_config.root + 'api/tools/' + options.id + '/download';
- }
- });
- }
-
- // create tool form section
- this.section = new ToolSection.View(self, {
- inputs : options.inputs,
- cls : 'ui-table-plain'
- });
-
- // switch to classic tool form mako if the form definition is incompatible
- if (this.incompatible) {
- this.$el.hide();
- $('#tool-form-classic').show();
- return;
- }
-
- // create portlet
- this.portlet = new Portlet.View({
- icon : 'fa-wrench',
- title : '<b>' + options.name + '</b> ' + options.description + ' (Galaxy Tool Version ' + options.version + ')',
- cls : 'ui-portlet-slim',
- operations: {
- requirements : requirements_button,
- menu : menu_button,
- versions : versions_button
- },
- buttons: {
- execute : new Ui.Button({
- icon : 'fa-check',
- tooltip : 'Execute: ' + options.name,
- title : 'Execute',
- cls : 'btn btn-primary',
- floating : 'clear',
- onclick : function() {
- self.job_handler.submit();
- }
- })
- }
- });
-
- // append message
- this.portlet.append(this.message.$el, true);
-
- // append tool section
- this.portlet.append(this.section.$el);
-
- // start form
- this.$el.empty();
- this.$el.append(this.portlet.$el);
-
- // append help
- if (options.help != '') {
- this.$el.append(ToolTemplate.help(options.help));
- }
-
- // append citations
- if (options.citations) {
- var $citations = $('<div/>');
- var citations = new CitationModel.ToolCitationCollection();
- citations.tool_id = options.id;
- var citation_list_view = new CitationView.CitationListView({ el: $citations, collection: citations } );
- citation_list_view.render();
- citations.fetch();
- this.$el.append($citations);
- }
-
- // show message if available in model
- if (options.message) {
- this.message.update({
- persistent : true,
- status : 'warning',
- message : options.message
- });
- }
}
});
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/tools/tools-jobs.js
--- a/client/galaxy/scripts/mvc/tools/tools-jobs.js
+++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js
@@ -98,7 +98,7 @@
}
// validate non-optional fields
- if (!input_def.optional && input_field.validate && !input_field.validate()) {
+ if (!input_def.optional && input_value == null) {
this.app.highlight(input_id);
return false;
}
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -382,6 +382,11 @@
/** Data input field
*/
_fieldData : function(input_def) {
+ if (this.app.workflow) {
+ var extensions = Utils.textify(input_def.extensions.toString());
+ input_def.info = 'Data input \'' + input_def.name + '\' (' + extensions + ')';
+ return this._fieldHidden(input_def);
+ }
var self = this;
return new SelectContent.View(this.app, {
id : 'field-' + input_def.id,
@@ -398,6 +403,14 @@
/** Select/Checkbox/Radio options field
*/
_fieldSelect : function (input_def) {
+ // show text field in workflow
+ if (this.app.workflow && input_def.is_dynamic) {
+ if (!Utils.validate(input_def.value)) {
+ input_def.value = '';
+ }
+ return this._fieldText(input_def);
+ }
+
// configure options fields
var options = [];
for (var i in input_def.options) {
@@ -475,7 +488,8 @@
*/
_fieldHidden : function(input_def) {
return new Ui.Hidden({
- id : 'field-' + input_def.id
+ id : 'field-' + input_def.id,
+ info : input_def.info
});
},
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 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
@@ -36,14 +36,7 @@
this.list = {};
// error messages
- var extensions = options.extensions.toString();
- if (extensions) {
- extensions = extensions.replace(/,/g, ', ');
- var pos = extensions.lastIndexOf(', ');
- if (pos != -1) {
- extensions = extensions.substr(0, pos) + ' or ' + extensions.substr(pos+1);
- }
- }
+ var extensions = Utils.textify(options.extensions);
var hda_error = 'No dataset available.';
if (extensions) {
hda_error = 'No ' + extensions + ' dataset available.';
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/tools/tools-tree.js
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -2,7 +2,7 @@
This class maps the tool form dom to an api compatible javascript dictionary.
*/
// dependencies
-define([], function() {
+define(['utils/utils'], function(Utils) {
// tool form tree
return Backbone.Model.extend({
@@ -120,7 +120,7 @@
// handle default value
if (!field.skip) {
- if (input.optional && field.validate && !field.validate()) {
+ if (field.validate && !field.validate(value)) {
value = null;
}
add (job_input_id, input.id, value);
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/ui/ui-misc.js
--- a/client/galaxy/scripts/mvc/ui/ui-misc.js
+++ b/client/galaxy/scripts/mvc/ui/ui-misc.js
@@ -412,7 +412,7 @@
initialize : function(options) {
// configure options
this.options = options;
-
+
// create new element
this.setElement(this._template(this.options));
@@ -425,14 +425,20 @@
// value
value : function (new_val) {
if (new_val !== undefined) {
- this.$el.val(new_val);
+ this.$('hidden').val(new_val);
}
- return this.$el.val();
+ return this.$('hidden').val();
},
// element
_template: function(options) {
- return '<hidden id="' + options.id + '" value="' + options.value + '"/>';
+ var tmpl = '<div id="' + options.id + '" >';
+ if (options.info) {
+ tmpl += '<label>' + options.info + '</label>';
+ }
+ tmpl += '<hidden value="' + options.value + '"/>' +
+ '</div>';
+ return tmpl;
}
});
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/ui/ui-options.js
--- a/client/galaxy/scripts/mvc/ui/ui-options.js
+++ b/client/galaxy/scripts/mvc/ui/ui-options.js
@@ -137,16 +137,7 @@
/** Validate the selected option/options
*/
validate: function() {
- var current = this.value();
- if (!(current instanceof Array)) {
- current = [current];
- }
- for (var i in current) {
- if ([null, 'null', undefined].indexOf(current[i]) > -1) {
- return false;
- }
- }
- return true;
+ return Utils.validate(this.value());
},
/** Wait message during request processing
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/ui/ui-select-default.js
--- a/client/galaxy/scripts/mvc/ui/ui-select-default.js
+++ b/client/galaxy/scripts/mvc/ui/ui-select-default.js
@@ -96,16 +96,7 @@
/** Validate the current selection
*/
validate: function() {
- var current = this.value();
- if (!(current instanceof Array)) {
- current = [current];
- }
- for (var i in current) {
- if ([null, 'null', undefined].indexOf(current[i]) > -1) {
- return false;
- }
- }
- return true;
+ return Utils.validate(this.value());
},
/** Return the label/text of the current selection
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/mvc/upload/upload-view.js
--- a/client/galaxy/scripts/mvc/upload/upload-view.js
+++ b/client/galaxy/scripts/mvc/upload/upload-view.js
@@ -104,7 +104,7 @@
});
// define location
- $('#left .unified-panel-header-inner').append((new UploadButton.View(this.ui_button)).$el);
+ $('.with-upload-button').append((new UploadButton.View(this.ui_button)).$el);
// load extension
var self = this;
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 client/galaxy/scripts/utils/utils.js
--- a/client/galaxy/scripts/utils/utils.js
+++ b/client/galaxy/scripts/utils/utils.js
@@ -15,6 +15,40 @@
};
/**
+ * Validate atomic values or list of values
+ * usually used for selectable options
+ * @param{String} value - Value or list to be validated
+ */
+function validate (value) {
+ if (!(value instanceof Array)) {
+ value = [value];
+ }
+ for (var i in value) {
+ if (['None', null, 'null', undefined, 'undefined'].indexOf(value[i]) > -1) {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+ * Convert list to pretty string
+ * @param{String} lst - List of strings to be converted in human readable list sentence
+ */
+function textify(lst) {
+ var lst = lst.toString();
+ if (lst) {
+ lst = lst.replace(/,/g, ', ');
+ var pos = lst.lastIndexOf(', ');
+ if (pos != -1) {
+ lst = lst.substr(0, pos) + ' or ' + lst.substr(pos+1);
+ }
+ return lst;
+ }
+ return '';
+};
+
+/**
* Request handler for GET
* @param{String} url - Url request is made to
* @param{Function} success - Callback on success
@@ -212,7 +246,9 @@
time: time,
wrap: wrap,
request: request,
- sanitize: sanitize
+ sanitize: sanitize,
+ textify: textify,
+ validate: validate
};
});
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 config/datatypes_conf.xml.sample
--- a/config/datatypes_conf.xml.sample
+++ b/config/datatypes_conf.xml.sample
@@ -181,7 +181,8 @@
<datatype extension="taxonomy" type="galaxy.datatypes.tabular:Taxonomy" display_in_upload="true"/><datatype extension="tabular" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true" description="Any data in tab delimited format (tabular)." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Tabular_.28tab_delimited.29"/><datatype extension="twobit" type="galaxy.datatypes.binary:TwoBit" mimetype="application/octet-stream" display_in_upload="true"/>
- <datatype extension="sqlite" type="galaxy.datatypes.binary:SQlite" mimetype="application/octet-stream" display_in_upload="true"/>
+ <datatype extension="sqlite" type="galaxy.datatypes.binary:SQlite" mimetype="application/octet-stream" display_in_upload="true"/>
+ <datatype extension="gemini.sqlite" type="galaxy.datatypes.binary:GeminiSQLite" mimetype="application/octet-stream" display_in_upload="True" /><datatype extension="txt" type="galaxy.datatypes.data:Text" display_in_upload="true" description="Any text file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Plain_text"/><datatype extension="linecount" type="galaxy.datatypes.data:LineCount" display_in_upload="false"/><datatype extension="memexml" type="galaxy.datatypes.xml:MEMEXml" mimetype="application/xml" display_in_upload="true"/>
@@ -271,6 +272,7 @@
--><sniffer type="galaxy.datatypes.tabular:Vcf"/><sniffer type="galaxy.datatypes.binary:TwoBit"/>
+ <sniffer type="galaxy.datatypes.binary:GeminiSQLite"/><sniffer type="galaxy.datatypes.binary:SQlite"/><sniffer type="galaxy.datatypes.binary:Bam"/><sniffer type="galaxy.datatypes.binary:Sff"/>
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -20,7 +20,7 @@
from bx.seq.twobit import TWOBIT_MAGIC_NUMBER, TWOBIT_MAGIC_NUMBER_SWAP, TWOBIT_MAGIC_SIZE
from galaxy.util import sqlite
-from galaxy.datatypes.metadata import MetadataElement,ListParameter,DictParameter
+from galaxy.datatypes.metadata import MetadataElement, MetadataParameter, ListParameter, DictParameter
from galaxy.datatypes import metadata
import dataproviders
@@ -640,8 +640,66 @@
return dataproviders.dataset.SQliteDataDictProvider( dataset_source, **settings )
+#Binary.register_sniffable_binary_format("sqlite", "sqlite", SQlite)
+
+
+class GeminiSQLite( SQlite ):
+ """Class describing a Gemini Sqlite database """
+ MetadataElement( name="gemini_version", default='0.10.0' , param=MetadataParameter, desc="Gemini Version",
+ readonly=True, visible=True, no_value='0.10.0' )
+ file_ext = "gemini.sqlite"
+
+ def set_meta( self, dataset, overwrite = True, **kwd ):
+ super( GeminiSQLite, self ).set_meta( dataset, overwrite = overwrite, **kwd )
+ try:
+ conn = sqlite.connect( dataset.file_name )
+ c = conn.cursor()
+ tables_query = "SELECT version FROM version"
+ result = c.execute( tables_query ).fetchall()
+ for version, in result:
+ dataset.metadata.gemini_version = version
+ # TODO: Can/should we detect even more attributes, such as use of PED file, what was input annotation type, etc.
+ except Exception, e:
+ log.warn( '%s, set_meta Exception: %s', self, e )
+
+ def sniff( self, filename ):
+ if super( GeminiSQLite, self ).sniff( filename ):
+ gemini_table_names = [ "gene_detailed", "gene_summary", "resources", "sample_genotype_counts", "sample_genotypes", "samples",
+ "variant_impacts", "variants", "version" ]
+ try:
+ conn = sqlite.connect( filename )
+ c = conn.cursor()
+ tables_query = "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name"
+ result = c.execute( tables_query ).fetchall()
+ result = map( lambda x: x[0], result )
+ for table_name in gemini_table_names:
+ if table_name not in result:
+ return False
+ return True
+ except Exception, e:
+ log.warn( '%s, sniff Exception: %s', self, e )
+ return False
+
+ def set_peek( self, dataset, is_multi_byte=False ):
+ if not dataset.dataset.purged:
+ dataset.peek = "Gemini SQLite Database, version %s" % ( dataset.metadata.gemini_version or 'unknown' )
+ dataset.blurb = data.nice_size( dataset.get_size() )
+ else:
+ dataset.peek = 'file does not exist'
+ dataset.blurb = 'file purged from disk'
+
+ def display_peek( self, dataset ):
+ try:
+ return dataset.peek
+ except:
+ return "Gemini SQLite Database, version %s" % ( dataset.metadata.gemini_version or 'unknown' )
+
+Binary.register_sniffable_binary_format( "gemini.sqlite", "gemini.sqlite", GeminiSQLite )
+# FIXME: We need to register gemini.sqlite before sqlite, since register_sniffable_binary_format and is_sniffable_binary called in upload.py
+# ignores sniff order declared in datatypes_conf.xml
Binary.register_sniffable_binary_format("sqlite", "sqlite", SQlite)
+
class Xlsx(Binary):
"""Class for Excel 2007 (xlsx) files"""
file_ext="xlsx"
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -33,7 +33,7 @@
from galaxy.tools.actions.data_source import DataSourceToolAction
from galaxy.tools.actions.data_manager import DataManagerToolAction
from galaxy.tools.deps import build_dependency_manager
-from galaxy.tools.parameters import check_param, params_from_strings, params_to_strings
+from galaxy.tools.parameters import params_to_incoming, check_param, params_from_strings, params_to_strings
from galaxy.tools.parameters import output_collect
from galaxy.tools.parameters.basic import (BaseURLToolParameter,
DataToolParameter, HiddenToolParameter, LibraryDatasetToolParameter,
@@ -1843,7 +1843,8 @@
"""Return a list of commands to be run to populate the current environment to include this tools requirements."""
return self.app.toolbox.dependency_manager.dependency_shell_commands(
self.requirements,
- installed_tool_dependencies=self.installed_tool_dependencies
+ installed_tool_dependencies=self.installed_tool_dependencies,
+ tool_dir=self.tool_dir,
)
@property
@@ -2072,6 +2073,336 @@
return tool_dict
+ def to_json (self, trans, **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
+ log.error('Failed to retrieve job.')
+ 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
+ log.error('User has no access to dataset.')
+ return { 'error': 'User has no access to dataset.' }
+ job = data.creating_job
+ if not job:
+ trans.response.status = 500
+ log.error('Creating job not found.')
+ return { 'error': 'Creating job not found.' }
+ except Exception, exception:
+ trans.response.status = 500
+ log.error('Failed to get job information.')
+ return { 'error': 'Failed to get job information.' }
+
+ # load job parameters into incoming
+ tool_message = ''
+ if job:
+ try:
+ job_params = job.get_param_values( trans.app, ignore_errors = True )
+ job_messages = self.check_and_update_param_values( job_params, trans, update_values=False )
+ tool_message = self._compare_tool_version(trans, job)
+ params_to_incoming( kwd, self.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 jsonify(v):
+ # check if value is numeric
+ isnumber = False
+ try:
+ float(v)
+ isnumber = True
+ except Exception:
+ pass
+
+ # fix hda parsing
+ if isinstance(v, trans.app.model.HistoryDatasetAssociation):
+ return {
+ 'id' : trans.security.encode_id(v.id),
+ 'src' : 'hda'
+ }
+ elif isinstance(v, bool):
+ if v is True:
+ return 'true'
+ else:
+ return 'false'
+ 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
+
+ # jsonify by type
+ if dict['type'] in ['data']:
+ if isinstance(value, list):
+ value = [ jsonify(v) for v in value ]
+ else:
+ value = [ jsonify(value) ]
+ value = { 'values': value }
+ elif isinstance(value, list):
+ value = [ jsonify(v) for v in value ]
+ else:
+ value = jsonify(value)
+
+ # update and return
+ dict['value'] = value
+ return dict
+
+ # initialize state using default parameters
+ def initialize_state(trans, inputs, state, context=None):
+ context = ExpressionContext(state, context)
+ for input in inputs.itervalues():
+ state[input.name] = input.get_initial_value(trans, context)
+
+ # check the current state of a value and update it if necessary
+ def check_state(trans, input, default_value, context):
+ value = default_value
+ error = 'State validation failed.'
+ try:
+ # resolves the inconsistent definition of boolean parameters (see base.py) without modifying shared code
+ if input.type == 'boolean' and isinstance(default_value, basestring):
+ value, error = [util.string_as_bool(default_value), None]
+ else:
+ value, error = check_param(trans, input, default_value, context)
+ except Exception, err:
+ log.error('Checking parameter failed. %s', str(err))
+ pass
+ return [value, error]
+
+ # populates state with incoming url parameters
+ def populate_state(trans, inputs, state, errors, incoming, prefix="", context=None ):
+ context = ExpressionContext(state, context)
+ for input in inputs.itervalues():
+ key = prefix + input.name
+ if input.type == 'repeat':
+ group_state = state[input.name]
+ rep_index = 0
+ del group_state[:]
+ while True:
+ rep_name = "%s_%d" % (key, rep_index)
+ if not any([incoming_key.startswith(rep_name) for incoming_key in incoming.keys()]):
+ break
+ if rep_index < input.max:
+ new_state = {}
+ new_state['__index__'] = rep_index
+ initialize_state(trans, input.inputs, new_state, context)
+ group_state.append(new_state)
+ populate_state(trans, input.inputs, new_state, errors, incoming, prefix=rep_name + "|", context=context)
+ rep_index += 1
+ elif input.type == 'conditional':
+ group_state = state[input.name]
+ group_prefix = "%s|" % ( key )
+ test_param_key = group_prefix + input.test_param.name
+ default_value = incoming.get(test_param_key, group_state.get(input.test_param.name, None))
+ value, error = check_state(trans, input.test_param, default_value, context)
+ if error:
+ errors[test_param_key] = error
+ else:
+ try:
+ current_case = input.get_current_case(value, trans)
+ group_state = state[input.name] = {}
+ initialize_state(trans, input.cases[current_case].inputs, group_state, context)
+ populate_state( trans, input.cases[current_case].inputs, group_state, errors, incoming, prefix=group_prefix, context=context)
+ group_state['__current_case__'] = current_case
+ except Exception, e:
+ errors[test_param_key] = 'The selected case is unavailable/invalid.'
+ pass
+ group_state[input.test_param.name] = value
+ else:
+ default_value = incoming.get(key, state.get(input.name, None))
+ value, error = check_state(trans, input, default_value, context)
+ if error:
+ errors[key] = error
+ state[input.name] = value
+
+ # builds tool model including all attributes
+ def iterate(group_inputs, inputs, state_inputs, other_values=None):
+ other_values = ExpressionContext( state_inputs, other_values )
+ for input_index, input in enumerate( inputs.itervalues() ):
+ # create model dictionary
+ tool_dict = input.to_dict(trans)
+ if tool_dict is None:
+ continue
+
+ # state for subsection/group
+ group_state = state_inputs[input.name]
+
+ # iterate and update values
+ if input.type == 'repeat':
+ group_cache = tool_dict['cache'] = {}
+ for i in range( len( group_state ) ):
+ group_cache[i] = {}
+ iterate( group_cache[i], input.inputs, group_state[i], other_values )
+ elif input.type == 'conditional':
+ if 'test_param' in tool_dict:
+ test_param = tool_dict['test_param']
+ test_param['value'] = jsonify(group_state[test_param['name']])
+ if '__current_case__' in group_state:
+ i = group_state['__current_case__']
+ iterate(tool_dict['cases'][i]['inputs'], input.cases[i].inputs, group_state, other_values)
+ else:
+ # create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options
+ try:
+ tool_dict = input.to_dict(trans, other_values=other_values)
+ except Exception:
+ pass
+
+ # identify name
+ input_name = tool_dict.get('name')
+ if input_name:
+ # update input value from tool state
+ if input_name in state_inputs:
+ tool_dict['value'] = state_inputs[input_name]
+
+ # sanitize if value exists
+ tool_dict = sanitize(tool_dict)
+
+ # backup final input dictionary
+ group_inputs[input_index] = tool_dict
+
+ # sanatization for the final tool state
+ def sanitize_state(state):
+ keys = None
+ if isinstance(state, dict):
+ keys = state
+ elif isinstance(state, list):
+ keys = range( len(state) )
+ if keys:
+ for k in keys:
+ if isinstance(state[k], dict) or isinstance(state[k], list):
+ sanitize_state(state[k])
+ else:
+ state[k] = jsonify(state[k])
+
+ # do param translation here, used by datasource tools
+ if self.input_translator:
+ self.input_translator.translate( params )
+
+ # initialize and populate tool state
+ state_inputs = {}
+ state_errors = {}
+ initialize_state(trans, self.inputs, state_inputs)
+ populate_state(trans, self.inputs, state_inputs, state_errors, params.__dict__)
+
+ # create basic tool model
+ tool_model = self.to_dict(trans)
+ tool_model['inputs'] = {}
+
+ # build tool model and tool state
+ iterate(tool_model['inputs'], self.inputs, state_inputs, '')
+
+ # sanitize tool state
+ sanitize_state(state_inputs)
+
+ # load tool help
+ tool_help = ''
+ if self.help:
+ tool_help = self.help
+ tool_help = tool_help.render( static_path=url_for( '/static' ), host_url=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 self.citations:
+ tool_citations = True
+
+ # get tool versions
+ tool_versions = []
+ tools = self.app.toolbox.get_loaded_tools_by_lineage(self.id)
+ for t in tools:
+ tool_versions.append(t.version)
+
+ ## add information with underlying requirements and their versions
+ tool_requirements = []
+ if self.requirements:
+ for requirement in self.requirements:
+ tool_requirements.append({
+ 'name' : requirement.name,
+ 'version' : requirement.version
+ })
+
+ # add additional properties
+ tool_model.update({
+ 'help' : tool_help,
+ 'citations' : tool_citations,
+ 'biostar_url' : trans.app.config.biostar_url,
+ 'message' : tool_message,
+ 'versions' : tool_versions,
+ 'requirements' : tool_requirements,
+ 'errors' : state_errors,
+ 'state_inputs' : state_inputs
+ })
+
+ # check for errors
+ if 'error' in tool_message:
+ return tool_message
+
+ # return enriched tool model
+ return tool_model
+
+ def _compare_tool_version( self, trans, job ):
+ """
+ Compares a tool version with the tool version from a job (from ToolRunner).
+ """
+ tool_id = job.tool_id
+ tool_version = job.tool_version
+ message = ''
+ try:
+ select_field, tools, tool = self.app.toolbox.get_tool_components( tool_id, tool_version=tool_version, get_loaded_tools_by_lineage=False, set_selected=True )
+ if tool is None:
+ trans.response.status = 500
+ return { 'error': 'This dataset was created by an obsolete tool (%s). Can\'t re-run.' % tool_id }
+ if ( self.id != tool_id and self.old_id != tool_id ) or self.version != tool_version:
+ if self.id == tool_id:
+ if tool_version == None:
+ # for some reason jobs don't always keep track of the tool version.
+ message = ''
+ else:
+ message = 'This job was initially run with tool version "%s", which is currently not available. ' % tool_version
+ if len( tools ) > 1:
+ message += 'You can re-run the job with the selected tool or choose another derivation of the tool.'
+ else:
+ message += 'You can re-run the job with this tool version, which is a derivation of the original tool.'
+ else:
+ if len( tools ) > 1:
+ message = 'This job was initially run with tool version "%s", which is currently not available. ' % tool_version
+ message += 'You can re-run the job with the selected tool or choose another derivation of the tool.'
+ else:
+ message = 'This job was initially run with tool id "%s", version "%s", which is ' % ( tool_id, tool_version )
+ message += 'currently not available. You can re-run the job with this tool, which is a derivation of the original tool.'
+ except Exception, error:
+ trans.response.status = 500
+ return { 'error': str (error) }
+
+ # can't rerun upload, external data sources, et cetera. workflow compatible will proxy this for now
+ #if not self.is_workflow_compatible:
+ # trans.response.status = 500
+ # return { 'error': 'The \'%s\' tool does currently not support re-running.' % self.name }
+ return message
+
def get_default_history_by_trans( self, trans, create=False ):
return trans.get_history( create=create )
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 lib/galaxy/tools/deps/brew_exts.py
--- a/lib/galaxy/tools/deps/brew_exts.py
+++ b/lib/galaxy/tools/deps/brew_exts.py
@@ -28,6 +28,7 @@
import os
import re
import sys
+import string
import subprocess
WHITESPACE_PATTERN = re.compile("[\s]+")
@@ -43,6 +44,7 @@
CANNOT_DETERMINE_TAP_ERROR_MESSAGE = "Cannot determine tap of specified recipe - please use fully qualified recipe (e.g. homebrew/science/samtools)."
VERBOSE = False
RELAXED = False
+BREW_ARGS = []
class BrewContext(object):
@@ -104,6 +106,7 @@
def main():
global VERBOSE
global RELAXED
+ global BREW_ARGS
parser = argparse.ArgumentParser(description=DESCRIPTION)
parser.add_argument("--brew", help="Path to linuxbrew 'brew' executable to target")
actions = ["vinstall", "vuninstall", "vdeps", "vinfo", "env"]
@@ -114,11 +117,13 @@
parser.add_argument('version', metavar='version', help="Version for action (e.g. 0.1.19).")
parser.add_argument('--relaxed', action='store_true', help="Relaxed processing - for instance allow use of env on non-vinstall-ed recipes.")
parser.add_argument('--verbose', action='store_true', help="Verbose output")
+ parser.add_argument('restargs', nargs=argparse.REMAINDER)
args = parser.parse_args()
if args.verbose:
VERBOSE = True
if args.relaxed:
RELAXED = True
+ BREW_ARGS = args.restargs
if not action:
action = args.action
brew_context = BrewContext(args)
@@ -159,7 +164,7 @@
return self.message
-def versioned_install(recipe_context, package=None, version=None):
+def versioned_install(recipe_context, package=None, version=None, installed_deps=[]):
if package is None:
package = recipe_context.recipe
version = recipe_context.version
@@ -176,10 +181,15 @@
versioned = version_info[2]
if versioned:
dep_to_version[dep] = dep_version
+ if dep in installed_deps:
+ continue
versioned_install(recipe_context, dep, dep_version)
+ installed_deps.append(dep)
else:
# Install latest.
dep_to_version[dep] = None
+ if dep in installed_deps:
+ continue
unversioned_install(dep)
try:
for dep in deps:
@@ -198,7 +208,16 @@
}
deps_metadata.append(dep_metadata)
- brew_execute(["install", package])
+ cellar_root = recipe_context.brew_context.homebrew_cellar
+ cellar_path = recipe_context.cellar_path
+ env_actions = build_env_actions(deps_metadata, cellar_root, cellar_path, custom_only=True)
+ env = EnvAction.build_env(env_actions)
+ args = ["install"]
+ if VERBOSE:
+ args.append("--verbose")
+ args.extend(BREW_ARGS)
+ args.append(package)
+ brew_execute(args, env=env)
deps = brew_execute(["deps", package])
deps = [d.strip() for d in deps.split("\n") if d]
metadata = {
@@ -278,10 +297,10 @@
pass
-def brew_execute(args):
+def brew_execute(args, env=None):
os.environ["HOMEBREW_NO_EMOJI"] = "1" # simplify brew parsing.
cmds = ["brew"] + args
- return execute(cmds)
+ return execute(cmds, env=env)
def build_env_statements_from_recipe_context(recipe_context, **kwds):
@@ -290,11 +309,20 @@
return env_statements
-def build_env_statements(cellar_root, cellar_path, relaxed=None):
+def build_env_statements(cellar_root, cellar_path, relaxed=None, custom_only=False):
deps = load_versioned_deps(cellar_path, relaxed=relaxed)
+ actions = build_env_actions(deps, cellar_root, cellar_path, relaxed, custom_only)
+ env_statements = []
+ for action in actions:
+ env_statements.extend(action.to_statements())
+ return "\n".join(env_statements)
+
+
+def build_env_actions(deps, cellar_root, cellar_path, relaxed=None, custom_only=False):
path_appends = []
ld_path_appends = []
+ actions = []
def handle_keg(cellar_path):
bin_path = os.path.join(cellar_path, "bin")
@@ -303,6 +331,14 @@
lib_path = os.path.join(cellar_path, "lib")
if os.path.isdir(lib_path):
ld_path_appends.append(lib_path)
+ env_path = os.path.join(cellar_path, "platform_environment.json")
+ if os.path.exists(env_path):
+ with open(env_path, "r") as f:
+ env_metadata = json.load(f)
+ if "actions" in env_metadata:
+ def to_action(desc):
+ return EnvAction(cellar_path, desc)
+ actions.extend(map(to_action, env_metadata["actions"]))
for dep in deps:
package = dep['name']
@@ -311,14 +347,54 @@
handle_keg( dep_cellar_path )
handle_keg( cellar_path )
- env_statements = []
- if path_appends:
- env_statements.append("PATH=" + ":".join(path_appends) + ":$PATH")
- env_statements.append("export PATH")
- if ld_path_appends:
- env_statements.append("LD_LIBRARY_PATH=" + ":".join(ld_path_appends) + ":$LD_LIBRARY_PATH")
- env_statements.append("export LD_LIBRARY_PATH")
- return "\n".join(env_statements)
+ if not custom_only:
+ if path_appends:
+ actions.append(EnvAction(cellar_path, {"action": "prepend", "variable": "PATH", "value": ":".join(path_appends)}))
+ if ld_path_appends:
+ actions.append(EnvAction(cellar_path, {"action": "prepend", "variable": "LD_LIBRARY_PATH", "value": ":".join(path_appends)}))
+ return actions
+
+
+class EnvAction(object):
+
+ def __init__(self, keg_root, action_description):
+ self.variable = action_description["variable"]
+ self.action = action_description["action"]
+ self.value = string.Template(action_description["value"]).safe_substitute({
+ 'KEG_ROOT': keg_root,
+ })
+
+ @staticmethod
+ def build_env(env_actions):
+ new_env = os.environ.copy()
+ map(lambda env_action: env_action.modify_environ(new_env), env_actions)
+ return new_env
+
+ def modify_environ(self, environ):
+ if self.action == "set" or not environ.get(self.variable, ""):
+ environ[self.variable] = self.__eval("${value}")
+ elif self.action == "prepend":
+ environ[self.variable] = self.__eval("${value}:%s" % environ[self.variable])
+ else:
+ environ[self.variable] = self.__eval("%s:${value}" % environ[self.variable])
+
+ def __eval(self, template):
+ return string.Template(template).safe_substitute(
+ variable=self.variable,
+ value=self.value,
+ )
+
+ def to_statements(self):
+ if self.action == "set":
+ template = '''${variable}="${value}"'''
+ elif self.action == "prepend":
+ template = '''${variable}="${value}:$$${variable}"'''
+ else:
+ template = '''${variable}="$$${variable}:${value}"'''
+ return [
+ self.__eval(template),
+ "export %s" % self.variable
+ ]
@contextlib.contextmanager
@@ -350,8 +426,15 @@
return execute(cmds)
-def execute(cmds):
- p = subprocess.Popen(cmds, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+def execute(cmds, env=None):
+ subprocess_kwds = dict(
+ shell=False,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ )
+ if env:
+ subprocess_kwds["env"] = env
+ p = subprocess.Popen(cmds, **subprocess_kwds)
#log = p.stdout.read()
global VERBOSE
stdout, stderr = p.communicate()
@@ -363,7 +446,10 @@
def brew_deps(package):
- stdout = brew_execute(["deps", package])
+ args = ["deps"]
+ args.extend(BREW_ARGS)
+ args.append(package)
+ stdout = brew_execute(args)
return [p.strip() for p in stdout.split("\n") if p]
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 lib/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/resolvers/brewed_tool_shed_packages.py
@@ -0,0 +1,150 @@
+"""
+This dependency resolver resolves tool shed dependencies (those defined
+tool_dependencies.xml) installed using Platform Homebrew and converted
+via shed2tap (e.g. https://github.com/jmchilton/homebrew-toolshed)
+"""
+import logging
+import os
+from xml.etree import ElementTree as ET
+
+from .resolver_mixins import (
+ UsesHomebrewMixin,
+ UsesToolDependencyDirMixin,
+ UsesInstalledRepositoriesMixin,
+)
+from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY
+
+log = logging.getLogger(__name__)
+
+
+class HomebrewToolShedDependencyResolver(
+ DependencyResolver,
+ UsesHomebrewMixin,
+ UsesToolDependencyDirMixin,
+ UsesInstalledRepositoriesMixin,
+):
+ resolver_type = "tool_shed_tap"
+
+ def __init__(self, dependency_manager, **kwds):
+ self._init_homebrew(**kwds)
+ self._init_base_path(dependency_manager, **kwds)
+
+ def resolve(self, name, version, type, **kwds):
+ if type != "package":
+ return INDETERMINATE_DEPENDENCY
+
+ if version is None:
+ return INDETERMINATE_DEPENDENCY
+
+ return self._find_tool_dependencies(name, version, type, **kwds)
+
+ def _find_tool_dependencies(self, name, version, type, **kwds):
+ installed_tool_dependency = self._get_installed_dependency(name, type, version=version, **kwds)
+ if installed_tool_dependency:
+ return self._resolve_from_installed_tool_dependency(name, version, installed_tool_dependency)
+
+ if "tool_dir" in kwds:
+ tool_directory = os.path.abspath(kwds["tool_dir"])
+ tool_depenedencies_path = os.path.join(tool_directory, "tool_dependencies.xml")
+ if os.path.exists(tool_depenedencies_path):
+ return self._resolve_from_tool_dependencies_path(name, version, tool_depenedencies_path)
+
+ return INDETERMINATE_DEPENDENCY
+
+ def _resolve_from_installed_tool_dependency(self, name, version, installed_tool_dependency):
+ tool_shed_repository = installed_tool_dependency.tool_shed_repository
+ recipe_name = build_recipe_name(
+ package_name=name,
+ package_version=version,
+ repository_owner=tool_shed_repository.owner,
+ repository_name=tool_shed_repository.name,
+ )
+ return self._find_dep_default(recipe_name, None)
+
+ def _resolve_from_tool_dependencies_path(self, name, version, tool_dependencies_path):
+ try:
+ raw_dependencies = RawDependencies(tool_dependencies_path)
+ except Exception:
+ log.debug("Failed to parse dependencies in file %s" % tool_dependencies_path)
+ return INDETERMINATE_DEPENDENCY
+
+ raw_dependency = raw_dependencies.find(name, version)
+ if not raw_dependency:
+ return INDETERMINATE_DEPENDENCY
+
+ recipe_name = build_recipe_name(
+ package_name=name,
+ package_version=version,
+ repository_owner=raw_dependency.repository_owner,
+ repository_name=raw_dependency.repository_name
+ )
+ dep = self._find_dep_default(recipe_name, None)
+ return dep
+
+
+class RawDependencies(object):
+
+ def __init__(self, dependencies_file):
+ self.root = ET.parse(dependencies_file).getroot()
+ dependencies = []
+ package_els = self.root.findall("package") or []
+ for package_el in package_els:
+ repository_el = package_el.find("repository")
+ if repository_el is None:
+ continue
+ dependency = RawDependency(self, package_el, repository_el)
+ dependencies.append(dependency)
+ self.dependencies = dependencies
+
+ def find(self, package_name, package_version):
+ target_dependency = None
+
+ for dependency in self.dependencies:
+ if dependency.package_name == package_name and dependency.package_version == package_version:
+ target_dependency = dependency
+ break
+ return target_dependency
+
+
+class RawDependency(object):
+
+ def __init__(self, dependencies, package_el, repository_el):
+ self.dependencies = dependencies
+ self.package_el = package_el
+ self.repository_el = repository_el
+
+ def __repr__(self):
+ temp = "Dependency[package_name=%s,version=%s,dependent_package=%s]"
+ return temp % (
+ self.package_el.attrib["name"],
+ self.package_el.attrib["version"],
+ self.repository_el.attrib["name"]
+ )
+
+ @property
+ def repository_owner(self):
+ return self.repository_el.attrib["owner"]
+
+ @property
+ def repository_name(self):
+ return self.repository_el.attrib["name"]
+
+ @property
+ def package_name(self):
+ return self.package_el.attrib["name"]
+
+ @property
+ def package_version(self):
+ return self.package_el.attrib["version"]
+
+
+def build_recipe_name(package_name, package_version, repository_owner, repository_name):
+ # TODO: Consider baking package_name and package_version into name? (would be more "correct")
+ owner = repository_owner.replace("-", "")
+ name = repository_name
+ name = name.replace("_", "").replace("-", "")
+ base = "%s_%s" % (owner, name)
+ return base
+
+
+__all__ = [HomebrewToolShedDependencyResolver]
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 lib/galaxy/tools/deps/resolvers/galaxy_packages.py
--- a/lib/galaxy/tools/deps/resolvers/galaxy_packages.py
+++ b/lib/galaxy/tools/deps/resolvers/galaxy_packages.py
@@ -1,12 +1,13 @@
-from os.path import join, islink, realpath, basename, exists, abspath
+from os.path import join, islink, realpath, basename, exists
from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY, Dependency
+from .resolver_mixins import UsesToolDependencyDirMixin
import logging
log = logging.getLogger( __name__ )
-class GalaxyPackageDependencyResolver(DependencyResolver):
+class GalaxyPackageDependencyResolver(DependencyResolver, UsesToolDependencyDirMixin):
resolver_type = "galaxy_packages"
def __init__(self, dependency_manager, **kwds):
@@ -16,7 +17,7 @@
## resolver that will just grab 'default' version of exact version
## unavailable.
self.versionless = str(kwds.get('versionless', "false")).lower() == "true"
- self.base_path = abspath( kwds.get('base_path', dependency_manager.default_base_path) )
+ self._init_base_path( dependency_manager, **kwds )
def resolve( self, name, version, type, **kwds ):
"""
diff -r 23fddbbd5153ba3d6c8bbbbd33fcb5aa9225f35e -r 85e8fb54b2851454a000cab23d57ce102af6aa30 lib/galaxy/tools/deps/resolvers/homebrew.py
--- a/lib/galaxy/tools/deps/resolvers/homebrew.py
+++ b/lib/galaxy/tools/deps/resolvers/homebrew.py
@@ -12,20 +12,19 @@
incompatible changes coming.
"""
-import os
-from ..brew_exts import DEFAULT_HOMEBREW_ROOT, recipe_cellar_path, build_env_statements
-from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY, Dependency
+from .resolver_mixins import UsesHomebrewMixin
+from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY
# TODO: Implement prefer version linked...
PREFER_VERSION_LINKED = 'linked'
PREFER_VERSION_LATEST = 'latest'
-UNKNOWN_PREFER_VERSION_MESSAGE_TEMPLATE = "HomebrewDependencyResolver prefer_version must be latest %s"
+UNKNOWN_PREFER_VERSION_MESSAGE_TEMPLATE = "HomebrewDependencyResolver prefer_version must be %s"
UNKNOWN_PREFER_VERSION_MESSAGE = UNKNOWN_PREFER_VERSION_MESSAGE_TEMPLATE % (PREFER_VERSION_LATEST)
DEFAULT_PREFER_VERSION = PREFER_VERSION_LATEST
-class HomebrewDependencyResolver(DependencyResolver):
+class HomebrewDependencyResolver(DependencyResolver, UsesHomebrewMixin):
resolver_type = "homebrew"
def __init__(self, dependency_manager, **kwds):
@@ -38,11 +37,7 @@
if self.versionless and self.prefer_version not in [PREFER_VERSION_LATEST]:
raise Exception(UNKNOWN_PREFER_VERSION_MESSAGE)
- cellar_root = kwds.get('cellar', None)
- if cellar_root is None:
- cellar_root = os.path.join(DEFAULT_HOMEBREW_ROOT, "Cellar")
-
- self.cellar_root = cellar_root
+ self._init_homebrew(**kwds)
def resolve(self, name, version, type, **kwds):
if type != "package":
@@ -53,41 +48,6 @@
else:
return self._find_dep_versioned(name, version)
- def _find_dep_versioned(self, name, version):
- recipe_path = recipe_cellar_path(self.cellar_root, name, version)
- if not os.path.exists(recipe_path) or not os.path.isdir(recipe_path):
- return INDETERMINATE_DEPENDENCY
-
- commands = build_env_statements(self.cellar_root, recipe_path, relaxed=True)
- return HomebrewDependency(commands)
-
- def _find_dep_default(self, name, version):
- installed_versions = self._installed_versions(name)
- if not installed_versions:
- return INDETERMINATE_DEPENDENCY
-
- # Just grab newest installed version - may make sense some day to find
- # the linked version instead.
- default_version = sorted(installed_versions, reverse=True)[0]
- return self._find_dep_versioned(name, default_version)
-
- def _installed_versions(self, recipe):
- recipe_base_path = os.path.join(self.cellar_root, recipe)
- if not os.path.exists(recipe_base_path):
- return []
-
- names = os.listdir(recipe_base_path)
- return filter(lambda n: os.path.isdir(os.path.join(recipe_base_path, n)), names)
-
-
-class HomebrewDependency(Dependency):
-
- def __init__(self, commands):
- self.commands = commands
-
- def shell_commands(self, requirement):
- return self.commands.replace("\n", ";") + "\n"
-
def _string_as_bool( value ):
return str( value ).lower() == "true"
This diff is so big that we needed to truncate the remainder.
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.
1
0

commit/galaxy-central: dannon: Merged in nsoranzo/galaxy-central (pull request #628)
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d3dff45bbb05/
Changeset: d3dff45bbb05
User: dannon
Date: 2015-01-12 12:02:23+00:00
Summary: Merged in nsoranzo/galaxy-central (pull request #628)
PEP-8 fixes and API doc ehnancements to libraries API
Affected #: 2 files
diff -r eb61b02da1866c4a7da0f2fa357ce43e6c62b57c -r d3dff45bbb0554150da4491eb2d2031d11f90063 lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -6,10 +6,7 @@
from galaxy.managers import libraries, folders, roles
from galaxy.web import _future_expose_api as expose_api
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
-from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController
-from sqlalchemy.orm.exc import MultipleResultsFound
-from sqlalchemy.orm.exc import NoResultFound
import logging
log = logging.getLogger( __name__ )
@@ -48,7 +45,7 @@
def __decode_id( self, trans, encoded_id, object_name=None ):
"""
- Try to decode the id.
+ Try to decode the id.
:param object_name: Name of the object the id belongs to. (optional)
:type object_name: str
@@ -149,7 +146,7 @@
synopsis = payload.get( 'synopsis', None )
else:
raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
- updated_library = self.library_manager.update( trans, library, name, description, synopsis )
+ updated_library = self.library_manager.update( trans, library, name, description, synopsis )
library_dict = self.library_manager.get_library_dict( trans, updated_library )
return library_dict
@@ -248,20 +245,20 @@
*POST /api/libraries/{encoded_library_id}/permissions
:param encoded_library_id: the encoded id of the library to set the permissions of
- :type encoded_library_id: an encoded id string
+ :type encoded_library_id: an encoded id string
:param action: (required) describes what action should be performed
available actions: remove_restrictions, set_permissions
- :type action: string
+ :type action: string
:param access_ids[]: list of Role.id defining roles that should have access permission on the library
- :type access_ids[]: string or list
+ :type access_ids[]: string or list
:param add_ids[]: list of Role.id defining roles that should have add item permission on the library
- :type add_ids[]: string or list
+ :type add_ids[]: string or list
:param manage_ids[]: list of Role.id defining roles that should have manage permission on the library
- :type manage_ids[]: string or list
+ :type manage_ids[]: string or list
:param modify_ids[]: list of Role.id defining roles that should have modify permission on the library
- :type modify_ids[]: string or list
+ :type modify_ids[]: string or list
:rtype: dictionary
:returns: dict of current roles for all available permission types
@@ -306,7 +303,7 @@
else:
invalid_access_roles_names.append( role_id )
if len( invalid_access_roles_names ) > 0:
- log.warning( "The following roles could not be added to the library access permission: " + str( invalid_access_roles_names ) )
+ log.warning( "The following roles could not be added to the library access permission: " + str( invalid_access_roles_names ) )
# ADD TO LIBRARY ROLES
valid_add_roles = []
@@ -319,8 +316,8 @@
else:
invalid_add_roles_names.append( role_id )
if len( invalid_add_roles_names ) > 0:
- log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) )
-
+ log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) )
+
# MANAGE LIBRARY ROLES
valid_manage_roles = []
invalid_manage_roles_names = []
@@ -332,8 +329,8 @@
else:
invalid_manage_roles_names.append( role_id )
if len( invalid_manage_roles_names ) > 0:
- log.warning( "The following roles could not be added to the manage library permission: " + str( invalid_manage_roles_names ) )
-
+ log.warning( "The following roles could not be added to the manage library permission: " + str( invalid_manage_roles_names ) )
+
# MODIFY LIBRARY ROLES
valid_modify_roles = []
invalid_modify_roles_names = []
@@ -345,7 +342,7 @@
else:
invalid_modify_roles_names.append( role_id )
if len( invalid_modify_roles_names ) > 0:
- log.warning( "The following roles could not be added to the modify library permission: " + str( invalid_modify_roles_names ) )
+ log.warning( "The following roles could not be added to the modify library permission: " + str( invalid_modify_roles_names ) )
permissions = { trans.app.security_agent.permitted_actions.LIBRARY_ACCESS : valid_access_roles }
permissions.update( { trans.app.security_agent.permitted_actions.LIBRARY_ADD : valid_add_roles } )
@@ -357,7 +354,7 @@
# Copy the permissions to the root folder
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
else:
- raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
+ raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
'Allowed values are: "remove_restrictions", set_permissions"' )
roles = self.library_manager.get_current_roles( trans, library )
return roles
@@ -369,18 +366,16 @@
POST /api/libraries/{encoded_library_id}/permissions
Updates the library permissions.
"""
- import galaxy.util
- params = galaxy.util.Params( payload )
+ params = util.Params( payload )
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
role_params = params.get( k + '_in', [] )
- in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in galaxy.util.listify( role_params ) ]
+ in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
trans.app.security_agent.set_all_library_permissions( trans, library, permissions )
trans.sa_session.refresh( library )
# Copy the permissions to the root folder
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
- message = "Permissions updated for library '%s'." % library.name
item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
return item
diff -r eb61b02da1866c4a7da0f2fa357ce43e6c62b57c -r d3dff45bbb0554150da4491eb2d2031d11f90063 lib/galaxy/webapps/galaxy/api/library_contents.py
--- a/lib/galaxy/webapps/galaxy/api/library_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/library_contents.py
@@ -29,12 +29,12 @@
.. note:: May be slow! Returns all content traversing recursively through all folders.
.. seealso:: :class:`galaxy.webapps.galaxy.api.FolderContentsController.index` for a non-recursive solution
- :param library_id: encoded id string of the library
- :type library_id: string
+ :param library_id: the encoded id of the library
+ :type library_id: str
:returns: list of dictionaries of the form:
* id: the encoded id of the library item
- * name: the 'libary path'
+ * name: the 'library path'
or relationship of the library item to the root
* type: 'file' or 'folder'
* url: the url to get detailed information on the library item
@@ -109,7 +109,7 @@
:param id: the encoded id of the library item to return
:type id: str
- :param library_id: encoded id string of the library that contains this item
+ :param library_id: the encoded id of the library that contains this item
:type library_id: str
:returns: detailed library item information
@@ -119,7 +119,7 @@
:func:`galaxy.model.LibraryDataset.to_dict` and
:attr:`galaxy.model.LibraryFolder.dict_element_visible_keys`
"""
- class_name, content_id = self.__decode_library_content_id( trans, id )
+ class_name, content_id = self.__decode_library_content_id( id )
if class_name == 'LibraryFolder':
content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessible=True )
rval = content.to_dict( view='element', value_mapper={ 'id': trans.security.encode_id } )
@@ -146,27 +146,39 @@
the HDA's encoded id in ``from_hda_id`` (and optionally ``ldda_message``).
:type library_id: str
- :param library_id: encoded id string of the library where to create the new item
+ :param library_id: the encoded id of the library where to create the new item
:type payload: dict
:param payload: dictionary structure containing:
- * folder_id: the parent folder of the new item
+ * folder_id: the encoded id of the parent folder of the new item
* create_type: the type of item to create ('file', 'folder' or 'collection')
- * from_hda_id: (optional) the id of an accessible HDA to copy into the
- library
+ * from_hda_id: (optional, only if create_type is 'file') the
+ encoded id of an accessible HDA to copy into the library
* ldda_message: (optional) the new message attribute of the LDDA created
* extended_metadata: (optional) dub-dictionary containing any extended
metadata to associate with the item
- * link_data_only: (optional) either 'copy_files' (default) or 'link_to_files'
* upload_option: (optional) one of 'upload_file' (default), 'upload_directory' or 'upload_paths'
- * server_dir: (optional) only if upload_option is 'upload_directory'
- * filesystem_paths: (optional) only if upload_option is 'upload_paths' and the user is an admin
+ * server_dir: (optional, only if upload_option is
+ 'upload_directory') relative path of the subdirectory of Galaxy
+ ``library_import_dir`` to upload. All and only the files (i.e.
+ no subdirectories) contained in the specified directory will be
+ uploaded.
+ * filesystem_paths: (optional, only if upload_option is
+ 'upload_paths' and the user is an admin) file paths on the
+ Galaxy server to upload to the library, one file per line
+ * link_data_only: (optional, only when upload_option is
+ 'upload_directory' or 'upload_paths') either 'copy_files'
+ (default) or 'link_to_files'. Setting to 'link_to_files'
+ symlinks instead of copying the files
+ * name: (optional, only if create_type is 'folder') name of the
+ folder to create
+ * description: (optional, only if create_type is 'folder')
+ description of the folder to create
:rtype: dict
:returns: a dictionary containing the id, name,
and 'show' url of the new item
"""
- create_type = None
if 'create_type' not in payload:
trans.response.status = 400
return "Missing required 'create_type' parameter."
@@ -178,10 +190,10 @@
if 'folder_id' not in payload:
trans.response.status = 400
- return "Missing requred 'folder_id' parameter."
+ return "Missing required 'folder_id' parameter."
else:
folder_id = payload.pop( 'folder_id' )
- class_name, folder_id = self.__decode_library_content_id( trans, folder_id )
+ class_name, folder_id = self.__decode_library_content_id( folder_id )
try:
# security is checked in the downstream controller
parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessible=False )
@@ -198,9 +210,7 @@
#check for extended metadata, store it and pop it out of the param
#otherwise sanitize_param will have a fit
- ex_meta_payload = None
- if 'extended_metadata' in payload:
- ex_meta_payload = payload.pop('extended_metadata')
+ ex_meta_payload = payload.pop('extended_metadata', None)
# Now create the desired content object, either file or folder.
if create_type == 'file':
@@ -272,7 +282,7 @@
def _copy_hda_to_library_folder( self, trans, from_hda_id, library_id, folder_id, ldda_message='' ):
"""
- Copies hda ``from_hda_id`` to library folder ``library_folder_id`` optionally
+ Copies hda ``from_hda_id`` to library folder ``folder_id``, optionally
adding ``ldda_message`` to the new ldda's ``message``.
``library_contents.create`` will branch to this if called with 'from_hda_id'
@@ -325,7 +335,7 @@
:type id: str
:param id: the encoded id of the library item to return
:type library_id: str
- :param library_id: encoded id string of the library that contains this item
+ :param library_id: the encoded id of the library that contains this item
:type payload: dict
:param payload: dictionary structure containing::
'converted_dataset_id':
@@ -344,7 +354,7 @@
trans.sa_session.add( assoc )
trans.sa_session.flush()
- def __decode_library_content_id( self, trans, content_id ):
+ def __decode_library_content_id( self, content_id ):
if len( content_id ) % 16 == 0:
return 'LibraryDataset', content_id
elif content_id.startswith( 'F' ):
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.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/841deccfb359/
Changeset: 841deccfb359
User: nsoranzo
Date: 2015-01-08 13:00:50+00:00
Summary: PEP-8 and style fixes.
Affected #: 2 files
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r 841deccfb359c7722eeeb6f5101caa4b5925fb6e lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -6,10 +6,7 @@
from galaxy.managers import libraries, folders, roles
from galaxy.web import _future_expose_api as expose_api
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
-from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController
-from sqlalchemy.orm.exc import MultipleResultsFound
-from sqlalchemy.orm.exc import NoResultFound
import logging
log = logging.getLogger( __name__ )
@@ -48,7 +45,7 @@
def __decode_id( self, trans, encoded_id, object_name=None ):
"""
- Try to decode the id.
+ Try to decode the id.
:param object_name: Name of the object the id belongs to. (optional)
:type object_name: str
@@ -149,7 +146,7 @@
synopsis = payload.get( 'synopsis', None )
else:
raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
- updated_library = self.library_manager.update( trans, library, name, description, synopsis )
+ updated_library = self.library_manager.update( trans, library, name, description, synopsis )
library_dict = self.library_manager.get_library_dict( trans, updated_library )
return library_dict
@@ -248,20 +245,20 @@
*POST /api/libraries/{encoded_library_id}/permissions
:param encoded_library_id: the encoded id of the library to set the permissions of
- :type encoded_library_id: an encoded id string
+ :type encoded_library_id: an encoded id string
:param action: (required) describes what action should be performed
available actions: remove_restrictions, set_permissions
- :type action: string
+ :type action: string
:param access_ids[]: list of Role.id defining roles that should have access permission on the library
- :type access_ids[]: string or list
+ :type access_ids[]: string or list
:param add_ids[]: list of Role.id defining roles that should have add item permission on the library
- :type add_ids[]: string or list
+ :type add_ids[]: string or list
:param manage_ids[]: list of Role.id defining roles that should have manage permission on the library
- :type manage_ids[]: string or list
+ :type manage_ids[]: string or list
:param modify_ids[]: list of Role.id defining roles that should have modify permission on the library
- :type modify_ids[]: string or list
+ :type modify_ids[]: string or list
:rtype: dictionary
:returns: dict of current roles for all available permission types
@@ -306,7 +303,7 @@
else:
invalid_access_roles_names.append( role_id )
if len( invalid_access_roles_names ) > 0:
- log.warning( "The following roles could not be added to the library access permission: " + str( invalid_access_roles_names ) )
+ log.warning( "The following roles could not be added to the library access permission: " + str( invalid_access_roles_names ) )
# ADD TO LIBRARY ROLES
valid_add_roles = []
@@ -319,8 +316,8 @@
else:
invalid_add_roles_names.append( role_id )
if len( invalid_add_roles_names ) > 0:
- log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) )
-
+ log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) )
+
# MANAGE LIBRARY ROLES
valid_manage_roles = []
invalid_manage_roles_names = []
@@ -332,8 +329,8 @@
else:
invalid_manage_roles_names.append( role_id )
if len( invalid_manage_roles_names ) > 0:
- log.warning( "The following roles could not be added to the manage library permission: " + str( invalid_manage_roles_names ) )
-
+ log.warning( "The following roles could not be added to the manage library permission: " + str( invalid_manage_roles_names ) )
+
# MODIFY LIBRARY ROLES
valid_modify_roles = []
invalid_modify_roles_names = []
@@ -345,7 +342,7 @@
else:
invalid_modify_roles_names.append( role_id )
if len( invalid_modify_roles_names ) > 0:
- log.warning( "The following roles could not be added to the modify library permission: " + str( invalid_modify_roles_names ) )
+ log.warning( "The following roles could not be added to the modify library permission: " + str( invalid_modify_roles_names ) )
permissions = { trans.app.security_agent.permitted_actions.LIBRARY_ACCESS : valid_access_roles }
permissions.update( { trans.app.security_agent.permitted_actions.LIBRARY_ADD : valid_add_roles } )
@@ -357,7 +354,7 @@
# Copy the permissions to the root folder
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
else:
- raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
+ raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
'Allowed values are: "remove_restrictions", set_permissions"' )
roles = self.library_manager.get_current_roles( trans, library )
return roles
@@ -369,18 +366,16 @@
POST /api/libraries/{encoded_library_id}/permissions
Updates the library permissions.
"""
- import galaxy.util
- params = galaxy.util.Params( payload )
+ params = util.Params( payload )
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
role_params = params.get( k + '_in', [] )
- in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in galaxy.util.listify( role_params ) ]
+ in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
trans.app.security_agent.set_all_library_permissions( trans, library, permissions )
trans.sa_session.refresh( library )
# Copy the permissions to the root folder
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
- message = "Permissions updated for library '%s'." % library.name
item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
return item
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r 841deccfb359c7722eeeb6f5101caa4b5925fb6e lib/galaxy/webapps/galaxy/api/library_contents.py
--- a/lib/galaxy/webapps/galaxy/api/library_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/library_contents.py
@@ -119,7 +119,7 @@
:func:`galaxy.model.LibraryDataset.to_dict` and
:attr:`galaxy.model.LibraryFolder.dict_element_visible_keys`
"""
- class_name, content_id = self.__decode_library_content_id( trans, id )
+ class_name, content_id = self.__decode_library_content_id( id )
if class_name == 'LibraryFolder':
content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessible=True )
rval = content.to_dict( view='element', value_mapper={ 'id': trans.security.encode_id } )
@@ -166,7 +166,6 @@
:returns: a dictionary containing the id, name,
and 'show' url of the new item
"""
- create_type = None
if 'create_type' not in payload:
trans.response.status = 400
return "Missing required 'create_type' parameter."
@@ -178,10 +177,10 @@
if 'folder_id' not in payload:
trans.response.status = 400
- return "Missing requred 'folder_id' parameter."
+ return "Missing required 'folder_id' parameter."
else:
folder_id = payload.pop( 'folder_id' )
- class_name, folder_id = self.__decode_library_content_id( trans, folder_id )
+ class_name, folder_id = self.__decode_library_content_id( folder_id )
try:
# security is checked in the downstream controller
parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessible=False )
@@ -198,9 +197,7 @@
#check for extended metadata, store it and pop it out of the param
#otherwise sanitize_param will have a fit
- ex_meta_payload = None
- if 'extended_metadata' in payload:
- ex_meta_payload = payload.pop('extended_metadata')
+ ex_meta_payload = payload.pop('extended_metadata', None)
# Now create the desired content object, either file or folder.
if create_type == 'file':
@@ -344,7 +341,7 @@
trans.sa_session.add( assoc )
trans.sa_session.flush()
- def __decode_library_content_id( self, trans, content_id ):
+ def __decode_library_content_id( self, content_id ):
if len( content_id ) % 16 == 0:
return 'LibraryDataset', content_id
elif content_id.startswith( 'F' ):
https://bitbucket.org/galaxy/galaxy-central/commits/dbdc660f2a86/
Changeset: dbdc660f2a86
User: nsoranzo
Date: 2015-01-09 22:57:23+00:00
Summary: API doc enhancements.
Affected #: 1 file
diff -r 841deccfb359c7722eeeb6f5101caa4b5925fb6e -r dbdc660f2a86cfe46ac9518793b128196dfe9788 lib/galaxy/webapps/galaxy/api/library_contents.py
--- a/lib/galaxy/webapps/galaxy/api/library_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/library_contents.py
@@ -29,12 +29,12 @@
.. note:: May be slow! Returns all content traversing recursively through all folders.
.. seealso:: :class:`galaxy.webapps.galaxy.api.FolderContentsController.index` for a non-recursive solution
- :param library_id: encoded id string of the library
- :type library_id: string
+ :param library_id: the encoded id of the library
+ :type library_id: str
:returns: list of dictionaries of the form:
* id: the encoded id of the library item
- * name: the 'libary path'
+ * name: the 'library path'
or relationship of the library item to the root
* type: 'file' or 'folder'
* url: the url to get detailed information on the library item
@@ -109,7 +109,7 @@
:param id: the encoded id of the library item to return
:type id: str
- :param library_id: encoded id string of the library that contains this item
+ :param library_id: the encoded id of the library that contains this item
:type library_id: str
:returns: detailed library item information
@@ -146,21 +146,34 @@
the HDA's encoded id in ``from_hda_id`` (and optionally ``ldda_message``).
:type library_id: str
- :param library_id: encoded id string of the library where to create the new item
+ :param library_id: the encoded id of the library where to create the new item
:type payload: dict
:param payload: dictionary structure containing:
- * folder_id: the parent folder of the new item
+ * folder_id: the encoded id of the parent folder of the new item
* create_type: the type of item to create ('file', 'folder' or 'collection')
- * from_hda_id: (optional) the id of an accessible HDA to copy into the
- library
+ * from_hda_id: (optional, only if create_type is 'file') the
+ encoded id of an accessible HDA to copy into the library
* ldda_message: (optional) the new message attribute of the LDDA created
* extended_metadata: (optional) dub-dictionary containing any extended
metadata to associate with the item
- * link_data_only: (optional) either 'copy_files' (default) or 'link_to_files'
* upload_option: (optional) one of 'upload_file' (default), 'upload_directory' or 'upload_paths'
- * server_dir: (optional) only if upload_option is 'upload_directory'
- * filesystem_paths: (optional) only if upload_option is 'upload_paths' and the user is an admin
+ * server_dir: (optional, only if upload_option is
+ 'upload_directory') relative path of the subdirectory of Galaxy
+ ``library_import_dir`` to upload. All and only the files (i.e.
+ no subdirectories) contained in the specified directory will be
+ uploaded.
+ * filesystem_paths: (optional, only if upload_option is
+ 'upload_paths' and the user is an admin) file paths on the
+ Galaxy server to upload to the library, one file per line
+ * link_data_only: (optional, only when upload_option is
+ 'upload_directory' or 'upload_paths') either 'copy_files'
+ (default) or 'link_to_files'. Setting to 'link_to_files'
+ symlinks instead of copying the files
+ * name: (optional, only if create_type is 'folder') name of the
+ folder to create
+ * description: (optional, only if create_type is 'folder')
+ description of the folder to create
:rtype: dict
:returns: a dictionary containing the id, name,
@@ -269,7 +282,7 @@
def _copy_hda_to_library_folder( self, trans, from_hda_id, library_id, folder_id, ldda_message='' ):
"""
- Copies hda ``from_hda_id`` to library folder ``library_folder_id`` optionally
+ Copies hda ``from_hda_id`` to library folder ``folder_id``, optionally
adding ``ldda_message`` to the new ldda's ``message``.
``library_contents.create`` will branch to this if called with 'from_hda_id'
@@ -322,7 +335,7 @@
:type id: str
:param id: the encoded id of the library item to return
:type library_id: str
- :param library_id: encoded id string of the library that contains this item
+ :param library_id: the encoded id of the library that contains this item
:type payload: dict
:param payload: dictionary structure containing::
'converted_dataset_id':
https://bitbucket.org/galaxy/galaxy-central/commits/d3dff45bbb05/
Changeset: d3dff45bbb05
User: dannon
Date: 2015-01-12 12:02:23+00:00
Summary: Merged in nsoranzo/galaxy-central (pull request #628)
PEP-8 fixes and API doc ehnancements to libraries API
Affected #: 2 files
diff -r eb61b02da1866c4a7da0f2fa357ce43e6c62b57c -r d3dff45bbb0554150da4491eb2d2031d11f90063 lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -6,10 +6,7 @@
from galaxy.managers import libraries, folders, roles
from galaxy.web import _future_expose_api as expose_api
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
-from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController
-from sqlalchemy.orm.exc import MultipleResultsFound
-from sqlalchemy.orm.exc import NoResultFound
import logging
log = logging.getLogger( __name__ )
@@ -48,7 +45,7 @@
def __decode_id( self, trans, encoded_id, object_name=None ):
"""
- Try to decode the id.
+ Try to decode the id.
:param object_name: Name of the object the id belongs to. (optional)
:type object_name: str
@@ -149,7 +146,7 @@
synopsis = payload.get( 'synopsis', None )
else:
raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
- updated_library = self.library_manager.update( trans, library, name, description, synopsis )
+ updated_library = self.library_manager.update( trans, library, name, description, synopsis )
library_dict = self.library_manager.get_library_dict( trans, updated_library )
return library_dict
@@ -248,20 +245,20 @@
*POST /api/libraries/{encoded_library_id}/permissions
:param encoded_library_id: the encoded id of the library to set the permissions of
- :type encoded_library_id: an encoded id string
+ :type encoded_library_id: an encoded id string
:param action: (required) describes what action should be performed
available actions: remove_restrictions, set_permissions
- :type action: string
+ :type action: string
:param access_ids[]: list of Role.id defining roles that should have access permission on the library
- :type access_ids[]: string or list
+ :type access_ids[]: string or list
:param add_ids[]: list of Role.id defining roles that should have add item permission on the library
- :type add_ids[]: string or list
+ :type add_ids[]: string or list
:param manage_ids[]: list of Role.id defining roles that should have manage permission on the library
- :type manage_ids[]: string or list
+ :type manage_ids[]: string or list
:param modify_ids[]: list of Role.id defining roles that should have modify permission on the library
- :type modify_ids[]: string or list
+ :type modify_ids[]: string or list
:rtype: dictionary
:returns: dict of current roles for all available permission types
@@ -306,7 +303,7 @@
else:
invalid_access_roles_names.append( role_id )
if len( invalid_access_roles_names ) > 0:
- log.warning( "The following roles could not be added to the library access permission: " + str( invalid_access_roles_names ) )
+ log.warning( "The following roles could not be added to the library access permission: " + str( invalid_access_roles_names ) )
# ADD TO LIBRARY ROLES
valid_add_roles = []
@@ -319,8 +316,8 @@
else:
invalid_add_roles_names.append( role_id )
if len( invalid_add_roles_names ) > 0:
- log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) )
-
+ log.warning( "The following roles could not be added to the add library item permission: " + str( invalid_add_roles_names ) )
+
# MANAGE LIBRARY ROLES
valid_manage_roles = []
invalid_manage_roles_names = []
@@ -332,8 +329,8 @@
else:
invalid_manage_roles_names.append( role_id )
if len( invalid_manage_roles_names ) > 0:
- log.warning( "The following roles could not be added to the manage library permission: " + str( invalid_manage_roles_names ) )
-
+ log.warning( "The following roles could not be added to the manage library permission: " + str( invalid_manage_roles_names ) )
+
# MODIFY LIBRARY ROLES
valid_modify_roles = []
invalid_modify_roles_names = []
@@ -345,7 +342,7 @@
else:
invalid_modify_roles_names.append( role_id )
if len( invalid_modify_roles_names ) > 0:
- log.warning( "The following roles could not be added to the modify library permission: " + str( invalid_modify_roles_names ) )
+ log.warning( "The following roles could not be added to the modify library permission: " + str( invalid_modify_roles_names ) )
permissions = { trans.app.security_agent.permitted_actions.LIBRARY_ACCESS : valid_access_roles }
permissions.update( { trans.app.security_agent.permitted_actions.LIBRARY_ADD : valid_add_roles } )
@@ -357,7 +354,7 @@
# Copy the permissions to the root folder
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
else:
- raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
+ raise exceptions.RequestParameterInvalidException( 'The mandatory parameter "action" has an invalid value.'
'Allowed values are: "remove_restrictions", set_permissions"' )
roles = self.library_manager.get_current_roles( trans, library )
return roles
@@ -369,18 +366,16 @@
POST /api/libraries/{encoded_library_id}/permissions
Updates the library permissions.
"""
- import galaxy.util
- params = galaxy.util.Params( payload )
+ params = util.Params( payload )
permissions = {}
for k, v in trans.app.model.Library.permitted_actions.items():
role_params = params.get( k + '_in', [] )
- in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in galaxy.util.listify( role_params ) ]
+ in_roles = [ trans.sa_session.query( trans.app.model.Role ).get( trans.security.decode_id( x ) ) for x in util.listify( role_params ) ]
permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles
trans.app.security_agent.set_all_library_permissions( trans, library, permissions )
trans.sa_session.refresh( library )
# Copy the permissions to the root folder
trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder )
- message = "Permissions updated for library '%s'." % library.name
item = library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
return item
diff -r eb61b02da1866c4a7da0f2fa357ce43e6c62b57c -r d3dff45bbb0554150da4491eb2d2031d11f90063 lib/galaxy/webapps/galaxy/api/library_contents.py
--- a/lib/galaxy/webapps/galaxy/api/library_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/library_contents.py
@@ -29,12 +29,12 @@
.. note:: May be slow! Returns all content traversing recursively through all folders.
.. seealso:: :class:`galaxy.webapps.galaxy.api.FolderContentsController.index` for a non-recursive solution
- :param library_id: encoded id string of the library
- :type library_id: string
+ :param library_id: the encoded id of the library
+ :type library_id: str
:returns: list of dictionaries of the form:
* id: the encoded id of the library item
- * name: the 'libary path'
+ * name: the 'library path'
or relationship of the library item to the root
* type: 'file' or 'folder'
* url: the url to get detailed information on the library item
@@ -109,7 +109,7 @@
:param id: the encoded id of the library item to return
:type id: str
- :param library_id: encoded id string of the library that contains this item
+ :param library_id: the encoded id of the library that contains this item
:type library_id: str
:returns: detailed library item information
@@ -119,7 +119,7 @@
:func:`galaxy.model.LibraryDataset.to_dict` and
:attr:`galaxy.model.LibraryFolder.dict_element_visible_keys`
"""
- class_name, content_id = self.__decode_library_content_id( trans, id )
+ class_name, content_id = self.__decode_library_content_id( id )
if class_name == 'LibraryFolder':
content = self.get_library_folder( trans, content_id, check_ownership=False, check_accessible=True )
rval = content.to_dict( view='element', value_mapper={ 'id': trans.security.encode_id } )
@@ -146,27 +146,39 @@
the HDA's encoded id in ``from_hda_id`` (and optionally ``ldda_message``).
:type library_id: str
- :param library_id: encoded id string of the library where to create the new item
+ :param library_id: the encoded id of the library where to create the new item
:type payload: dict
:param payload: dictionary structure containing:
- * folder_id: the parent folder of the new item
+ * folder_id: the encoded id of the parent folder of the new item
* create_type: the type of item to create ('file', 'folder' or 'collection')
- * from_hda_id: (optional) the id of an accessible HDA to copy into the
- library
+ * from_hda_id: (optional, only if create_type is 'file') the
+ encoded id of an accessible HDA to copy into the library
* ldda_message: (optional) the new message attribute of the LDDA created
* extended_metadata: (optional) dub-dictionary containing any extended
metadata to associate with the item
- * link_data_only: (optional) either 'copy_files' (default) or 'link_to_files'
* upload_option: (optional) one of 'upload_file' (default), 'upload_directory' or 'upload_paths'
- * server_dir: (optional) only if upload_option is 'upload_directory'
- * filesystem_paths: (optional) only if upload_option is 'upload_paths' and the user is an admin
+ * server_dir: (optional, only if upload_option is
+ 'upload_directory') relative path of the subdirectory of Galaxy
+ ``library_import_dir`` to upload. All and only the files (i.e.
+ no subdirectories) contained in the specified directory will be
+ uploaded.
+ * filesystem_paths: (optional, only if upload_option is
+ 'upload_paths' and the user is an admin) file paths on the
+ Galaxy server to upload to the library, one file per line
+ * link_data_only: (optional, only when upload_option is
+ 'upload_directory' or 'upload_paths') either 'copy_files'
+ (default) or 'link_to_files'. Setting to 'link_to_files'
+ symlinks instead of copying the files
+ * name: (optional, only if create_type is 'folder') name of the
+ folder to create
+ * description: (optional, only if create_type is 'folder')
+ description of the folder to create
:rtype: dict
:returns: a dictionary containing the id, name,
and 'show' url of the new item
"""
- create_type = None
if 'create_type' not in payload:
trans.response.status = 400
return "Missing required 'create_type' parameter."
@@ -178,10 +190,10 @@
if 'folder_id' not in payload:
trans.response.status = 400
- return "Missing requred 'folder_id' parameter."
+ return "Missing required 'folder_id' parameter."
else:
folder_id = payload.pop( 'folder_id' )
- class_name, folder_id = self.__decode_library_content_id( trans, folder_id )
+ class_name, folder_id = self.__decode_library_content_id( folder_id )
try:
# security is checked in the downstream controller
parent = self.get_library_folder( trans, folder_id, check_ownership=False, check_accessible=False )
@@ -198,9 +210,7 @@
#check for extended metadata, store it and pop it out of the param
#otherwise sanitize_param will have a fit
- ex_meta_payload = None
- if 'extended_metadata' in payload:
- ex_meta_payload = payload.pop('extended_metadata')
+ ex_meta_payload = payload.pop('extended_metadata', None)
# Now create the desired content object, either file or folder.
if create_type == 'file':
@@ -272,7 +282,7 @@
def _copy_hda_to_library_folder( self, trans, from_hda_id, library_id, folder_id, ldda_message='' ):
"""
- Copies hda ``from_hda_id`` to library folder ``library_folder_id`` optionally
+ Copies hda ``from_hda_id`` to library folder ``folder_id``, optionally
adding ``ldda_message`` to the new ldda's ``message``.
``library_contents.create`` will branch to this if called with 'from_hda_id'
@@ -325,7 +335,7 @@
:type id: str
:param id: the encoded id of the library item to return
:type library_id: str
- :param library_id: encoded id string of the library that contains this item
+ :param library_id: the encoded id of the library that contains this item
:type payload: dict
:param payload: dictionary structure containing::
'converted_dataset_id':
@@ -344,7 +354,7 @@
trans.sa_session.add( assoc )
trans.sa_session.flush()
- def __decode_library_content_id( self, trans, content_id ):
+ def __decode_library_content_id( self, content_id ):
if len( content_id ) % 16 == 0:
return 'LibraryDataset', content_id
elif content_id.startswith( 'F' ):
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.
1
0

commit/galaxy-central: jmchilton: Source the common startup script for run_tests.sh.
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/eb61b02da186/
Changeset: eb61b02da186
User: jmchilton
Date: 2015-01-12 02:43:13+00:00
Summary: Source the common startup script for run_tests.sh.
Fixes planemo #50.
Affected #: 1 file
diff -r ff4e9117b39ddaff106d1c44792eb6fbcc7c0256 -r eb61b02da1866c4a7da0f2fa357ce43e6c62b57c run_tests.sh
--- a/run_tests.sh
+++ b/run_tests.sh
@@ -1,5 +1,7 @@
#!/bin/sh
+./scripts/common_startup.sh
+
# A good place to look for nose info: http://somethingaboutorange.com/mrl/projects/nose/
rm -f run_functional_tests.log
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.
1
0

commit/galaxy-central: jmchilton: Tool Tests - Only set library import dir if it exists.
by commits-noreply@bitbucket.org 12 Jan '15
by commits-noreply@bitbucket.org 12 Jan '15
12 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ff4e9117b39d/
Changeset: ff4e9117b39d
User: jmchilton
Date: 2015-01-12 02:32:50+00:00
Summary: Tool Tests - Only set library import dir if it exists.
Fixes planemo #41 (https://github.com/galaxyproject/planemo/issues/41)
Affected #: 1 file
diff -r 796f3129e903e164e72ce9ec4db0158eb427ccac -r ff4e9117b39ddaff106d1c44792eb6fbcc7c0256 scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -225,7 +225,11 @@
if not os.path.isabs( galaxy_test_file_dir ):
galaxy_test_file_dir = os.path.join( os.getcwd(), galaxy_test_file_dir )
library_import_dir = galaxy_test_file_dir
- user_library_import_dir = os.path.join( galaxy_test_file_dir, 'users' )
+ import_dir = os.path.join( galaxy_test_file_dir, 'users' )
+ if os.path.exists(import_dir):
+ user_library_import_dir = import_dir
+ else:
+ user_library_import_dir = None
ignore_files = ()
start_server = 'GALAXY_TEST_EXTERNAL' not in os.environ
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.
1
0

commit/galaxy-central: guerler: Masthead: Lower icons by one pixel
by commits-noreply@bitbucket.org 11 Jan '15
by commits-noreply@bitbucket.org 11 Jan '15
11 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/796f3129e903/
Changeset: 796f3129e903
User: guerler
Date: 2015-01-11 18:16:00+00:00
Summary: Masthead: Lower icons by one pixel
Affected #: 2 files
diff -r 7833db9748f17c88f458976471e3aa64cb6e8d8b -r 796f3129e903e164e72ce9ec4db0158eb427ccac static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1742,7 +1742,7 @@
#masthead li.dropdown>a:hover .caret{border-top-color:gold;border-bottom-color:gold}
#masthead .navbar-brand{position:absolute;left:0;top:0;font-family:verdana;font-weight:bold;font-size:20px;line-height:1;color:white;padding:5px 20px 12px;margin-left:-15px;z-index:2000}#masthead .navbar-brand img{display:inline;width:26px;vertical-align:top}
#masthead .navbar-brand a{color:white;text-decoration:none}
-#masthead .iconbar{position:absolute;top:6px;right:110px;cursor:pointer;color:#999;overflow:hidden}#masthead .iconbar .symbol{float:left;margin:0px 10px;height:26px;font-size:11px}
+#masthead .iconbar{position:absolute;top:7px;right:110px;cursor:pointer;color:#999;overflow:hidden}#masthead .iconbar .symbol{float:left;margin:0px 10px;height:26px;font-size:11px}
#masthead .iconbar .symbol .number{font-weight:bold;font-size:10px;font-family:"Lucida Grande",verdana,arial,helvetica,sans-serif;position:relative;left:23px;top:-12px}
#masthead .iconbar .toggle{color:gold}
.quota-meter-container{position:absolute;top:0;right:0;height:32px}
diff -r 7833db9748f17c88f458976471e3aa64cb6e8d8b -r 796f3129e903e164e72ce9ec4db0158eb427ccac static/style/src/less/base.less
--- a/static/style/src/less/base.less
+++ b/static/style/src/less/base.less
@@ -425,7 +425,7 @@
.iconbar
{
position : absolute;
- top : 6px;
+ top : 7px;
right : 110px;
cursor : pointer;
color : @gray-light;
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.
1
0

commit/galaxy-central: guerler: Upload: Show upload button only in analysis view
by commits-noreply@bitbucket.org 11 Jan '15
by commits-noreply@bitbucket.org 11 Jan '15
11 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7833db9748f1/
Changeset: 7833db9748f1
User: guerler
Date: 2015-01-11 17:59:43+00:00
Summary: Upload: Show upload button only in analysis view
Affected #: 4 files
diff -r 41bad82393f1790013b09851afd6f8914500f7e2 -r 7833db9748f17c88f458976471e3aa64cb6e8d8b client/galaxy/scripts/mvc/upload/upload-view.js
--- a/client/galaxy/scripts/mvc/upload/upload-view.js
+++ b/client/galaxy/scripts/mvc/upload/upload-view.js
@@ -104,7 +104,7 @@
});
// define location
- $('#left .unified-panel-header-inner').append((new UploadButton.View(this.ui_button)).$el);
+ $('.with-upload-button').append((new UploadButton.View(this.ui_button)).$el);
// load extension
var self = this;
diff -r 41bad82393f1790013b09851afd6f8914500f7e2 -r 7833db9748f17c88f458976471e3aa64cb6e8d8b static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -104,7 +104,7 @@
});
// define location
- $('#left .unified-panel-header-inner').append((new UploadButton.View(this.ui_button)).$el);
+ $('.with-upload-button').append((new UploadButton.View(this.ui_button)).$el);
// load extension
var self = this;
diff -r 41bad82393f1790013b09851afd6f8914500f7e2 -r 7833db9748f17c88f458976471e3aa64cb6e8d8b static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui/ui-popover","mvc/ui/ui-modal","utils/uploadbox"],function(f,e,c,b,g,d,a){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,list_extensions:[],list_genomes:[],auto:{id:"auto",text:"Auto-detect",description:"This system will try to detect the file type automatically. If your file is not detected properly as one of the known formats, it most likely means that it has some format problems (e.g., different number of columns on different rows). You can still coerce the system to set your data to the format you think it should be. You can also upload compressed files, which will automatically be decompressed."},collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(i){this.options=_.defaults(i,this.options)}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){j.preventDefault();h.show()}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.get({url:galaxy_config.root+"api/datatypes?extension_only=False",success:function(j){for(key in j){h.list_extensions.push({id:j[key].extension,text:j[key].extension,description:j[key].description,description_url:j[key].description_url})}h.list_extensions.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0});if(!h.options.datatypes_disable_auto){h.list_extensions.unshift(h.auto)}}});f.get({url:galaxy_config.root+"api/genomes",success:function(j){for(key in j){h.list_genomes.push({id:j[key][1],text:j[key][0]})}h.list_genomes.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0})}});this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},show:function(){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.show()},500);return}if(!this.modal){var h=this;this.modal=new a.View({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Paste/Fetch data":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(j,k,l){h._eventAnnounce(j,k,l)},initialize:function(j,k,l){return h._eventInitialize(j,k,l)},progress:function(j,k,l){h._eventProgress(j,k,l)},success:function(j,k,l){h._eventSuccess(j,k,l)},error:function(j,k,l){h._eventError(j,k,l)},complete:function(){h._eventComplete()}});var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}this.modal.show();this._updateUser();this._updateScreen()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}tool_input={};if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshContents()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateUser:function(){this.current_user=Galaxy.currUser.get("id");this.current_history=null;if(this.current_user){this.current_history=Galaxy.currHistoryPanel.model.get("id")}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Paste/Fetch data")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Paste/Fetch data")}if(this.current_user&&this.options.ftp_upload_dir&&this.options.ftp_upload_site){this.modal.showButton("Choose FTP file")}else{this.modal.hideButton("Choose FTP file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui/ui-popover","mvc/ui/ui-modal","utils/uploadbox"],function(f,e,c,b,g,d,a){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,list_extensions:[],list_genomes:[],auto:{id:"auto",text:"Auto-detect",description:"This system will try to detect the file type automatically. If your file is not detected properly as one of the known formats, it most likely means that it has some format problems (e.g., different number of columns on different rows). You can still coerce the system to set your data to the format you think it should be. You can also upload compressed files, which will automatically be decompressed."},collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(i){this.options=_.defaults(i,this.options)}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){j.preventDefault();h.show()}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$(".with-upload-button").append((new e.View(this.ui_button)).$el);var h=this;f.get({url:galaxy_config.root+"api/datatypes?extension_only=False",success:function(j){for(key in j){h.list_extensions.push({id:j[key].extension,text:j[key].extension,description:j[key].description,description_url:j[key].description_url})}h.list_extensions.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0});if(!h.options.datatypes_disable_auto){h.list_extensions.unshift(h.auto)}}});f.get({url:galaxy_config.root+"api/genomes",success:function(j){for(key in j){h.list_genomes.push({id:j[key][1],text:j[key][0]})}h.list_genomes.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0})}});this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},show:function(){var h=this;if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.show()},500);return}if(!this.modal){var h=this;this.modal=new a.View({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Paste/Fetch data":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(j,k,l){h._eventAnnounce(j,k,l)},initialize:function(j,k,l){return h._eventInitialize(j,k,l)},progress:function(j,k,l){h._eventProgress(j,k,l)},success:function(j,k,l){h._eventSuccess(j,k,l)},error:function(j,k,l){h._eventError(j,k,l)},complete:function(){h._eventComplete()}});var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}this.modal.show();this._updateUser();this._updateScreen()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}tool_input={};if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshContents()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateUser:function(){this.current_user=Galaxy.currUser.get("id");this.current_history=null;if(this.current_user){this.current_history=Galaxy.currHistoryPanel.model.get("id")}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Paste/Fetch data")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Paste/Fetch data")}if(this.current_user&&this.options.ftp_upload_dir&&this.options.ftp_upload_site){this.modal.showButton("Choose FTP file")}else{this.modal.hideButton("Choose FTP file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
diff -r 41bad82393f1790013b09851afd6f8914500f7e2 -r 7833db9748f17c88f458976471e3aa64cb6e8d8b templates/webapps/galaxy/root/index.mako
--- a/templates/webapps/galaxy/root/index.mako
+++ b/templates/webapps/galaxy/root/index.mako
@@ -58,7 +58,7 @@
<%def name="left_panel()"><div class="unified-panel-header" unselectable="on">
- <div class='unified-panel-header-inner'>
+ <div class='unified-panel-header-inner with-upload-button'>
${n_('Tools')}
</div></div>
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.
1
0

commit/galaxy-central: guerler: ToolForm/Workflow: Add modules
by commits-noreply@bitbucket.org 11 Jan '15
by commits-noreply@bitbucket.org 11 Jan '15
11 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/41bad82393f1/
Changeset: 41bad82393f1
User: guerler
Date: 2015-01-11 17:08:10+00:00
Summary: ToolForm/Workflow: Add modules
Affected #: 6 files
diff -r d9b038019163bc378b72b675ddb4e1e902384b12 -r 41bad82393f1790013b09851afd6f8914500f7e2 client/galaxy/scripts/mvc/tools/tools-form-base.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-form-base.js
@@ -0,0 +1,315 @@
+/**
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
+define(['utils/utils', 'utils/deferred', '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'],
+ function(Utils, Deferred, Portlet, Ui, CitationModel, CitationView,
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree) {
+
+ // create form view
+ return Backbone.View.extend({
+ // initialize
+ initialize: function(options) {
+ // log options
+ console.debug(options);
+
+ // link galaxy modal or create one
+ var galaxy = parent.Galaxy;
+ if (galaxy && galaxy.modal) {
+ this.modal = galaxy.modal;
+ } else {
+ this.modal = new Ui.Modal.View();
+ }
+
+ // check if the user is an admin
+ if (galaxy && galaxy.currUser) {
+ this.is_admin = galaxy.currUser.get('is_admin');
+ } else {
+ this.is_admin = false;
+ }
+
+ // link options
+ this.options = options;
+
+ // link container
+ this.container = this.options.container || 'body';
+
+ // create deferred processing queue handler
+ // this handler reduces the number of requests to the api by filtering redundant requests
+ this.deferred = new Deferred();
+
+ // set element
+ this.setElement('<div/>');
+
+ // add to main element
+ $(this.container).append(this.$el);
+
+ // build this form
+ this._buildForm();
+ },
+
+ /** Shows the final message (usually upon successful job submission)
+ */
+ reciept: function($el) {
+ $(this.container).empty();
+ $(this.container).append($el);
+ },
+
+ /** Highlight and scroll to input element (currently only used for error notifications)
+ */
+ highlight: function (input_id, message, silent) {
+ // get input field
+ var input_element = this.element_list[input_id];
+
+ // check input element
+ if (input_element) {
+ // mark error
+ input_element.error(message || 'Please verify this parameter.');
+
+ // scroll to first input element
+ if (!silent) {
+ $(this.container).animate({
+ scrollTop: input_element.$el.offset().top - 20
+ }, 500);
+ }
+ }
+ },
+
+ /** Main tool form build function. This function is called once a new model is available.
+ */
+ _buildForm: function() {
+ // link this
+ var self = this;
+
+ // reset events
+ this.off('refresh');
+ this.off('reset');
+
+ // reset field list, which contains the input field elements
+ this.field_list = {};
+
+ // reset sequential input definition list, which contains the input definitions as provided from the api
+ this.input_list = {};
+
+ // reset input element list, which contains the dom elements of each input element (includes also the input field)
+ this.element_list = {};
+
+ // creates a tree/json data structure from the input form
+ this.tree = new ToolTree(this);
+
+ // request history content and build form
+ this.content = new ToolContent(this);
+
+ // link model options
+ var options = this.options;
+
+ // create ui elements
+ this._renderForm(options);
+
+ // rebuild the underlying data structure
+ this.tree.finalize();
+
+ // show errors
+ if (!this.workflow && options.errors) {
+ var error_messages = this.tree.matchResponse(options.errors);
+ for (var input_id in error_messages) {
+ this.highlight(input_id, error_messages[input_id], true);
+ }
+ }
+
+ // add refresh listener
+ this.on('refresh', function() {
+ // by using/reseting the deferred ajax queue the number of redundant calls is reduced
+ self.deferred.reset();
+ self.deferred.execute(function(){self._updateModel()});
+ });
+
+ // add reset listener
+ this.on('reset', function() {
+ for (var i in this.element_list) {
+ this.element_list[i].reset();
+ }
+ });
+ },
+
+ /** Renders the UI elements required for the form
+ */
+ _renderForm: function(options) {
+ // link this
+ var self = this;
+
+ // create message view
+ this.message = new Ui.Message();
+
+ // button for version selection
+ var requirements_button = new Ui.ButtonIcon({
+ icon : 'fa-info-circle',
+ title : 'Requirements',
+ tooltip : 'Display tool requirements',
+ onclick : function() {
+ if (!this.visible) {
+ this.visible = true;
+ self.message.update({
+ persistent : true,
+ message : ToolTemplate.requirements(options),
+ status : 'info'
+ });
+ } else {
+ this.visible = false;
+ self.message.update({
+ message : ''
+ });
+ }
+ }
+ });
+ if (!options.requirements || options.requirements.length == 0) {
+ requirements_button.$el.hide();
+ }
+
+ // button for version selection
+ var versions_button = new Ui.ButtonMenu({
+ icon : 'fa-cubes',
+ title : 'Versions',
+ tooltip : 'Select another tool version'
+ });
+ if (options.versions && options.versions.length > 1) {
+ for (var i in options.versions) {
+ var version = options.versions[i];
+ if (version != options.version) {
+ versions_button.addMenu({
+ title : 'Switch to ' + version,
+ version : version,
+ icon : 'fa-cube',
+ onclick : function() {
+ // here we update the tool version (some tools encode the version also in the id)
+ options.id = options.id.replace(options.version, this.version);
+ options.version = this.version;
+
+ // rebuild the model and form
+ self.deferred.reset();
+ self.deferred.execute(function(){self._buildModel()});
+ }
+ });
+ }
+ }
+ } else {
+ versions_button.$el.hide();
+ }
+
+ // button menu
+ var menu_button = new Ui.ButtonMenu({
+ icon : 'fa-caret-down',
+ title : 'Options',
+ tooltip : 'View available options'
+ });
+
+ // configure button selection
+ if(options.biostar_url) {
+ // add question option
+ menu_button.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu_button.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(options.biostar_url + '/t/' + options.id + '/');
+ }
+ });
+ };
+
+ // create share button
+ menu_button.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=' + options.id);
+ }
+ });
+
+ // add admin operations
+ if (this.is_admin) {
+ // create download button
+ menu_button.addMenu({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + options.id + '/download';
+ }
+ });
+ }
+
+ // create tool form section
+ this.section = new ToolSection.View(self, {
+ inputs : options.inputs,
+ cls : 'ui-table-plain'
+ });
+
+ // switch to classic tool form mako if the form definition is incompatible
+ if (this.incompatible) {
+ this.$el.hide();
+ $('#tool-form-classic').show();
+ return;
+ }
+
+ // create portlet
+ this.portlet = new Portlet.View({
+ icon : 'fa-wrench',
+ title : '<b>' + options.name + '</b> ' + options.description + ' (Galaxy Tool Version ' + options.version + ')',
+ cls : 'ui-portlet-slim',
+ operations: {
+ requirements : requirements_button,
+ menu : menu_button,
+ versions : versions_button
+ },
+ buttons : this.buttons
+ });
+
+ // append message
+ this.portlet.append(this.message.$el, true);
+
+ // append tool section
+ this.portlet.append(this.section.$el);
+
+ // start form
+ this.$el.empty();
+ this.$el.append(this.portlet.$el);
+
+ // append help
+ if (options.help != '') {
+ this.$el.append(ToolTemplate.help(options.help));
+ }
+
+ // append citations
+ if (options.citations) {
+ var $citations = $('<div/>');
+ var citations = new CitationModel.ToolCitationCollection();
+ citations.tool_id = options.id;
+ var citation_list_view = new CitationView.CitationListView({ el: $citations, collection: citations } );
+ citation_list_view.render();
+ citations.fetch();
+ this.$el.append($citations);
+ }
+
+ // show message if available in model
+ if (options.message) {
+ this.message.update({
+ persistent : true,
+ status : 'warning',
+ message : options.message
+ });
+ }
+ }
+ });
+});
diff -r d9b038019163bc378b72b675ddb4e1e902384b12 -r 41bad82393f1790013b09851afd6f8914500f7e2 client/galaxy/scripts/mvc/tools/tools-form-workflow.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js
@@ -0,0 +1,66 @@
+/**
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
+define(['utils/utils', 'mvc/tools/tools-form-base'],
+ function(Utils, ToolFormBase) {
+
+ // create form view
+ var View = ToolFormBase.extend({
+ initialize: function(options) {
+ this.workflow = true;
+ ToolFormBase.prototype.initialize.call(this, options);
+ },
+
+ /** Builds a new model through api call and recreates the entire form
+ */
+ _buildModel: function() {
+ },
+
+ /** Request a new model for an already created tool form and updates the form inputs
+ */
+ _updateModel: function() {
+ // create the request dictionary
+ var self = this;
+ var current_state = this.tree.finalize();
+
+ // log tool state
+ console.debug('tools-form-workflow::_refreshForm() - Refreshing states.');
+ console.debug(current_state);
+
+ // register process
+ var process_id = this.deferred.register();
+
+ // build model url for request
+ var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id;
+
+ // post job
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ data : current_state,
+ success : function(node) {
+ parent.update_node(node);
+
+ // process completed
+ self.deferred.done(process_id);
+
+ // log success
+ console.debug('tools-form::_refreshForm() - States refreshed.');
+ console.debug(node);
+ },
+ error : function(response) {
+ // process completed
+ self.deferred.done(process_id);
+
+ // log error
+ console.debug('tools-form::_refreshForm() - Refresh request failed.');
+ console.debug(response);
+ }
+ });
+ }
+ });
+
+ return {
+ View: View
+ };
+});
diff -r d9b038019163bc378b72b675ddb4e1e902384b12 -r 41bad82393f1790013b09851afd6f8914500f7e2 static/scripts/mvc/tools/tools-form-base.js
--- /dev/null
+++ b/static/scripts/mvc/tools/tools-form-base.js
@@ -0,0 +1,315 @@
+/**
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
+define(['utils/utils', 'utils/deferred', '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'],
+ function(Utils, Deferred, Portlet, Ui, CitationModel, CitationView,
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree) {
+
+ // create form view
+ return Backbone.View.extend({
+ // initialize
+ initialize: function(options) {
+ // log options
+ console.debug(options);
+
+ // link galaxy modal or create one
+ var galaxy = parent.Galaxy;
+ if (galaxy && galaxy.modal) {
+ this.modal = galaxy.modal;
+ } else {
+ this.modal = new Ui.Modal.View();
+ }
+
+ // check if the user is an admin
+ if (galaxy && galaxy.currUser) {
+ this.is_admin = galaxy.currUser.get('is_admin');
+ } else {
+ this.is_admin = false;
+ }
+
+ // link options
+ this.options = options;
+
+ // link container
+ this.container = this.options.container || 'body';
+
+ // create deferred processing queue handler
+ // this handler reduces the number of requests to the api by filtering redundant requests
+ this.deferred = new Deferred();
+
+ // set element
+ this.setElement('<div/>');
+
+ // add to main element
+ $(this.container).append(this.$el);
+
+ // build this form
+ this._buildForm();
+ },
+
+ /** Shows the final message (usually upon successful job submission)
+ */
+ reciept: function($el) {
+ $(this.container).empty();
+ $(this.container).append($el);
+ },
+
+ /** Highlight and scroll to input element (currently only used for error notifications)
+ */
+ highlight: function (input_id, message, silent) {
+ // get input field
+ var input_element = this.element_list[input_id];
+
+ // check input element
+ if (input_element) {
+ // mark error
+ input_element.error(message || 'Please verify this parameter.');
+
+ // scroll to first input element
+ if (!silent) {
+ $(this.container).animate({
+ scrollTop: input_element.$el.offset().top - 20
+ }, 500);
+ }
+ }
+ },
+
+ /** Main tool form build function. This function is called once a new model is available.
+ */
+ _buildForm: function() {
+ // link this
+ var self = this;
+
+ // reset events
+ this.off('refresh');
+ this.off('reset');
+
+ // reset field list, which contains the input field elements
+ this.field_list = {};
+
+ // reset sequential input definition list, which contains the input definitions as provided from the api
+ this.input_list = {};
+
+ // reset input element list, which contains the dom elements of each input element (includes also the input field)
+ this.element_list = {};
+
+ // creates a tree/json data structure from the input form
+ this.tree = new ToolTree(this);
+
+ // request history content and build form
+ this.content = new ToolContent(this);
+
+ // link model options
+ var options = this.options;
+
+ // create ui elements
+ this._renderForm(options);
+
+ // rebuild the underlying data structure
+ this.tree.finalize();
+
+ // show errors
+ if (!this.workflow && options.errors) {
+ var error_messages = this.tree.matchResponse(options.errors);
+ for (var input_id in error_messages) {
+ this.highlight(input_id, error_messages[input_id], true);
+ }
+ }
+
+ // add refresh listener
+ this.on('refresh', function() {
+ // by using/reseting the deferred ajax queue the number of redundant calls is reduced
+ self.deferred.reset();
+ self.deferred.execute(function(){self._updateModel()});
+ });
+
+ // add reset listener
+ this.on('reset', function() {
+ for (var i in this.element_list) {
+ this.element_list[i].reset();
+ }
+ });
+ },
+
+ /** Renders the UI elements required for the form
+ */
+ _renderForm: function(options) {
+ // link this
+ var self = this;
+
+ // create message view
+ this.message = new Ui.Message();
+
+ // button for version selection
+ var requirements_button = new Ui.ButtonIcon({
+ icon : 'fa-info-circle',
+ title : 'Requirements',
+ tooltip : 'Display tool requirements',
+ onclick : function() {
+ if (!this.visible) {
+ this.visible = true;
+ self.message.update({
+ persistent : true,
+ message : ToolTemplate.requirements(options),
+ status : 'info'
+ });
+ } else {
+ this.visible = false;
+ self.message.update({
+ message : ''
+ });
+ }
+ }
+ });
+ if (!options.requirements || options.requirements.length == 0) {
+ requirements_button.$el.hide();
+ }
+
+ // button for version selection
+ var versions_button = new Ui.ButtonMenu({
+ icon : 'fa-cubes',
+ title : 'Versions',
+ tooltip : 'Select another tool version'
+ });
+ if (options.versions && options.versions.length > 1) {
+ for (var i in options.versions) {
+ var version = options.versions[i];
+ if (version != options.version) {
+ versions_button.addMenu({
+ title : 'Switch to ' + version,
+ version : version,
+ icon : 'fa-cube',
+ onclick : function() {
+ // here we update the tool version (some tools encode the version also in the id)
+ options.id = options.id.replace(options.version, this.version);
+ options.version = this.version;
+
+ // rebuild the model and form
+ self.deferred.reset();
+ self.deferred.execute(function(){self._buildModel()});
+ }
+ });
+ }
+ }
+ } else {
+ versions_button.$el.hide();
+ }
+
+ // button menu
+ var menu_button = new Ui.ButtonMenu({
+ icon : 'fa-caret-down',
+ title : 'Options',
+ tooltip : 'View available options'
+ });
+
+ // configure button selection
+ if(options.biostar_url) {
+ // add question option
+ menu_button.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu_button.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(options.biostar_url + '/t/' + options.id + '/');
+ }
+ });
+ };
+
+ // create share button
+ menu_button.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=' + options.id);
+ }
+ });
+
+ // add admin operations
+ if (this.is_admin) {
+ // create download button
+ menu_button.addMenu({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + options.id + '/download';
+ }
+ });
+ }
+
+ // create tool form section
+ this.section = new ToolSection.View(self, {
+ inputs : options.inputs,
+ cls : 'ui-table-plain'
+ });
+
+ // switch to classic tool form mako if the form definition is incompatible
+ if (this.incompatible) {
+ this.$el.hide();
+ $('#tool-form-classic').show();
+ return;
+ }
+
+ // create portlet
+ this.portlet = new Portlet.View({
+ icon : 'fa-wrench',
+ title : '<b>' + options.name + '</b> ' + options.description + ' (Galaxy Tool Version ' + options.version + ')',
+ cls : 'ui-portlet-slim',
+ operations: {
+ requirements : requirements_button,
+ menu : menu_button,
+ versions : versions_button
+ },
+ buttons : this.buttons
+ });
+
+ // append message
+ this.portlet.append(this.message.$el, true);
+
+ // append tool section
+ this.portlet.append(this.section.$el);
+
+ // start form
+ this.$el.empty();
+ this.$el.append(this.portlet.$el);
+
+ // append help
+ if (options.help != '') {
+ this.$el.append(ToolTemplate.help(options.help));
+ }
+
+ // append citations
+ if (options.citations) {
+ var $citations = $('<div/>');
+ var citations = new CitationModel.ToolCitationCollection();
+ citations.tool_id = options.id;
+ var citation_list_view = new CitationView.CitationListView({ el: $citations, collection: citations } );
+ citation_list_view.render();
+ citations.fetch();
+ this.$el.append($citations);
+ }
+
+ // show message if available in model
+ if (options.message) {
+ this.message.update({
+ persistent : true,
+ status : 'warning',
+ message : options.message
+ });
+ }
+ }
+ });
+});
diff -r d9b038019163bc378b72b675ddb4e1e902384b12 -r 41bad82393f1790013b09851afd6f8914500f7e2 static/scripts/mvc/tools/tools-form-workflow.js
--- /dev/null
+++ b/static/scripts/mvc/tools/tools-form-workflow.js
@@ -0,0 +1,66 @@
+/**
+ This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
+*/
+define(['utils/utils', 'mvc/tools/tools-form-base'],
+ function(Utils, ToolFormBase) {
+
+ // create form view
+ var View = ToolFormBase.extend({
+ initialize: function(options) {
+ this.workflow = true;
+ ToolFormBase.prototype.initialize.call(this, options);
+ },
+
+ /** Builds a new model through api call and recreates the entire form
+ */
+ _buildModel: function() {
+ },
+
+ /** Request a new model for an already created tool form and updates the form inputs
+ */
+ _updateModel: function() {
+ // create the request dictionary
+ var self = this;
+ var current_state = this.tree.finalize();
+
+ // log tool state
+ console.debug('tools-form-workflow::_refreshForm() - Refreshing states.');
+ console.debug(current_state);
+
+ // register process
+ var process_id = this.deferred.register();
+
+ // build model url for request
+ var model_url = galaxy_config.root + 'workflow/editor_form_post?tool_id=' + this.options.id;
+
+ // post job
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ data : current_state,
+ success : function(node) {
+ parent.update_node(node);
+
+ // process completed
+ self.deferred.done(process_id);
+
+ // log success
+ console.debug('tools-form::_refreshForm() - States refreshed.');
+ console.debug(node);
+ },
+ error : function(response) {
+ // process completed
+ self.deferred.done(process_id);
+
+ // log error
+ console.debug('tools-form::_refreshForm() - Refresh request failed.');
+ console.debug(response);
+ }
+ });
+ }
+ });
+
+ return {
+ View: View
+ };
+});
diff -r d9b038019163bc378b72b675ddb4e1e902384b12 -r 41bad82393f1790013b09851afd6f8914500f7e2 static/scripts/packed/mvc/tools/tools-form-base.js
--- /dev/null
+++ b/static/scripts/packed/mvc/tools/tools-form-base.js
@@ -0,0 +1,1 @@
+define(["utils/utils","utils/deferred","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"],function(g,h,f,k,i,a,d,c,e,j,b){return Backbone.View.extend({initialize:function(l){console.debug(l);var m=parent.Galaxy;if(m&&m.modal){this.modal=m.modal}else{this.modal=new k.Modal.View()}if(m&&m.currUser){this.is_admin=m.currUser.get("is_admin")}else{this.is_admin=false}this.options=l;this.container=this.options.container||"body";this.deferred=new h();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(l){$(this.container).empty();$(this.container).append(l)},highlight:function(m,n,l){var o=this.element_list[m];if(o){o.error(n||"Please verify this parameter.");if(!l){$(this.container).animate({scrollTop:o.$el.offset().top-20},500)}}},_buildForm:function(){var l=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new b(this);this.content=new e(this);var n=this.options;this._renderForm(n);this.tree.finalize();if(!this.workflow&&n.errors){var o=this.tree.matchResponse(n.errors);for(var m in o){this.highlight(m,o[m],true)}}this.on("refresh",function(){l.deferred.reset();l.deferred.execute(function(){l._updateModel()})});this.on("reset",function(){for(var p in this.element_list){this.element_list[p].reset()}})},_renderForm:function(u){var t=this;this.message=new k.Message();var q=new k.ButtonIcon({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;t.message.update({persistent:true,message:c.requirements(u),status:"info"})}else{this.visible=false;t.message.update({message:""})}}});if(!u.requirements||u.requirements.length==0){q.$el.hide()}var m=new k.ButtonMenu({icon:"fa-cubes",title:"Versions",tooltip:"Select another tool version"});if(u.versions&&u.versions.length>1){for(var o in u.versions){var r=u.versions[o];if(r!=u.version){m.addMenu({title:"Switch to "+r,version:r,icon:"fa-cube",onclick:function(){u.id=u.id.replace(u.version,this.version);u.version=this.version;t.deferred.reset();t.deferred.execute(function(){t._buildModel()})}})}}}else{m.$el.hide()}var p=new k.ButtonMenu({icon:"fa-caret-down",title:"Options",tooltip:"View available options"});if(u.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(u.biostar_url+"/t/"+u.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="+u.id)}});if(this.is_admin){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+u.id+"/download"}})}this.section=new j.View(t,{inputs:u.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new f.View({icon:"fa-wrench",title:"<b>"+u.name+"</b> "+u.description+" (Galaxy Tool Version "+u.version+")",cls:"ui-portlet-slim",operations:{requirements:q,menu:p,versions:m},buttons:this.buttons});this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(u.help!=""){this.$el.append(c.help(u.help))}if(u.citations){var s=$("<div/>");var l=new i.ToolCitationCollection();l.tool_id=u.id;var n=new a.CitationListView({el:s,collection:l});n.render();l.fetch();this.$el.append(s)}if(u.message){this.message.update({persistent:true,status:"warning",message:u.message})}}})});
\ No newline at end of file
diff -r d9b038019163bc378b72b675ddb4e1e902384b12 -r 41bad82393f1790013b09851afd6f8914500f7e2 static/scripts/packed/mvc/tools/tools-form-workflow.js
--- /dev/null
+++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js
@@ -0,0 +1,1 @@
+define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(d){this.workflow=true;a.prototype.initialize.call(this,d)},_buildModel:function(){},_updateModel:function(){var d=this;var e=this.tree.finalize();console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"workflow/editor_form_post?tool_id="+this.options.id;b.request({type:"GET",url:f,data:e,success:function(h){parent.update_node(h);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}});
\ 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.
1
0

commit/galaxy-central: guerler: ToolForm/Workflow: Generalize/revise tool model building process, insert form into workflow editor
by commits-noreply@bitbucket.org 11 Jan '15
by commits-noreply@bitbucket.org 11 Jan '15
11 Jan '15
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d9b038019163/
Changeset: d9b038019163
User: guerler
Date: 2015-01-11 17:02:11+00:00
Summary: ToolForm/Workflow: Generalize/revise tool model building process, insert form into workflow editor
Affected #: 36 files
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/galaxy.workflow_editor.canvas.js
--- a/client/galaxy/scripts/galaxy.workflow_editor.canvas.js
+++ b/client/galaxy/scripts/galaxy.workflow_editor.canvas.js
@@ -805,7 +805,7 @@
nodeView.addDataOutput( output );
} );
nodeView.render();
- workflow.node_changed( this );
+ workflow.node_changed( this, true);
},
update_field_data : function( data ) {
var node = this;
@@ -1094,9 +1094,9 @@
this.active_node = node;
}
},
- node_changed : function ( node ) {
+ node_changed : function ( node, force ) {
this.has_changes = true;
- if ( this.active_node == node ) {
+ if ( this.active_node == node && (!parent.__NEWTOOLFORM__ || force)) {
// Reactive with new form_html
this.check_changes_in_active_form(); //Force changes to be saved even on new connection (previously dumped)
parent.show_form_for_tool( node.form_html + node.tooltip, node );
@@ -1305,6 +1305,12 @@
return node;
}
+function update_node( data ) {
+ var node = workflow.active_node;
+ if (node) {
+ node.update_field_data(data, true);
+ }
+}
var ext_to_type = null;
var type_to_type = null;
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 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
@@ -1,79 +1,28 @@
/**
This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
*/
-define(['utils/utils', 'utils/deferred', '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(Utils, Deferred, Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/tools/tools-form-base', 'mvc/tools/tools-jobs'],
+ function(Utils, Ui, ToolFormBase, ToolJobs) {
// create form view
- var View = Backbone.View.extend({
- // base element
- container: 'body',
-
+ var View = ToolFormBase.extend({
// initialize
initialize: function(options) {
- // log options
- console.debug(options);
-
- // link galaxy modal or create one
- var galaxy = parent.Galaxy;
- if (galaxy && galaxy.modal) {
- this.modal = galaxy.modal;
- } else {
- this.modal = new Ui.Modal.View();
+ var self = this;
+ this.job_handler = new ToolJobs(this);
+ this.buttons = {
+ execute : new Ui.Button({
+ icon : 'fa-check',
+ tooltip : 'Execute: ' + options.name,
+ title : 'Execute',
+ cls : 'btn btn-primary',
+ floating : 'clear',
+ onclick : function() {
+ self.job_handler.submit();
+ }
+ })
}
-
- // check if the user is an admin
- if (galaxy && galaxy.currUser) {
- this.is_admin = galaxy.currUser.get('is_admin')
- } else {
- this.is_admin = false;
- }
-
- // link options
- this.options = options;
-
- // create deferred processing queue handler
- // this handler reduces the number of requests to the api by filtering redundant requests
- this.deferred = new Deferred();
-
- // set element
- this.setElement('<div/>');
-
- // add to main element
- $(this.container).append(this.$el);
-
- // build this form
- this._buildForm();
- },
-
- /** Shows the final message (usually upon successful job submission)
- */
- reciept: function($el) {
- $(this.container).empty();
- $(this.container).append($el);
- },
-
- /** Highlight and scroll to input element (currently only used for error notifications)
- */
- highlight: function (input_id, message, silent) {
- // get input field
- var input_element = this.element_list[input_id];
-
- // check input element
- if (input_element) {
- // mark error
- input_element.error(message || 'Please verify this parameter.');
-
- // scroll to first input element
- if (!silent) {
- $(this.container).animate({
- scrollTop: input_element.$el.offset().top - 20
- }, 500);
- }
- }
+ ToolFormBase.prototype.initialize.call(this, options);
},
/** Builds a new model through api call and recreates the entire form
@@ -250,256 +199,6 @@
console.debug(response);
}
});
- },
-
- /** Main tool form build function. This function is called once a new model is available.
- */
- _buildForm: function() {
- // link this
- var self = this;
-
- // reset events
- this.off('refresh');
- this.off('reset');
-
- // reset field list, which contains the input field elements
- this.field_list = {};
-
- // reset sequential input definition list, which contains the input definitions as provided from the api
- this.input_list = {};
-
- // reset input element list, which contains the dom elements of each input element (includes also the input field)
- this.element_list = {};
-
- // creates a tree/json data structure from the input form
- this.tree = new ToolTree(this);
-
- // creates the job handler
- this.job_handler = new ToolJobs(this);
-
- // request history content and build form
- this.content = new ToolContent(this);
-
- // link model options
- var options = this.options;
-
- // create ui elements
- this._renderForm(options);
-
- // rebuild the underlying data structure
- this.tree.finalize();
-
- // show errors
- if (options.errors) {
- var error_messages = this.tree.matchResponse(options.errors);
- for (var input_id in error_messages) {
- this.highlight(input_id, error_messages[input_id], true);
- }
- }
-
- // add refresh listener
- this.on('refresh', function() {
- // by using/reseting the deferred ajax queue the number of redundant calls is reduced
- self.deferred.reset();
- self.deferred.execute(function(){self._updateModel()});
- });
-
- // add reset listener
- this.on('reset', function() {
- for (var i in this.element_list) {
- this.element_list[i].reset();
- }
- });
- },
-
- /** Renders the UI elements required for the form
- */
- _renderForm: function(options) {
- // link this
- var self = this;
-
- // create message view
- this.message = new Ui.Message();
-
- // button for version selection
- var requirements_button = new Ui.ButtonIcon({
- icon : 'fa-info-circle',
- title : 'Requirements',
- tooltip : 'Display tool requirements',
- onclick : function() {
- if (!this.visible) {
- this.visible = true;
- self.message.update({
- persistent : true,
- message : ToolTemplate.requirements(options),
- status : 'info'
- });
- } else {
- this.visible = false;
- self.message.update({
- message : ''
- });
- }
- }
- });
- if (!options.requirements || options.requirements.length == 0) {
- requirements_button.$el.hide();
- }
-
- // button for version selection
- var versions_button = new Ui.ButtonMenu({
- icon : 'fa-cubes',
- title : 'Versions',
- tooltip : 'Select another tool version'
- });
- if (options.versions && options.versions.length > 1) {
- for (var i in options.versions) {
- var version = options.versions[i];
- if (version != options.version) {
- versions_button.addMenu({
- title : 'Switch to ' + version,
- version : version,
- icon : 'fa-cube',
- onclick : function() {
- // here we update the tool version (some tools encode the version also in the id)
- options.id = options.id.replace(options.version, this.version);
- options.version = this.version;
-
- // rebuild the model and form
- self.deferred.reset();
- self.deferred.execute(function(){self._buildModel()});
- }
- });
- }
- }
- } else {
- versions_button.$el.hide();
- }
-
- // button menu
- var menu_button = new Ui.ButtonMenu({
- icon : 'fa-caret-down',
- title : 'Options',
- tooltip : 'View available options'
- });
-
- // configure button selection
- if(options.biostar_url) {
- // add question option
- menu_button.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu_button.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(options.biostar_url + '/t/' + options.id + '/');
- }
- });
- };
-
- // create share button
- menu_button.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=' + options.id);
- }
- });
-
- // add admin operations
- if (this.is_admin) {
- // create download button
- menu_button.addMenu({
- icon : 'fa-download',
- title : 'Download',
- tooltip : 'Download this tool',
- onclick : function() {
- window.location.href = galaxy_config.root + 'api/tools/' + options.id + '/download';
- }
- });
- }
-
- // create tool form section
- this.section = new ToolSection.View(self, {
- inputs : options.inputs,
- cls : 'ui-table-plain'
- });
-
- // switch to classic tool form mako if the form definition is incompatible
- if (this.incompatible) {
- this.$el.hide();
- $('#tool-form-classic').show();
- return;
- }
-
- // create portlet
- this.portlet = new Portlet.View({
- icon : 'fa-wrench',
- title : '<b>' + options.name + '</b> ' + options.description + ' (Galaxy Tool Version ' + options.version + ')',
- cls : 'ui-portlet-slim',
- operations: {
- requirements : requirements_button,
- menu : menu_button,
- versions : versions_button
- },
- buttons: {
- execute : new Ui.Button({
- icon : 'fa-check',
- tooltip : 'Execute: ' + options.name,
- title : 'Execute',
- cls : 'btn btn-primary',
- floating : 'clear',
- onclick : function() {
- self.job_handler.submit();
- }
- })
- }
- });
-
- // append message
- this.portlet.append(this.message.$el, true);
-
- // append tool section
- this.portlet.append(this.section.$el);
-
- // start form
- this.$el.empty();
- this.$el.append(this.portlet.$el);
-
- // append help
- if (options.help != '') {
- this.$el.append(ToolTemplate.help(options.help));
- }
-
- // append citations
- if (options.citations) {
- var $citations = $('<div/>');
- var citations = new CitationModel.ToolCitationCollection();
- citations.tool_id = options.id;
- var citation_list_view = new CitationView.CitationListView({ el: $citations, collection: citations } );
- citation_list_view.render();
- citations.fetch();
- this.$el.append($citations);
- }
-
- // show message if available in model
- if (options.message) {
- this.message.update({
- persistent : true,
- status : 'warning',
- message : options.message
- });
- }
}
});
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/mvc/tools/tools-jobs.js
--- a/client/galaxy/scripts/mvc/tools/tools-jobs.js
+++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js
@@ -98,7 +98,7 @@
}
// validate non-optional fields
- if (!input_def.optional && input_field.validate && !input_field.validate()) {
+ if (!input_def.optional && input_value == null) {
this.app.highlight(input_id);
return false;
}
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -382,6 +382,11 @@
/** Data input field
*/
_fieldData : function(input_def) {
+ if (this.app.workflow) {
+ var extensions = Utils.textify(input_def.extensions.toString());
+ input_def.info = 'Data input \'' + input_def.name + '\' (' + extensions + ')';
+ return this._fieldHidden(input_def);
+ }
var self = this;
return new SelectContent.View(this.app, {
id : 'field-' + input_def.id,
@@ -398,6 +403,14 @@
/** Select/Checkbox/Radio options field
*/
_fieldSelect : function (input_def) {
+ // show text field in workflow
+ if (this.app.workflow && input_def.is_dynamic) {
+ if (!Utils.validate(input_def.value)) {
+ input_def.value = '';
+ }
+ return this._fieldText(input_def);
+ }
+
// configure options fields
var options = [];
for (var i in input_def.options) {
@@ -475,7 +488,8 @@
*/
_fieldHidden : function(input_def) {
return new Ui.Hidden({
- id : 'field-' + input_def.id
+ id : 'field-' + input_def.id,
+ info : input_def.info
});
},
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 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
@@ -36,14 +36,7 @@
this.list = {};
// error messages
- var extensions = options.extensions.toString();
- if (extensions) {
- extensions = extensions.replace(/,/g, ', ');
- var pos = extensions.lastIndexOf(', ');
- if (pos != -1) {
- extensions = extensions.substr(0, pos) + ' or ' + extensions.substr(pos+1);
- }
- }
+ var extensions = Utils.textify(options.extensions);
var hda_error = 'No dataset available.';
if (extensions) {
hda_error = 'No ' + extensions + ' dataset available.';
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/mvc/tools/tools-tree.js
--- a/client/galaxy/scripts/mvc/tools/tools-tree.js
+++ b/client/galaxy/scripts/mvc/tools/tools-tree.js
@@ -2,7 +2,7 @@
This class maps the tool form dom to an api compatible javascript dictionary.
*/
// dependencies
-define([], function() {
+define(['utils/utils'], function(Utils) {
// tool form tree
return Backbone.Model.extend({
@@ -120,7 +120,7 @@
// handle default value
if (!field.skip) {
- if (input.optional && field.validate && !field.validate()) {
+ if (field.validate && !field.validate(value)) {
value = null;
}
add (job_input_id, input.id, value);
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/mvc/ui/ui-misc.js
--- a/client/galaxy/scripts/mvc/ui/ui-misc.js
+++ b/client/galaxy/scripts/mvc/ui/ui-misc.js
@@ -412,7 +412,7 @@
initialize : function(options) {
// configure options
this.options = options;
-
+
// create new element
this.setElement(this._template(this.options));
@@ -425,14 +425,20 @@
// value
value : function (new_val) {
if (new_val !== undefined) {
- this.$el.val(new_val);
+ this.$('hidden').val(new_val);
}
- return this.$el.val();
+ return this.$('hidden').val();
},
// element
_template: function(options) {
- return '<hidden id="' + options.id + '" value="' + options.value + '"/>';
+ var tmpl = '<div id="' + options.id + '" >';
+ if (options.info) {
+ tmpl += '<label>' + options.info + '</label>';
+ }
+ tmpl += '<hidden value="' + options.value + '"/>' +
+ '</div>';
+ return tmpl;
}
});
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/mvc/ui/ui-options.js
--- a/client/galaxy/scripts/mvc/ui/ui-options.js
+++ b/client/galaxy/scripts/mvc/ui/ui-options.js
@@ -137,16 +137,7 @@
/** Validate the selected option/options
*/
validate: function() {
- var current = this.value();
- if (!(current instanceof Array)) {
- current = [current];
- }
- for (var i in current) {
- if ([null, 'null', undefined].indexOf(current[i]) > -1) {
- return false;
- }
- }
- return true;
+ return Utils.validate(this.value());
},
/** Wait message during request processing
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/mvc/ui/ui-select-default.js
--- a/client/galaxy/scripts/mvc/ui/ui-select-default.js
+++ b/client/galaxy/scripts/mvc/ui/ui-select-default.js
@@ -96,16 +96,7 @@
/** Validate the current selection
*/
validate: function() {
- var current = this.value();
- if (!(current instanceof Array)) {
- current = [current];
- }
- for (var i in current) {
- if ([null, 'null', undefined].indexOf(current[i]) > -1) {
- return false;
- }
- }
- return true;
+ return Utils.validate(this.value());
},
/** Return the label/text of the current selection
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 client/galaxy/scripts/utils/utils.js
--- a/client/galaxy/scripts/utils/utils.js
+++ b/client/galaxy/scripts/utils/utils.js
@@ -15,6 +15,40 @@
};
/**
+ * Validate atomic values or list of values
+ * usually used for selectable options
+ * @param{String} value - Value or list to be validated
+ */
+function validate (value) {
+ if (!(value instanceof Array)) {
+ value = [value];
+ }
+ for (var i in value) {
+ if (['None', null, 'null', undefined, 'undefined'].indexOf(value[i]) > -1) {
+ return false;
+ }
+ }
+ return true;
+};
+
+/**
+ * Convert list to pretty string
+ * @param{String} lst - List of strings to be converted in human readable list sentence
+ */
+function textify(lst) {
+ var lst = lst.toString();
+ if (lst) {
+ lst = lst.replace(/,/g, ', ');
+ var pos = lst.lastIndexOf(', ');
+ if (pos != -1) {
+ lst = lst.substr(0, pos) + ' or ' + lst.substr(pos+1);
+ }
+ return lst;
+ }
+ return '';
+};
+
+/**
* Request handler for GET
* @param{String} url - Url request is made to
* @param{Function} success - Callback on success
@@ -212,7 +246,9 @@
time: time,
wrap: wrap,
request: request,
- sanitize: sanitize
+ sanitize: sanitize,
+ textify: textify,
+ validate: validate
};
});
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -33,7 +33,7 @@
from galaxy.tools.actions.data_source import DataSourceToolAction
from galaxy.tools.actions.data_manager import DataManagerToolAction
from galaxy.tools.deps import build_dependency_manager
-from galaxy.tools.parameters import check_param, params_from_strings, params_to_strings
+from galaxy.tools.parameters import params_to_incoming, check_param, params_from_strings, params_to_strings
from galaxy.tools.parameters import output_collect
from galaxy.tools.parameters.basic import (BaseURLToolParameter,
DataToolParameter, HiddenToolParameter, LibraryDatasetToolParameter,
@@ -2073,6 +2073,336 @@
return tool_dict
+ def to_json (self, trans, **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
+ log.error('Failed to retrieve job.')
+ 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
+ log.error('User has no access to dataset.')
+ return { 'error': 'User has no access to dataset.' }
+ job = data.creating_job
+ if not job:
+ trans.response.status = 500
+ log.error('Creating job not found.')
+ return { 'error': 'Creating job not found.' }
+ except Exception, exception:
+ trans.response.status = 500
+ log.error('Failed to get job information.')
+ return { 'error': 'Failed to get job information.' }
+
+ # load job parameters into incoming
+ tool_message = ''
+ if job:
+ try:
+ job_params = job.get_param_values( trans.app, ignore_errors = True )
+ job_messages = self.check_and_update_param_values( job_params, trans, update_values=False )
+ tool_message = self._compare_tool_version(trans, job)
+ params_to_incoming( kwd, self.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 jsonify(v):
+ # check if value is numeric
+ isnumber = False
+ try:
+ float(v)
+ isnumber = True
+ except Exception:
+ pass
+
+ # fix hda parsing
+ if isinstance(v, trans.app.model.HistoryDatasetAssociation):
+ return {
+ 'id' : trans.security.encode_id(v.id),
+ 'src' : 'hda'
+ }
+ elif isinstance(v, bool):
+ if v is True:
+ return 'true'
+ else:
+ return 'false'
+ 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
+
+ # jsonify by type
+ if dict['type'] in ['data']:
+ if isinstance(value, list):
+ value = [ jsonify(v) for v in value ]
+ else:
+ value = [ jsonify(value) ]
+ value = { 'values': value }
+ elif isinstance(value, list):
+ value = [ jsonify(v) for v in value ]
+ else:
+ value = jsonify(value)
+
+ # update and return
+ dict['value'] = value
+ return dict
+
+ # initialize state using default parameters
+ def initialize_state(trans, inputs, state, context=None):
+ context = ExpressionContext(state, context)
+ for input in inputs.itervalues():
+ state[input.name] = input.get_initial_value(trans, context)
+
+ # check the current state of a value and update it if necessary
+ def check_state(trans, input, default_value, context):
+ value = default_value
+ error = 'State validation failed.'
+ try:
+ # resolves the inconsistent definition of boolean parameters (see base.py) without modifying shared code
+ if input.type == 'boolean' and isinstance(default_value, basestring):
+ value, error = [util.string_as_bool(default_value), None]
+ else:
+ value, error = check_param(trans, input, default_value, context)
+ except Exception, err:
+ log.error('Checking parameter failed. %s', str(err))
+ pass
+ return [value, error]
+
+ # populates state with incoming url parameters
+ def populate_state(trans, inputs, state, errors, incoming, prefix="", context=None ):
+ context = ExpressionContext(state, context)
+ for input in inputs.itervalues():
+ key = prefix + input.name
+ if input.type == 'repeat':
+ group_state = state[input.name]
+ rep_index = 0
+ del group_state[:]
+ while True:
+ rep_name = "%s_%d" % (key, rep_index)
+ if not any([incoming_key.startswith(rep_name) for incoming_key in incoming.keys()]):
+ break
+ if rep_index < input.max:
+ new_state = {}
+ new_state['__index__'] = rep_index
+ initialize_state(trans, input.inputs, new_state, context)
+ group_state.append(new_state)
+ populate_state(trans, input.inputs, new_state, errors, incoming, prefix=rep_name + "|", context=context)
+ rep_index += 1
+ elif input.type == 'conditional':
+ group_state = state[input.name]
+ group_prefix = "%s|" % ( key )
+ test_param_key = group_prefix + input.test_param.name
+ default_value = incoming.get(test_param_key, group_state.get(input.test_param.name, None))
+ value, error = check_state(trans, input.test_param, default_value, context)
+ if error:
+ errors[test_param_key] = error
+ else:
+ try:
+ current_case = input.get_current_case(value, trans)
+ group_state = state[input.name] = {}
+ initialize_state(trans, input.cases[current_case].inputs, group_state, context)
+ populate_state( trans, input.cases[current_case].inputs, group_state, errors, incoming, prefix=group_prefix, context=context)
+ group_state['__current_case__'] = current_case
+ except Exception, e:
+ errors[test_param_key] = 'The selected case is unavailable/invalid.'
+ pass
+ group_state[input.test_param.name] = value
+ else:
+ default_value = incoming.get(key, state.get(input.name, None))
+ value, error = check_state(trans, input, default_value, context)
+ if error:
+ errors[key] = error
+ state[input.name] = value
+
+ # builds tool model including all attributes
+ def iterate(group_inputs, inputs, state_inputs, other_values=None):
+ other_values = ExpressionContext( state_inputs, other_values )
+ for input_index, input in enumerate( inputs.itervalues() ):
+ # create model dictionary
+ tool_dict = input.to_dict(trans)
+ if tool_dict is None:
+ continue
+
+ # state for subsection/group
+ group_state = state_inputs[input.name]
+
+ # iterate and update values
+ if input.type == 'repeat':
+ group_cache = tool_dict['cache'] = {}
+ for i in range( len( group_state ) ):
+ group_cache[i] = {}
+ iterate( group_cache[i], input.inputs, group_state[i], other_values )
+ elif input.type == 'conditional':
+ if 'test_param' in tool_dict:
+ test_param = tool_dict['test_param']
+ test_param['value'] = jsonify(group_state[test_param['name']])
+ if '__current_case__' in group_state:
+ i = group_state['__current_case__']
+ iterate(tool_dict['cases'][i]['inputs'], input.cases[i].inputs, group_state, other_values)
+ else:
+ # create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options
+ try:
+ tool_dict = input.to_dict(trans, other_values=other_values)
+ except Exception:
+ pass
+
+ # identify name
+ input_name = tool_dict.get('name')
+ if input_name:
+ # update input value from tool state
+ if input_name in state_inputs:
+ tool_dict['value'] = state_inputs[input_name]
+
+ # sanitize if value exists
+ tool_dict = sanitize(tool_dict)
+
+ # backup final input dictionary
+ group_inputs[input_index] = tool_dict
+
+ # sanatization for the final tool state
+ def sanitize_state(state):
+ keys = None
+ if isinstance(state, dict):
+ keys = state
+ elif isinstance(state, list):
+ keys = range( len(state) )
+ if keys:
+ for k in keys:
+ if isinstance(state[k], dict) or isinstance(state[k], list):
+ sanitize_state(state[k])
+ else:
+ state[k] = jsonify(state[k])
+
+ # do param translation here, used by datasource tools
+ if self.input_translator:
+ self.input_translator.translate( params )
+
+ # initialize and populate tool state
+ state_inputs = {}
+ state_errors = {}
+ initialize_state(trans, self.inputs, state_inputs)
+ populate_state(trans, self.inputs, state_inputs, state_errors, params.__dict__)
+
+ # create basic tool model
+ tool_model = self.to_dict(trans)
+ tool_model['inputs'] = {}
+
+ # build tool model and tool state
+ iterate(tool_model['inputs'], self.inputs, state_inputs, '')
+
+ # sanitize tool state
+ sanitize_state(state_inputs)
+
+ # load tool help
+ tool_help = ''
+ if self.help:
+ tool_help = self.help
+ tool_help = tool_help.render( static_path=url_for( '/static' ), host_url=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 self.citations:
+ tool_citations = True
+
+ # get tool versions
+ tool_versions = []
+ tools = self.app.toolbox.get_loaded_tools_by_lineage(self.id)
+ for t in tools:
+ tool_versions.append(t.version)
+
+ ## add information with underlying requirements and their versions
+ tool_requirements = []
+ if self.requirements:
+ for requirement in self.requirements:
+ tool_requirements.append({
+ 'name' : requirement.name,
+ 'version' : requirement.version
+ })
+
+ # add additional properties
+ tool_model.update({
+ 'help' : tool_help,
+ 'citations' : tool_citations,
+ 'biostar_url' : trans.app.config.biostar_url,
+ 'message' : tool_message,
+ 'versions' : tool_versions,
+ 'requirements' : tool_requirements,
+ 'errors' : state_errors,
+ 'state_inputs' : state_inputs
+ })
+
+ # check for errors
+ if 'error' in tool_message:
+ return tool_message
+
+ # return enriched tool model
+ return tool_model
+
+ def _compare_tool_version( self, trans, job ):
+ """
+ Compares a tool version with the tool version from a job (from ToolRunner).
+ """
+ tool_id = job.tool_id
+ tool_version = job.tool_version
+ message = ''
+ try:
+ select_field, tools, tool = self.app.toolbox.get_tool_components( tool_id, tool_version=tool_version, get_loaded_tools_by_lineage=False, set_selected=True )
+ if tool is None:
+ trans.response.status = 500
+ return { 'error': 'This dataset was created by an obsolete tool (%s). Can\'t re-run.' % tool_id }
+ if ( self.id != tool_id and self.old_id != tool_id ) or self.version != tool_version:
+ if self.id == tool_id:
+ if tool_version == None:
+ # for some reason jobs don't always keep track of the tool version.
+ message = ''
+ else:
+ message = 'This job was initially run with tool version "%s", which is currently not available. ' % tool_version
+ if len( tools ) > 1:
+ message += 'You can re-run the job with the selected tool or choose another derivation of the tool.'
+ else:
+ message += 'You can re-run the job with this tool version, which is a derivation of the original tool.'
+ else:
+ if len( tools ) > 1:
+ message = 'This job was initially run with tool version "%s", which is currently not available. ' % tool_version
+ message += 'You can re-run the job with the selected tool or choose another derivation of the tool.'
+ else:
+ message = 'This job was initially run with tool id "%s", version "%s", which is ' % ( tool_id, tool_version )
+ message += 'currently not available. You can re-run the job with this tool, which is a derivation of the original tool.'
+ except Exception, error:
+ trans.response.status = 500
+ return { 'error': str (error) }
+
+ # can't rerun upload, external data sources, et cetera. workflow compatible will proxy this for now
+ #if not self.is_workflow_compatible:
+ # trans.response.status = 500
+ # return { 'error': 'The \'%s\' tool does currently not support re-running.' % self.name }
+ return message
+
def get_default_history_by_trans( self, trans, create=False ):
return trans.get_history( create=create )
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 lib/galaxy/webapps/galaxy/api/tools.py
--- a/lib/galaxy/webapps/galaxy/api/tools.py
+++ b/lib/galaxy/webapps/galaxy/api/tools.py
@@ -11,7 +11,7 @@
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, check_param
+from galaxy.tools.parameters import check_param
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
@@ -85,7 +85,7 @@
if not tool:
trans.response.status = 500
return { 'error': 'Could not find tool with id \'%s\'' % tool_id }
- return self._build_dict(trans, tool, kwd)
+ return tool.to_json(trans, **kwd)
@_future_expose_api
@web.require_admin
@@ -491,308 +491,3 @@
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.' }
-
- # load job parameters into incoming
- tool_message = ''
- 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 )
- tool_message = self._compare_tool_version(trans, tool, job)
- 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, bool):
- if v is True:
- return 'true'
- else:
- return 'false'
- 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'] in ['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
-
- # initialize state using default parameters
- def initialize_state(trans, inputs, state, context=None):
- context = ExpressionContext(state, context)
- for input in inputs.itervalues():
- state[input.name] = input.get_initial_value(trans, context)
-
- # check the current state of a value and update it if necessary
- def check_state(trans, input, default_value, context):
- value = default_value
- error = 'State validation failed.'
- try:
- # resolves the inconsistent definition of boolean parameters (see base.py) without modifying shared code
- if input.type == 'boolean' and isinstance(default_value, basestring):
- value, error = [util.string_as_bool(default_value), None]
- else:
- value, error = check_param(trans, input, default_value, context)
- except Exception:
- log.error('Checking parameter %s failed.', input.name)
- pass
- return [value, error]
-
- # populates state with incoming url parameters
- def populate_state(trans, inputs, state, errors, incoming, prefix="", context=None ):
- context = ExpressionContext(state, context)
- for input in inputs.itervalues():
- key = prefix + input.name
- if input.type == 'repeat':
- group_state = state[input.name]
- rep_index = 0
- del group_state[:]
- while True:
- rep_name = "%s_%d" % (key, rep_index)
- if not any([incoming_key.startswith(rep_name) for incoming_key in incoming.keys()]):
- break
- if rep_index < input.max:
- new_state = {}
- new_state['__index__'] = rep_index
- initialize_state(trans, input.inputs, new_state, context)
- group_state.append(new_state)
- populate_state(trans, input.inputs, new_state, errors, incoming, prefix=rep_name + "|", context=context)
- rep_index += 1
- elif input.type == 'conditional':
- group_state = state[input.name]
- group_prefix = "%s|" % ( key )
- test_param_key = group_prefix + input.test_param.name
- default_value = incoming.get(test_param_key, group_state.get(input.test_param.name, None))
- value, error = check_state(trans, input.test_param, default_value, context)
- if error:
- errors[test_param_key] = error
- else:
- current_case = input.get_current_case(value, trans)
- group_state = state[input.name] = {}
- initialize_state(trans, input.cases[current_case].inputs, group_state, context)
- populate_state( trans, input.cases[current_case].inputs, group_state, errors, incoming, prefix=group_prefix, context=context)
- group_state['__current_case__'] = current_case
- group_state[input.test_param.name] = value
- else:
- default_value = incoming.get(key, state.get(input.name, None))
- value, error = check_state(trans, input, default_value, context)
- if error:
- errors[key] = error
- state[input.name] = value
-
- # builds tool model including all attributes
- def iterate(group_inputs, inputs, tool_state, 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)
- if group_inputs[input_index] is None:
- continue
-
- # 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] = {}
- iterate( group_cache[i], input.inputs, group_state[i], other_values )
- elif input.type == 'conditional':
- try:
- test_param = group_inputs[input_index]['test_param']
- test_param['value'] = convert(group_state[test_param['name']])
- except Exception:
- pass
- i = group_state['__current_case__']
- iterate(group_inputs[input_index]['cases'][i]['inputs'], input.cases[i].inputs, group_state, 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_inputs = {}
- state_errors = {}
- initialize_state(trans, tool.inputs, state_inputs)
- populate_state(trans, tool.inputs, state_inputs, state_errors, 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, '')
-
- # 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
-
- # get tool versions
- tool_versions = []
- tools = self.app.toolbox.get_loaded_tools_by_lineage(tool.id)
- for t in tools:
- tool_versions.append(t.version)
-
- ## add information with underlying requirements and their versions
- tool_requirements = []
- if tool.requirements:
- for requirement in tool.requirements:
- tool_requirements.append({
- 'name' : requirement.name,
- 'version' : requirement.version
- })
-
- # add additional properties
- tool_model.update({
- 'help' : tool_help,
- 'citations' : tool_citations,
- 'biostar_url' : trans.app.config.biostar_url,
- 'message' : tool_message,
- 'versions' : tool_versions,
- 'requirements' : tool_requirements,
- 'errors' : state_errors
- })
-
- # check for errors
- if 'error' in tool_message:
- return tool_message
-
- # return enriched tool model
- return tool_model
-
- def _compare_tool_version( self, trans, tool, job ):
- """
- Compares a tool version with the tool version from a job (from ToolRunner).
- """
- tool_id = job.tool_id
- tool_version = job.tool_version
- message = ''
- try:
- select_field, tools, tool = self.app.toolbox.get_tool_components( tool_id, tool_version=tool_version, get_loaded_tools_by_lineage=False, set_selected=True )
- if tool is None:
- trans.response.status = 500
- return { 'error': 'This dataset was created by an obsolete tool (%s). Can\'t re-run.' % tool_id }
- if ( tool.id != tool_id and tool.old_id != tool_id ) or tool.version != tool_version:
- if tool.id == tool_id:
- if tool_version == None:
- # for some reason jobs don't always keep track of the tool version.
- message = ''
- else:
- message = 'This job was initially run with tool version "%s", which is currently not available. ' % tool_version
- if len( tools ) > 1:
- message += 'You can re-run the job with the selected tool or choose another derivation of the tool.'
- else:
- message += 'You can re-run the job with this tool version, which is a derivation of the original tool.'
- else:
- if len( tools ) > 1:
- message = 'This job was initially run with tool version "%s", which is currently not available. ' % tool_version
- message += 'You can re-run the job with the selected tool or choose another derivation of the tool.'
- else:
- message = 'This job was initially run with tool id "%s", version "%s", which is ' % ( tool_id, tool_version )
- message += 'currently not available. You can re-run the job with this tool, which is a derivation of the original tool.'
- except Exception, error:
- trans.response.status = 500
- return { 'error': str (error) }
-
- # can't rerun upload, external data sources, et cetera. workflow compatible will proxy this for now
- if not tool.is_workflow_compatible:
- trans.response.status = 500
- return { 'error': 'The \'%s\' tool does currently not support re-running.' % tool.name }
- return message
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -4,6 +4,7 @@
import os
import sgmllib
import urllib2
+import copy
from sqlalchemy import and_
from tool_shed.util import common_util
@@ -609,16 +610,26 @@
is selected.
"""
+ tool_state = incoming.pop('tool_state', None)
trans.workflow_building_mode = True
module = module_factory.from_dict( trans, {
'type': type,
'tool_id': tool_id,
- 'tool_state': incoming.pop("tool_state")
+ 'tool_state': tool_state
} )
+
+ # create tool model and default tool state (if missing)
+ tool_model = None
+ if not tool_state:
+ tool_model = module.tool.to_json(trans, **incoming)
+ module.state.inputs = copy.deepcopy(tool_model['state_inputs'])
+
+ # update module state
module.update_state( incoming )
-
+
if type == 'tool':
return {
+ 'tool_model': tool_model,
'tool_state': module.get_state(),
'data_inputs': module.get_data_inputs(),
'data_outputs': module.get_data_outputs(),
@@ -653,6 +664,7 @@
'name': module.get_name(),
'tool_id': module.get_tool_id(),
'tool_state': module.get_state(),
+ 'tool_model': module.tool.to_json(trans),
'tooltip': module.get_tooltip( static_path=url_for( '/static' ) ),
'data_inputs': module.get_data_inputs(),
'data_outputs': module.get_data_outputs(),
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 lib/galaxy/workflow/modules.py
--- a/lib/galaxy/workflow/modules.py
+++ b/lib/galaxy/workflow/modules.py
@@ -18,7 +18,7 @@
from galaxy.web.framework import formbuilder
from galaxy.jobs.actions.post import ActionBox
from galaxy.model import PostJobAction
-from galaxy.tools.parameters import check_param, DataToolParameter, DummyDataset, RuntimeValue, visit_input_values
+from galaxy.tools.parameters import params_to_incoming, check_param, DataToolParameter, DummyDataset, RuntimeValue, visit_input_values
from galaxy.tools.parameters import DataCollectionToolParameter
from galaxy.tools.parameters.wrapped import make_dict_copy
from galaxy.tools.execute import execute
@@ -509,7 +509,8 @@
message = "%s: using version '%s' instead of version '%s' indicated in this workflow." % ( tool_id, d.get( 'tool_version', 'Unspecified' ), module.get_tool_version() )
log.debug(message)
module.version_changes.append(message)
- module.state.decode( d[ "tool_state" ], module.tool, module.trans.app, secure=secure )
+ if d[ "tool_state" ]:
+ module.state.decode( d[ "tool_state" ], module.tool, module.trans.app, secure=secure )
module.errors = d.get( "tool_errors", None )
module.post_job_actions = d.get( "post_job_actions", {} )
module.workflow_outputs = d.get( "workflow_outputs", [] )
@@ -687,7 +688,7 @@
def get_config_form( self ):
self.add_dummy_datasets()
- return self.trans.fill_template( "workflow/editor_tool_form.mako",
+ return self.trans.fill_template( "workflow/editor_tool_form.mako", module=self,
tool=self.tool, values=self.state.inputs, errors=( self.errors or {} ) )
def encode_runtime_state( self, trans, state ):
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -805,7 +805,7 @@
nodeView.addDataOutput( output );
} );
nodeView.render();
- workflow.node_changed( this );
+ workflow.node_changed( this, true);
},
update_field_data : function( data ) {
var node = this;
@@ -1094,9 +1094,9 @@
this.active_node = node;
}
},
- node_changed : function ( node ) {
+ node_changed : function ( node, force ) {
this.has_changes = true;
- if ( this.active_node == node ) {
+ if ( this.active_node == node && (!parent.__NEWTOOLFORM__ || force)) {
// Reactive with new form_html
this.check_changes_in_active_form(); //Force changes to be saved even on new connection (previously dumped)
parent.show_form_for_tool( node.form_html + node.tooltip, node );
@@ -1305,6 +1305,12 @@
return node;
}
+function update_node( data ) {
+ var node = workflow.active_node;
+ if (node) {
+ node.update_field_data(data, true);
+ }
+}
var ext_to_type = null;
var type_to_type = null;
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -1,79 +1,28 @@
/**
This is the main class of the tool form plugin. It is referenced as 'app' in all lower level modules.
*/
-define(['utils/utils', 'utils/deferred', '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(Utils, Deferred, Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/tools/tools-form-base', 'mvc/tools/tools-jobs'],
+ function(Utils, Ui, ToolFormBase, ToolJobs) {
// create form view
- var View = Backbone.View.extend({
- // base element
- container: 'body',
-
+ var View = ToolFormBase.extend({
// initialize
initialize: function(options) {
- // log options
- console.debug(options);
-
- // link galaxy modal or create one
- var galaxy = parent.Galaxy;
- if (galaxy && galaxy.modal) {
- this.modal = galaxy.modal;
- } else {
- this.modal = new Ui.Modal.View();
+ var self = this;
+ this.job_handler = new ToolJobs(this);
+ this.buttons = {
+ execute : new Ui.Button({
+ icon : 'fa-check',
+ tooltip : 'Execute: ' + options.name,
+ title : 'Execute',
+ cls : 'btn btn-primary',
+ floating : 'clear',
+ onclick : function() {
+ self.job_handler.submit();
+ }
+ })
}
-
- // check if the user is an admin
- if (galaxy && galaxy.currUser) {
- this.is_admin = galaxy.currUser.get('is_admin')
- } else {
- this.is_admin = false;
- }
-
- // link options
- this.options = options;
-
- // create deferred processing queue handler
- // this handler reduces the number of requests to the api by filtering redundant requests
- this.deferred = new Deferred();
-
- // set element
- this.setElement('<div/>');
-
- // add to main element
- $(this.container).append(this.$el);
-
- // build this form
- this._buildForm();
- },
-
- /** Shows the final message (usually upon successful job submission)
- */
- reciept: function($el) {
- $(this.container).empty();
- $(this.container).append($el);
- },
-
- /** Highlight and scroll to input element (currently only used for error notifications)
- */
- highlight: function (input_id, message, silent) {
- // get input field
- var input_element = this.element_list[input_id];
-
- // check input element
- if (input_element) {
- // mark error
- input_element.error(message || 'Please verify this parameter.');
-
- // scroll to first input element
- if (!silent) {
- $(this.container).animate({
- scrollTop: input_element.$el.offset().top - 20
- }, 500);
- }
- }
+ ToolFormBase.prototype.initialize.call(this, options);
},
/** Builds a new model through api call and recreates the entire form
@@ -250,256 +199,6 @@
console.debug(response);
}
});
- },
-
- /** Main tool form build function. This function is called once a new model is available.
- */
- _buildForm: function() {
- // link this
- var self = this;
-
- // reset events
- this.off('refresh');
- this.off('reset');
-
- // reset field list, which contains the input field elements
- this.field_list = {};
-
- // reset sequential input definition list, which contains the input definitions as provided from the api
- this.input_list = {};
-
- // reset input element list, which contains the dom elements of each input element (includes also the input field)
- this.element_list = {};
-
- // creates a tree/json data structure from the input form
- this.tree = new ToolTree(this);
-
- // creates the job handler
- this.job_handler = new ToolJobs(this);
-
- // request history content and build form
- this.content = new ToolContent(this);
-
- // link model options
- var options = this.options;
-
- // create ui elements
- this._renderForm(options);
-
- // rebuild the underlying data structure
- this.tree.finalize();
-
- // show errors
- if (options.errors) {
- var error_messages = this.tree.matchResponse(options.errors);
- for (var input_id in error_messages) {
- this.highlight(input_id, error_messages[input_id], true);
- }
- }
-
- // add refresh listener
- this.on('refresh', function() {
- // by using/reseting the deferred ajax queue the number of redundant calls is reduced
- self.deferred.reset();
- self.deferred.execute(function(){self._updateModel()});
- });
-
- // add reset listener
- this.on('reset', function() {
- for (var i in this.element_list) {
- this.element_list[i].reset();
- }
- });
- },
-
- /** Renders the UI elements required for the form
- */
- _renderForm: function(options) {
- // link this
- var self = this;
-
- // create message view
- this.message = new Ui.Message();
-
- // button for version selection
- var requirements_button = new Ui.ButtonIcon({
- icon : 'fa-info-circle',
- title : 'Requirements',
- tooltip : 'Display tool requirements',
- onclick : function() {
- if (!this.visible) {
- this.visible = true;
- self.message.update({
- persistent : true,
- message : ToolTemplate.requirements(options),
- status : 'info'
- });
- } else {
- this.visible = false;
- self.message.update({
- message : ''
- });
- }
- }
- });
- if (!options.requirements || options.requirements.length == 0) {
- requirements_button.$el.hide();
- }
-
- // button for version selection
- var versions_button = new Ui.ButtonMenu({
- icon : 'fa-cubes',
- title : 'Versions',
- tooltip : 'Select another tool version'
- });
- if (options.versions && options.versions.length > 1) {
- for (var i in options.versions) {
- var version = options.versions[i];
- if (version != options.version) {
- versions_button.addMenu({
- title : 'Switch to ' + version,
- version : version,
- icon : 'fa-cube',
- onclick : function() {
- // here we update the tool version (some tools encode the version also in the id)
- options.id = options.id.replace(options.version, this.version);
- options.version = this.version;
-
- // rebuild the model and form
- self.deferred.reset();
- self.deferred.execute(function(){self._buildModel()});
- }
- });
- }
- }
- } else {
- versions_button.$el.hide();
- }
-
- // button menu
- var menu_button = new Ui.ButtonMenu({
- icon : 'fa-caret-down',
- title : 'Options',
- tooltip : 'View available options'
- });
-
- // configure button selection
- if(options.biostar_url) {
- // add question option
- menu_button.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu_button.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(options.biostar_url + '/t/' + options.id + '/');
- }
- });
- };
-
- // create share button
- menu_button.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=' + options.id);
- }
- });
-
- // add admin operations
- if (this.is_admin) {
- // create download button
- menu_button.addMenu({
- icon : 'fa-download',
- title : 'Download',
- tooltip : 'Download this tool',
- onclick : function() {
- window.location.href = galaxy_config.root + 'api/tools/' + options.id + '/download';
- }
- });
- }
-
- // create tool form section
- this.section = new ToolSection.View(self, {
- inputs : options.inputs,
- cls : 'ui-table-plain'
- });
-
- // switch to classic tool form mako if the form definition is incompatible
- if (this.incompatible) {
- this.$el.hide();
- $('#tool-form-classic').show();
- return;
- }
-
- // create portlet
- this.portlet = new Portlet.View({
- icon : 'fa-wrench',
- title : '<b>' + options.name + '</b> ' + options.description + ' (Galaxy Tool Version ' + options.version + ')',
- cls : 'ui-portlet-slim',
- operations: {
- requirements : requirements_button,
- menu : menu_button,
- versions : versions_button
- },
- buttons: {
- execute : new Ui.Button({
- icon : 'fa-check',
- tooltip : 'Execute: ' + options.name,
- title : 'Execute',
- cls : 'btn btn-primary',
- floating : 'clear',
- onclick : function() {
- self.job_handler.submit();
- }
- })
- }
- });
-
- // append message
- this.portlet.append(this.message.$el, true);
-
- // append tool section
- this.portlet.append(this.section.$el);
-
- // start form
- this.$el.empty();
- this.$el.append(this.portlet.$el);
-
- // append help
- if (options.help != '') {
- this.$el.append(ToolTemplate.help(options.help));
- }
-
- // append citations
- if (options.citations) {
- var $citations = $('<div/>');
- var citations = new CitationModel.ToolCitationCollection();
- citations.tool_id = options.id;
- var citation_list_view = new CitationView.CitationListView({ el: $citations, collection: citations } );
- citation_list_view.render();
- citations.fetch();
- this.$el.append($citations);
- }
-
- // show message if available in model
- if (options.message) {
- this.message.update({
- persistent : true,
- status : 'warning',
- message : options.message
- });
- }
}
});
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/tools/tools-jobs.js
--- a/static/scripts/mvc/tools/tools-jobs.js
+++ b/static/scripts/mvc/tools/tools-jobs.js
@@ -98,7 +98,7 @@
}
// validate non-optional fields
- if (!input_def.optional && input_field.validate && !input_field.validate()) {
+ if (!input_def.optional && input_value == null) {
this.app.highlight(input_id);
return false;
}
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -382,6 +382,11 @@
/** Data input field
*/
_fieldData : function(input_def) {
+ if (this.app.workflow) {
+ var extensions = Utils.textify(input_def.extensions.toString());
+ input_def.info = 'Data input \'' + input_def.name + '\' (' + extensions + ')';
+ return this._fieldHidden(input_def);
+ }
var self = this;
return new SelectContent.View(this.app, {
id : 'field-' + input_def.id,
@@ -398,6 +403,14 @@
/** Select/Checkbox/Radio options field
*/
_fieldSelect : function (input_def) {
+ // show text field in workflow
+ if (this.app.workflow && input_def.is_dynamic) {
+ if (!Utils.validate(input_def.value)) {
+ input_def.value = '';
+ }
+ return this._fieldText(input_def);
+ }
+
// configure options fields
var options = [];
for (var i in input_def.options) {
@@ -475,7 +488,8 @@
*/
_fieldHidden : function(input_def) {
return new Ui.Hidden({
- id : 'field-' + input_def.id
+ id : 'field-' + input_def.id,
+ info : input_def.info
});
},
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 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
@@ -36,14 +36,7 @@
this.list = {};
// error messages
- var extensions = options.extensions.toString();
- if (extensions) {
- extensions = extensions.replace(/,/g, ', ');
- var pos = extensions.lastIndexOf(', ');
- if (pos != -1) {
- extensions = extensions.substr(0, pos) + ' or ' + extensions.substr(pos+1);
- }
- }
+ var extensions = Utils.textify(options.extensions);
var hda_error = 'No dataset available.';
if (extensions) {
hda_error = 'No ' + extensions + ' dataset available.';
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/tools/tools-tree.js
--- a/static/scripts/mvc/tools/tools-tree.js
+++ b/static/scripts/mvc/tools/tools-tree.js
@@ -2,7 +2,7 @@
This class maps the tool form dom to an api compatible javascript dictionary.
*/
// dependencies
-define([], function() {
+define(['utils/utils'], function(Utils) {
// tool form tree
return Backbone.Model.extend({
@@ -120,7 +120,7 @@
// handle default value
if (!field.skip) {
- if (input.optional && field.validate && !field.validate()) {
+ if (field.validate && !field.validate(value)) {
value = null;
}
add (job_input_id, input.id, value);
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/ui/ui-misc.js
--- a/static/scripts/mvc/ui/ui-misc.js
+++ b/static/scripts/mvc/ui/ui-misc.js
@@ -412,7 +412,7 @@
initialize : function(options) {
// configure options
this.options = options;
-
+
// create new element
this.setElement(this._template(this.options));
@@ -425,14 +425,20 @@
// value
value : function (new_val) {
if (new_val !== undefined) {
- this.$el.val(new_val);
+ this.$('hidden').val(new_val);
}
- return this.$el.val();
+ return this.$('hidden').val();
},
// element
_template: function(options) {
- return '<hidden id="' + options.id + '" value="' + options.value + '"/>';
+ var tmpl = '<div id="' + options.id + '" >';
+ if (options.info) {
+ tmpl += '<label>' + options.info + '</label>';
+ }
+ tmpl += '<hidden value="' + options.value + '"/>' +
+ '</div>';
+ return tmpl;
}
});
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/ui/ui-options.js
--- a/static/scripts/mvc/ui/ui-options.js
+++ b/static/scripts/mvc/ui/ui-options.js
@@ -137,16 +137,7 @@
/** Validate the selected option/options
*/
validate: function() {
- var current = this.value();
- if (!(current instanceof Array)) {
- current = [current];
- }
- for (var i in current) {
- if ([null, 'null', undefined].indexOf(current[i]) > -1) {
- return false;
- }
- }
- return true;
+ return Utils.validate(this.value());
},
/** Wait message during request processing
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/mvc/ui/ui-select-default.js
--- a/static/scripts/mvc/ui/ui-select-default.js
+++ b/static/scripts/mvc/ui/ui-select-default.js
@@ -96,16 +96,7 @@
/** Validate the current selection
*/
validate: function() {
- var current = this.value();
- if (!(current instanceof Array)) {
- current = [current];
- }
- for (var i in current) {
- if ([null, 'null', undefined].indexOf(current[i]) > -1) {
- return false;
- }
- }
- return true;
+ return Utils.validate(this.value());
},
/** Return the label/text of the current selection
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.css("color","red")}},onMouseLeave:function(a){this.$el.css("color","black")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasConnectedOutputTerminals()&&!this.node.hasConnectedMappedInputTerminals()){_.each(this.node.mappedInputTerminals(),function(b){b.resetMappingIfNeeded()})}var a=!this.node.hasMappedOverInputTerminals();if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(this._collectionAttached()){inputsFilled=true}else{a=false}}else{a=true}}return a},_collectionAttached:function(){if(!this.connected()){return false}else{var a=this.connectors[0].handle1;if(!a){return false}else{if(a.isDataCollectionInput||a.isMappedOver()||a.datatypes.indexOf("input_collection")>0){return true}else{return false}}}},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(this.connected()&&!this._collectionAttached()){return false}if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(b){var a=[];$.each(b,function(c,d){if(d.connectors.length>0){a.push(d)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){a.push(d)}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.label=b.label;this.uuid=b.uuid;this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,uuid:f.uuid,label:f.label,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(b,c){var a=c.proxy.terminal.connectors[0];if(a){a.destroy()}$(c.proxy).remove();$(c.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+function CollectionTypeDescription(a){this.collectionType=a;this.isCollection=true;this.rank=a.split(":").length}$.extend(CollectionTypeDescription.prototype,{append:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return this}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return otherCollectionType}return new CollectionTypeDescription(this.collectionType+":"+a.collectionType)},canMatch:function(a){if(a===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(a===ANY_COLLECTION_TYPE_DESCRIPTION){return true}return a.collectionType==this.collectionType},canMapOver:function(b){if(b===NULL_COLLECTION_TYPE_DESCRIPTION){return false}if(b===ANY_COLLECTION_TYPE_DESCRIPTION){return false}if(this.rank<=b.rank){return false}var a=b.collectionType;return this._endsWith(this.collectionType,a)},effectiveMapOver:function(a){var c=a.collectionType;var b=this.collectionType.substring(0,this.collectionType.length-c.length-1);return new CollectionTypeDescription(b)},equal:function(a){return a.collectionType==this.collectionType},toString:function(){return"CollectionType["+this.collectionType+"]"},_endsWith:function(b,a){return b.indexOf(a,b.length-a.length)!==-1}});NULL_COLLECTION_TYPE_DESCRIPTION={isCollection:false,canMatch:function(a){return false},canMapOver:function(a){return false},toString:function(){return"NullCollectionType[]"},append:function(a){return a},equal:function(a){return a===this}};ANY_COLLECTION_TYPE_DESCRIPTION={isCollection:true,canMatch:function(a){return NULL_COLLECTION_TYPE_DESCRIPTION!==a},canMapOver:function(a){return false},toString:function(){return"AnyCollectionType[]"},append:function(a){throw"Cannot append to ANY_COLLECTION_TYPE_DESCRIPTION"},equal:function(a){return a===this}};var TerminalMapping=Backbone.Model.extend({initialize:function(a){this.mapOver=a.mapOver||NULL_COLLECTION_TYPE_DESCRIPTION;this.terminal=a.terminal;this.terminal.terminalMapping=this},disableMapOver:function(){this.setMapOver(NULL_COLLECTION_TYPE_DESCRIPTION)},setMapOver:function(a){this.mapOver=a;this.trigger("change")}});var TerminalMappingView=Backbone.View.extend({tagName:"div",className:"fa-icon-button fa fa-folder-o",initialize:function(b){var a="Run tool in parallel over collection";this.$el.tooltip({delay:500,title:a});this.model.bind("change",_.bind(this.render,this))},render:function(){if(this.model.mapOver.isCollection){this.$el.show()}else{this.$el.hide()}},});var InputTerminalMappingView=TerminalMappingView.extend({events:{click:"onClick",mouseenter:"onMouseEnter",mouseleave:"onMouseLeave",},onMouseEnter:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){this.$el.css("color","red")}},onMouseLeave:function(a){this.$el.css("color","black")},onClick:function(b){var a=this.model;if(!a.terminal.connected()&&a.mapOver.isCollection){a.terminal.resetMapping()}},});var InputTerminalMapping=TerminalMapping;var InputCollectionTerminalMapping=TerminalMapping;var OutputTerminalMapping=TerminalMapping;var OutputTerminalMappingView=TerminalMappingView;var InputCollectionTerminalMappingView=InputTerminalMappingView;var OutputCollectionTerminalMapping=TerminalMapping;var OutputCollectionTerminalMappingView=TerminalMappingView;var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged();this.resetMappingIfNeeded()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})},destroyInvalidConnections:function(){_.each(this.connectors,function(a){a.destroyIfInvalid()})},setMapOver:function(a){if(this.multiple){return}if(!this.mapOver().equal(a)){this.terminalMapping.setMapOver(a);_.each(this.node.output_terminals,function(b){b.setMapOver(a)})}},mapOver:function(){if(!this.terminalMapping){return NULL_COLLECTION_TYPE_DESCRIPTION}else{return this.terminalMapping.mapOver}},isMappedOver:function(){return this.terminalMapping&&this.terminalMapping.mapOver.isCollection},resetMapping:function(){this.terminalMapping.disableMapOver()},resetMappingIfNeeded:function(){},});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes},resetMappingIfNeeded:function(){if(!this.node.hasConnectedOutputTerminals()&&!this.node.hasConnectedMappedInputTerminals()){_.each(this.node.mappedInputTerminals(),function(b){b.resetMappingIfNeeded()})}var a=!this.node.hasMappedOverInputTerminals();if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();_.each(this.connectors,function(a){var b=a.handle2;if(b){b.resetMappingIfNeeded();a.destroyIfInvalid()}})}});var BaseInputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.update(a.input)},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},resetMappingIfNeeded:function(){var b=this.mapOver();if(!b.isCollection){return}var a=this.node.hasConnectedMappedInputTerminals()||(!this.node.hasConnectedOutputTerminals());if(a){this.resetMapping()}},resetMapping:function(){this.terminalMapping.disableMapOver();if(!this.node.hasMappedOverInputTerminals()){_.each(this.node.output_terminals,function(a){a.resetMapping()})}},connected:function(){return this.connectors.length!==0},_inputFilled:function(){var a;if(!this.connected()){a=false}else{if(this.multiple){if(this._collectionAttached()){inputsFilled=true}else{a=false}}else{a=true}}return a},_collectionAttached:function(){if(!this.connected()){return false}else{var a=this.connectors[0].handle1;if(!a){return false}else{if(a.isDataCollectionInput||a.isMappedOver()||a.datatypes.indexOf("input_collection")>0){return true}else{return false}}}},_mappingConstraints:function(){if(!this.node){return[]}var b=this.mapOver();if(b.isCollection){return[b]}var a=[];if(!this.node.hasConnectedOutputTerminals()){_.each(this.node.connectedMappedInputTerminals(),function(c){a.push(c.mapOver())})}else{a.push(_.first(_.values(this.node.output_terminals)).mapOver())}return a},_producesAcceptableDatatype:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){var h=f[b];if(h=="input"||h=="input_collection"||issubtype(f[b],this.datatypes[c])){return true}}}return false},_otherCollectionType:function(a){var c=NULL_COLLECTION_TYPE_DESCRIPTION;if(a.isDataCollectionInput){c=a.collectionType}else{var b=a.mapOver();if(b.isCollection){c=b}}return c},});var InputTerminal=BaseInputTerminal.extend({update:function(a){this.datatypes=a.extensions;this.multiple=a.multiple;this.collection=false},connect:function(a){BaseInputTerminal.prototype.connect.call(this,a);var b=a.handle1;if(!b){return}var c=this._otherCollectionType(b);if(c.isCollection){this.setMapOver(c)}},attachable:function(b){var d=this._otherCollectionType(b);var a=this.mapOver();if(d.isCollection){if(this.multiple){if(this.connected()&&!this._collectionAttached()){return false}if(d.rank==1){return this._producesAcceptableDatatype(b)}else{return false}}if(a.isCollection&&a.canMatch(d)){return this._producesAcceptableDatatype(b)}else{var c=this._mappingConstraints();if(c.every(_.bind(d.canMatch,d))){return this._producesAcceptableDatatype(b)}else{return false}}}else{if(a.isCollection){return false}}return this._producesAcceptableDatatype(b)}});var InputCollectionTerminal=BaseInputTerminal.extend({update:function(a){this.multiple=false;this.collection=true;this.datatypes=a.extensions;if(a.collection_type){this.collectionType=new CollectionTypeDescription(a.collection_type)}else{this.collectionType=ANY_COLLECTION_TYPE_DESCRIPTION}},connect:function(b){BaseInputTerminal.prototype.connect.call(this,b);var a=b.handle1;if(!a){return}var c=this._effectiveMapOver(a);this.setMapOver(c)},_effectiveMapOver:function(a){var b=this.collectionType;var c=this._otherCollectionType(a);if(!b.canMatch(c)){return c.effectiveMapOver(b)}else{return NULL_COLLECTION_TYPE_DESCRIPTION}},_effectiveCollectionType:function(){var b=this.collectionType;var a=this.mapOver();return a.append(b)},attachable:function(b){var g=this._otherCollectionType(b);if(g.isCollection){var f=this._effectiveCollectionType();var a=this.mapOver();if(f.canMatch(g)){return this._producesAcceptableDatatype(b)}else{if(a.isCollection){return false}else{if(g.canMapOver(this.collectionType)){var d=this._effectiveMapOver(b);if(!d.isCollection){return false}var c=this._mappingConstraints();if(c.every(d.canMatch)){return this._producesAcceptableDatatype(b)}}}}}return false}});var OutputCollectionTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.collectionType=new CollectionTypeDescription(a.collection_type);this.isDataCollectionInput=true},update:function(a){var b=new CollectionTypeDescription(a.collection_type);if(b.collectionType!=this.collectionType.collectionType){_.each(this.connectors,function(c){c.destroy()})}this.collectionType=b}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},destroyIfInvalid:function(){if(this.handle1&&this.handle2&&!this.handle2.attachable(this.handle1)){this.destroy()}},redraw:function(){var f=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}f.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var v=function(c){return $(c).offset().left-f.offset().left};var p=function(c){return $(c).offset().top-f.offset().top};if(!this.handle1||!this.handle2){return}var o=v(this.handle1.element)+5;var n=p(this.handle1.element)+5;var x=v(this.handle2.element)+5;var u=p(this.handle2.element)+5;var k=100;var r=Math.min(o,x);var a=Math.max(o,x);var q=Math.min(n,u);var B=Math.max(n,u);var d=Math.min(Math.max(Math.abs(B-q)/2,100),300);var w=r-k;var A=q-k;var y=a-r+2*k;var s=B-q+2*k;this.canvas.style.left=w+"px";this.canvas.style.top=A+"px";this.canvas.setAttribute("width",y);this.canvas.setAttribute("height",s);o-=w;n-=A;x-=w;u-=A;var z=this.canvas.getContext("2d"),h=null,l=null;var g=1;if(this.handle1&&this.handle1.isMappedOver()){var h=[-6,-3,0,3,6];g=5}else{var h=[0]}if(this.handle2&&this.handle2.isMappedOver()){var l=[-6,-3,0,3,6];g=5}else{var l=[0]}var b=this;for(var t=0;t<g;t++){var m=5,j=7;if(h.length>1||l.length>1){m=1;j=3}b.draw_outlined_curve(o,n,x,u,d,m,j,h[t%h.length],l[t%l.length])}},draw_outlined_curve:function(j,i,l,k,a,b,f,g,d){var g=g||0;var d=d||0;var h=this.canvas.getContext("2d");h.lineCap="round";h.strokeStyle=this.outer_color;h.lineWidth=f;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke();h.strokeStyle=this.inner_color;h.lineWidth=b;h.beginPath();h.moveTo(j,i+g);h.bezierCurveTo(j+a,i+g,l-a,k+d,l,k+d);h.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},connectedOutputTerminals:function(){return this._connectedTerminals(this.output_terminals)},_connectedTerminals:function(b){var a=[];$.each(b,function(c,d){if(d.connectors.length>0){a.push(d)}});return a},hasConnectedOutputTerminals:function(){var a=this.output_terminals;for(var b in a){if(a[b].connectors.length>0){return true}}return false},connectedMappedInputTerminals:function(){return this._connectedMappedTerminals(this.input_terminals)},hasConnectedMappedInputTerminals:function(){var c=this.input_terminals;for(var b in c){var a=c[b];if(a.connectors.length>0&&a.isMappedOver()){return true}}return false},_connectedMappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){if(d.connectors.length>0){a.push(d)}}});return a},mappedInputTerminals:function(){return this._mappedTerminals(this.input_terminals)},_mappedTerminals:function(b){var a=[];$.each(b,function(c,d){var f=d.mapOver();if(f.isCollection){a.push(d)}});return a},hasMappedOverInputTerminals:function(){var a=false;_.each(this.input_terminals,function(b){var c=b.mapOver();if(c.isCollection){a=true}});return a},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.label=b.label;this.uuid=b.uuid;this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this,true)},update_field_data:function(d){var c=this;nodeView=c.nodeView;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;if("post_job_actions" in d){var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{}}c.nodeView.renderToolErrors();var g=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();var b={};_.each(d.data_inputs,function(h){var i=c.nodeView.addDataInput(h,a);b[h.name]=i});_.each(_.difference(_.values(nodeView.terminalViews),_.values(b)),function(h){h.el.terminal.destroy()});nodeView.terminalViews=b;if(d.data_outputs.length==1&&"collection_type" in d.data_outputs[0]){nodeView.updateDataOutput(d.data_outputs[0])}g.replaceWith(a);this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,uuid:f.uuid,label:f.label,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a,b){this.has_changes=true;if(this.active_node==a&&(!parent.__NEWTOOLFORM__||b)){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}function update_node(b){var a=workflow.active_node;if(a){a.update_field_data(b,true)}}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body);this.terminalViews={};this.outputTerminlViews={}},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(i,d){var j=true;if(!d){d=this.$(".inputs");j=false}var f=this.terminalViews[i.name];var h=(i.input_type=="dataset_collection")?InputCollectionTerminalView:InputTerminalView;if(f&&!(f instanceof h)){f.el.terminal.destroy();f=null}if(!f){f=new h({node:this.node,input:i})}else{var g=f.el.terminal;g.update(i);g.destroyInvalidConnections()}this.terminalViews[i.name]=f;var c=f.el;var b=new DataInputView({terminalElement:c,input:i,nodeView:this,skipResize:j});var a=b.$el;d.append(a.prepend(f.terminalElements()));return f},addDataOutput:function(a){var d=(a.collection_type)?OutputCollectionTerminalView:OutputTerminalView;var c=new d({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(c.terminalElements()))},updateDataOutput:function(b){var a=this.node.output_terminals[b.name];a.update(b)}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var f=this.nodeView.node;var d=a.extensions.indexOf("input")>=0||a.extensions.indexOf("input_collection")>=0;if(!d){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(f.type=="tool"){var g=new OutputCalloutView({label:b,output:a,node:f,});this.$el.append(g.el);this.$el.hover(function(){g.hoverImage()},function(){g.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var TerminalView=Backbone.View.extend({setupMappingView:function(b){var c=new this.terminalMappingClass({terminal:b});var a=new this.terminalMappingViewClass({model:c});a.render();b.terminalMappingView=a;this.terminalMappingView=a},terminalElements:function(){if(this.terminalMappingView){return[this.terminalMappingView.el,this.el]}else{return[this.el]}}});var BaseInputTerminalView=TerminalView.extend({className:"terminal input-terminal",initialize:function(c){var f=c.node;var a=c.input;var b=a.name;var d=this.terminalForInput(a);if(!d.multiple){this.setupMappingView(d)}this.el.terminal=d;d.node=f;d.name=b;f.input_terminals[b]=d},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var InputTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputTerminalMapping,terminalMappingViewClass:InputTerminalMappingView,terminalForInput:function(a){return new InputTerminal({element:this.el,input:a})},});var InputCollectionTerminalView=BaseInputTerminalView.extend({terminalMappingClass:InputCollectionTerminalMapping,terminalMappingViewClass:InputCollectionTerminalMappingView,terminalForInput:function(a){return new InputCollectionTerminal({element:this.el,input:a})},});var BaseOutputTerminalView=TerminalView.extend({className:"terminal output-terminal",initialize:function(c){var f=c.node;var a=c.output;var b=a.name;var d=this.terminalForOutput(a);this.setupMappingView(d);this.el.terminal=d;d.node=f;d.name=b;f.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(b,c){var a=c.proxy.terminal.connectors[0];if(a){a.destroy()}$(c.proxy).remove();$(c.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});var OutputTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputTerminalMapping,terminalMappingViewClass:OutputTerminalMappingView,terminalForOutput:function(a){var c=a.extensions;var b=new OutputTerminal({element:this.el,datatypes:c});return b},});var OutputCollectionTerminalView=BaseOutputTerminalView.extend({terminalMappingClass:OutputCollectionTerminalMapping,terminalMappingViewClass:OutputCollectionTerminalMappingView,terminalForOutput:function(a){var c=a.collection_type;var b=new OutputCollectionTerminal({element:this.el,collection_type:c,datatypes:a.extensions});return b},});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 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","utils/deferred","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,j,h,m,k,a,e,d,f,l,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var o=parent.Galaxy;if(o&&o.modal){this.modal=o.modal}else{this.modal=new m.Modal.View()}if(o&&o.currUser){this.is_admin=o.currUser.get("is_admin")}else{this.is_admin=false}this.options=n;this.deferred=new j();this.setElement("<div/>");$(this.container).append(this.$el);this._buildForm()},reciept:function(n){$(this.container).empty();$(this.container).append(n)},highlight:function(o,p,n){var q=this.element_list[o];if(q){q.error(p||"Please verify this parameter.");if(!n){$(this.container).animate({scrollTop:q.$el.offset().top-20},500)}}},_buildModel:function(){var n=this;var o=galaxy_config.root+"api/tools/"+this.options.id+"/build?";if(this.options.job_id){o+="job_id="+this.options.job_id}else{if(this.options.dataset_id){o+="dataset_id="+this.options.dataset_id}else{o+="tool_version="+this.options.version+"&";var q=top.location.href;var r=q.indexOf("?");if(q.indexOf("tool_id=")!=-1&&r!==-1){o+=q.slice(r+1)}}}var p=this.deferred.register();i.request({type:"GET",url:o,success:function(s){n.options=s;n._buildForm();n.message.update({status:"success",message:"Now you are using '"+n.options.name+"' version "+n.options.version+".",persistent:false});n.deferred.done(p);console.debug("tools-form::initialize() - Initial tool model ready.");console.debug(s)},error:function(s){n.deferred.done(p);console.debug("tools-form::initialize() - Initial tool model request failed.");console.debug(s);var t=s.error||"Uncaught error.";n.modal.show({title:"Tool cannot be executed",body:t,buttons:{Close:function(){n.modal.hide()}}})}})},_updateModel:function(){var n=this;var o=this.tree.finalize({data:function(s){if(s.values.length>0&&s.values[0]&&s.values[0].src==="hda"){return n.content.get({id:s.values[0].id,src:"hda"}).id_uncoded}return null}});console.debug("tools-form::_refreshForm() - Refreshing states.");console.debug(o);function r(v){for(var t in n.input_list){var u=n.field_list[t];var s=n.input_list[t];if(s.is_dynamic&&u.wait&&u.unwait){if(v){u.wait()}else{u.unwait()}}}}r(true);var q=this.deferred.register();var p=galaxy_config.root+"api/tools/"+this.options.id+"/build?tool_version="+this.options.version;i.request({type:"GET",url:p,data:o,success:function(s){n.tree.matchModel(s,function(u,y){var t=n.input_list[u];if(t&&t.options){if(!_.isEqual(t.options,y.options)){t.options=y.options;var z=n.field_list[u];if(z.update){var x=[];if((["data","data_collection","drill_down"]).indexOf(t.type)!=-1){x=t.options}else{for(var w in y.options){var v=y.options[w];if(v.length>2){x.push({label:v[0],value:v[1]})}}}z.update(x);z.trigger("change");console.debug("Updating options for "+u)}}}});r(false);n.deferred.done(q);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(s)},error:function(s){n.deferred.done(q);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(s)}})},_buildForm:function(){var n=this;this.off("refresh");this.off("reset");this.field_list={};this.input_list={};this.element_list={};this.tree=new c(this);this.job_handler=new g(this);this.content=new f(this);var p=this.options;this._renderForm(p);this.tree.finalize();if(p.errors){var q=this.tree.matchResponse(p.errors);for(var o in q){this.highlight(o,q[o],true)}}this.on("refresh",function(){n.deferred.reset();n.deferred.execute(function(){n._updateModel()})});this.on("reset",function(){for(var r in this.element_list){this.element_list[r].reset()}})},_renderForm:function(w){var v=this;this.message=new m.Message();var s=new m.ButtonIcon({icon:"fa-info-circle",title:"Requirements",tooltip:"Display tool requirements",onclick:function(){if(!this.visible){this.visible=true;v.message.update({persistent:true,message:d.requirements(w),status:"info"})}else{this.visible=false;v.message.update({message:""})}}});if(!w.requirements||w.requirements.length==0){s.$el.hide()}var o=new m.ButtonMenu({icon:"fa-cubes",title:"Versions",tooltip:"Select another tool version"});if(w.versions&&w.versions.length>1){for(var q in w.versions){var t=w.versions[q];if(t!=w.version){o.addMenu({title:"Switch to "+t,version:t,icon:"fa-cube",onclick:function(){w.id=w.id.replace(w.version,this.version);w.version=this.version;v.deferred.reset();v.deferred.execute(function(){v._buildModel()})}})}}}else{o.$el.hide()}var r=new m.ButtonMenu({icon:"fa-caret-down",title:"Options",tooltip:"View available options"});if(w.biostar_url){r.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(w.biostar_url+"/p/new/post/")}});r.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(w.biostar_url+"/t/"+w.id+"/")}})}r.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="+w.id)}});if(this.is_admin){r.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+w.id+"/download"}})}this.section=new l.View(v,{inputs:w.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>"+w.name+"</b> "+w.description+" (Galaxy Tool Version "+w.version+")",cls:"ui-portlet-slim",operations:{requirements:s,menu:r,versions:o},buttons:{execute:new m.Button({icon:"fa-check",tooltip:"Execute: "+w.name,title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){v.job_handler.submit()}})}});this.portlet.append(this.message.$el,true);this.portlet.append(this.section.$el);this.$el.empty();this.$el.append(this.portlet.$el);if(w.help!=""){this.$el.append(d.help(w.help))}if(w.citations){var u=$("<div/>");var n=new k.ToolCitationCollection();n.tool_id=w.id;var p=new a.CitationListView({el:u,collection:n});p.render();n.fetch();this.$el.append(u)}if(w.message){this.message.update({persistent:true,status:"warning",message:w.message})}}});return{View:b}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-misc","mvc/tools/tools-form-base","mvc/tools/tools-jobs"],function(c,e,b,a){var d=b.extend({initialize:function(g){var f=this;this.job_handler=new a(this);this.buttons={execute:new e.Button({icon:"fa-check",tooltip:"Execute: "+g.name,title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){f.job_handler.submit()}})};b.prototype.initialize.call(this,g)},_buildModel:function(){var f=this;var g=galaxy_config.root+"api/tools/"+this.options.id+"/build?";if(this.options.job_id){g+="job_id="+this.options.job_id}else{if(this.options.dataset_id){g+="dataset_id="+this.options.dataset_id}else{g+="tool_version="+this.options.version+"&";var i=top.location.href;var j=i.indexOf("?");if(i.indexOf("tool_id=")!=-1&&j!==-1){g+=i.slice(j+1)}}}var h=this.deferred.register();c.request({type:"GET",url:g,success:function(k){f.options=k;f._buildForm();f.message.update({status:"success",message:"Now you are using '"+f.options.name+"' version "+f.options.version+".",persistent:false});f.deferred.done(h);console.debug("tools-form::initialize() - Initial tool model ready.");console.debug(k)},error:function(k){f.deferred.done(h);console.debug("tools-form::initialize() - Initial tool model request failed.");console.debug(k);var l=k.error||"Uncaught error.";f.modal.show({title:"Tool cannot be executed",body:l,buttons:{Close:function(){f.modal.hide()}}})}})},_updateModel:function(){var f=this;var g=this.tree.finalize({data:function(k){if(k.values.length>0&&k.values[0]&&k.values[0].src==="hda"){return f.content.get({id:k.values[0].id,src:"hda"}).id_uncoded}return null}});console.debug("tools-form::_refreshForm() - Refreshing states.");console.debug(g);function j(n){for(var l in f.input_list){var m=f.field_list[l];var k=f.input_list[l];if(k.is_dynamic&&m.wait&&m.unwait){if(n){m.wait()}else{m.unwait()}}}}j(true);var i=this.deferred.register();var h=galaxy_config.root+"api/tools/"+this.options.id+"/build?tool_version="+this.options.version;c.request({type:"GET",url:h,data:g,success:function(k){f.tree.matchModel(k,function(m,q){var l=f.input_list[m];if(l&&l.options){if(!_.isEqual(l.options,q.options)){l.options=q.options;var r=f.field_list[m];if(r.update){var p=[];if((["data","data_collection","drill_down"]).indexOf(l.type)!=-1){p=l.options}else{for(var o in q.options){var n=q.options[o];if(n.length>2){p.push({label:n[0],value:n[1]})}}}r.update(p);r.trigger("change");console.debug("Updating options for "+m)}}}});j(false);f.deferred.done(i);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(k)},error:function(k){f.deferred.done(i);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(k)}})}});return{View:d}});
\ No newline at end of file
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/packed/mvc/tools/tools-jobs.js
--- a/static/scripts/packed/mvc/tools/tools-jobs.js
+++ b/static/scripts/packed/mvc/tools/tools-jobs.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var d={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(d)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(d);this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide()}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:d,success:function(e){c.app.modal.hide();c.app.reciept(a.success(e));c._refreshHdas()},error:function(e,g){c.app.modal.hide();if(e&&e.message&&e.message.data){var h=c.app.tree.matchResponse(e.message.data);for(var f in h){c.app.highlight(f,h[f]);break}}else{console.debug(e);c.app.modal.show({title:"Job submission failed",body:a.error(d),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&e.validate&&!e.validate()){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})});
\ No newline at end of file
+define(["utils/utils","mvc/tools/tools-template"],function(b,a){return Backbone.Model.extend({initialize:function(c){this.app=c},submit:function(){var c=this;var d={tool_id:this.app.options.id,tool_version:this.app.options.version,inputs:this.app.tree.finalize()};this.app.trigger("reset");if(!this._validation(d)){console.debug("tools-jobs::submit - Submission canceled. Validation failed.");return}console.debug(d);this.app.modal.show({title:"Please wait...",body:"progress",closing_events:true,buttons:{Close:function(){c.app.modal.hide()}}});b.request({type:"POST",url:galaxy_config.root+"api/tools",data:d,success:function(e){c.app.modal.hide();c.app.reciept(a.success(e));c._refreshHdas()},error:function(e,g){c.app.modal.hide();if(e&&e.message&&e.message.data){var h=c.app.tree.matchResponse(e.message.data);for(var f in h){c.app.highlight(f,h[f]);break}}else{console.debug(e);c.app.modal.show({title:"Job submission failed",body:a.error(d),buttons:{Close:function(){c.app.modal.hide()}}})}}})},_validation:function(h){var d=h.inputs;var m=-1;var i=null;for(var k in d){var f=d[k];var l=this.app.tree.match(k);var e=this.app.field_list[l];var j=this.app.input_list[l];if(!l||!j||!e){console.debug("tools-jobs::_validation - Retrieving input objects failed.");continue}if(!j.optional&&f==null){this.app.highlight(l);return false}if(f&&f.batch){var g=f.values.length;var c=null;if(g>0){c=f.values[0]&&f.values[0].src}if(c){if(i===null){i=c}else{if(i!==c){this.app.highlight(l,"Please select either dataset or dataset list fields for all batch mode fields.");return false}}}if(m===-1){m=g}else{if(m!==g){this.app.highlight(l,"Please make sure that you select the same number of inputs for all batch mode fields. This field contains <b>"+g+"</b> selection(s) while a previous field contains <b>"+m+"</b>.");return false}}}}return true},_refreshHdas:function(){if(parent.Galaxy&&parent.Galaxy.currHistoryPanel){parent.Galaxy.currHistoryPanel.refreshContents()}}})});
\ No newline at end of file
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/packed/mvc/tools/tools-section.js
--- a/static/scripts/packed/mvc/tools/tools-section.js
+++ b/static/scripts/packed/mvc/tools/tools-section.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(d,b,g,c,a,e){var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new b.View(h);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var h in this.inputs){this._add(this.inputs[h])}},_add:function(j){var i=this;var h=jQuery.extend(true,{},j);h.id=j.id=d.uuid();this.app.input_list[h.id]=h;var k=h.type;switch(k){case"conditional":this._addConditional(h);break;case"repeat":this._addRepeat(h);break;default:this._addRow(h)}},_addConditional:function(h){var j=this;h.test_param.id=h.id;var m=this._addRow(h.test_param);m.options.onchange=function(t){var p=j.app.tree.matchCase(h,t);for(var r in h.cases){var w=h.cases[r];var u=h.id+"-section-"+r;var o=j.table.get(u);var v=false;for(var q in w.inputs){var s=w.inputs[q].type;if(s&&s!=="hidden"){v=true;break}}if(r==p&&v){o.fadeIn("fast")}else{o.hide()}}j.app.trigger("refresh")};for(var l in h.cases){var k=h.id+"-section-"+l;var n=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});n.$el.addClass("ui-table-form-section");this.table.add(n.$el);this.table.append(k)}m.trigger("change")},_addRepeat:function(o){var r=this;var p=0;function m(i,t){var s=o.id+"-section-"+(p++);var u=null;if(t){u=function(){k.del(s);k.retitle(o.title);r.app.trigger("refresh")}}var v=new f(r.app,{inputs:i,cls:"ui-table-plain"});k.add({id:s,title:o.title,$el:v.$el,ondel:u});k.retitle(o.title)}var k=new c.View({title_new:o.title,max:o.max,onnew:function(){m(o.inputs,true);r.app.trigger("refresh")}});var h=o.min;var q=_.size(o.cache);for(var l=0;l<Math.max(q,h);l++){var n=null;if(l<q){n=o.cache[l]}else{n=o.inputs}m(n,l>=h)}var j=new e(this.app,{label:o.title,help:o.help,field:k});j.$el.addClass("ui-table-form-section");this.table.add(j.$el);this.table.append(o.id)},_addRow:function(h){var k=h.id;var i=this._createField(h);this.app.field_list[k]=i;var j=new e(this.app,{label:h.label,optional:h.optional,help:h.help,field:i});this.app.element_list[k]=j;this.table.add(j.$el);this.table.append(k);return i},_createField:function(h){var i=null;switch(h.type){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_collection":i=this._fieldData(h);break;case"data_column":h.error_text="Missing columns in referenced dataset.";i=this._fieldSelect(h);break;case"hidden":i=this._fieldHidden(h);break;case"hidden_data":i=this._fieldHidden(h);break;case"integer":i=this._fieldSlider(h);break;case"float":i=this._fieldSlider(h);break;case"boolean":i=this._fieldBoolean(h);break;case"genomebuild":h.searchable=true;i=this._fieldSelect(h);break;case"drill_down":i=this._fieldDrilldown(h);break;case"baseurl":i=this._fieldHidden(h);break;default:this.app.incompatible=true;if(h.options){i=this._fieldSelect(h)}else{i=this._fieldText(h)}console.debug("tools-form::_addRow() : Auto matched field type ("+h.type+").")}if(h.value!==undefined){i.value(h.value)}return i},_fieldData:function(h){var i=this;return new a.View(this.app,{id:"field-"+h.id,extensions:h.extensions,multiple:h.multiple,type:h.type,data:h.options,onchange:function(){i.app.trigger("refresh")}})},_fieldSelect:function(h){var k=[];for(var l in h.options){var m=h.options[l];k.push({label:m[0],value:m[1]})}var n=g.Select;switch(h.display){case"checkboxes":n=g.Checkbox;break;case"radio":n=g.Radio;break}var j=this;return new n.View({id:"field-"+h.id,data:k,error_text:h.error_text||"No options available",multiple:h.multiple,searchable:h.searchable,onchange:function(){j.app.trigger("refresh")}})},_fieldDrilldown:function(h){var i=this;return new g.Drilldown.View({id:"field-"+h.id,data:h.options,display:h.display,onchange:function(){i.app.trigger("refresh")}})},_fieldText:function(h){var i=this;return new g.Input({id:"field-"+h.id,area:h.area,onchange:function(){i.app.trigger("refresh")}})},_fieldSlider:function(h){return new g.Slider.View({id:"field-"+h.id,precise:h.type=="float",min:h.min,max:h.max})},_fieldHidden:function(h){return new g.Hidden({id:"field-"+h.id})},_fieldBoolean:function(h){return new g.RadioButton.View({id:"field-"+h.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]})}});return{View:f}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-table","mvc/ui/ui-misc","mvc/tools/tools-repeat","mvc/tools/tools-select-content","mvc/tools/tools-input"],function(d,b,g,c,a,e){var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new b.View(h);this.setElement(this.table.$el);this.render()},render:function(){this.table.delAll();for(var h in this.inputs){this._add(this.inputs[h])}},_add:function(j){var i=this;var h=jQuery.extend(true,{},j);h.id=j.id=d.uuid();this.app.input_list[h.id]=h;var k=h.type;switch(k){case"conditional":this._addConditional(h);break;case"repeat":this._addRepeat(h);break;default:this._addRow(h)}},_addConditional:function(h){var j=this;h.test_param.id=h.id;var m=this._addRow(h.test_param);m.options.onchange=function(t){var p=j.app.tree.matchCase(h,t);for(var r in h.cases){var w=h.cases[r];var u=h.id+"-section-"+r;var o=j.table.get(u);var v=false;for(var q in w.inputs){var s=w.inputs[q].type;if(s&&s!=="hidden"){v=true;break}}if(r==p&&v){o.fadeIn("fast")}else{o.hide()}}j.app.trigger("refresh")};for(var l in h.cases){var k=h.id+"-section-"+l;var n=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});n.$el.addClass("ui-table-form-section");this.table.add(n.$el);this.table.append(k)}m.trigger("change")},_addRepeat:function(o){var r=this;var p=0;function m(i,t){var s=o.id+"-section-"+(p++);var u=null;if(t){u=function(){k.del(s);k.retitle(o.title);r.app.trigger("refresh")}}var v=new f(r.app,{inputs:i,cls:"ui-table-plain"});k.add({id:s,title:o.title,$el:v.$el,ondel:u});k.retitle(o.title)}var k=new c.View({title_new:o.title,max:o.max,onnew:function(){m(o.inputs,true);r.app.trigger("refresh")}});var h=o.min;var q=_.size(o.cache);for(var l=0;l<Math.max(q,h);l++){var n=null;if(l<q){n=o.cache[l]}else{n=o.inputs}m(n,l>=h)}var j=new e(this.app,{label:o.title,help:o.help,field:k});j.$el.addClass("ui-table-form-section");this.table.add(j.$el);this.table.append(o.id)},_addRow:function(h){var k=h.id;var i=this._createField(h);this.app.field_list[k]=i;var j=new e(this.app,{label:h.label,optional:h.optional,help:h.help,field:i});this.app.element_list[k]=j;this.table.add(j.$el);this.table.append(k);return i},_createField:function(h){var i=null;switch(h.type){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_collection":i=this._fieldData(h);break;case"data_column":h.error_text="Missing columns in referenced dataset.";i=this._fieldSelect(h);break;case"hidden":i=this._fieldHidden(h);break;case"hidden_data":i=this._fieldHidden(h);break;case"integer":i=this._fieldSlider(h);break;case"float":i=this._fieldSlider(h);break;case"boolean":i=this._fieldBoolean(h);break;case"genomebuild":h.searchable=true;i=this._fieldSelect(h);break;case"drill_down":i=this._fieldDrilldown(h);break;case"baseurl":i=this._fieldHidden(h);break;default:this.app.incompatible=true;if(h.options){i=this._fieldSelect(h)}else{i=this._fieldText(h)}console.debug("tools-form::_addRow() : Auto matched field type ("+h.type+").")}if(h.value!==undefined){i.value(h.value)}return i},_fieldData:function(h){if(this.app.workflow){var j=d.textify(h.extensions.toString());h.info="Data input '"+h.name+"' ("+j+")";return this._fieldHidden(h)}var i=this;return new a.View(this.app,{id:"field-"+h.id,extensions:h.extensions,multiple:h.multiple,type:h.type,data:h.options,onchange:function(){i.app.trigger("refresh")}})},_fieldSelect:function(h){if(this.app.workflow&&h.is_dynamic){if(!d.validate(h.value)){h.value=""}return this._fieldText(h)}var k=[];for(var l in h.options){var m=h.options[l];k.push({label:m[0],value:m[1]})}var n=g.Select;switch(h.display){case"checkboxes":n=g.Checkbox;break;case"radio":n=g.Radio;break}var j=this;return new n.View({id:"field-"+h.id,data:k,error_text:h.error_text||"No options available",multiple:h.multiple,searchable:h.searchable,onchange:function(){j.app.trigger("refresh")}})},_fieldDrilldown:function(h){var i=this;return new g.Drilldown.View({id:"field-"+h.id,data:h.options,display:h.display,onchange:function(){i.app.trigger("refresh")}})},_fieldText:function(h){var i=this;return new g.Input({id:"field-"+h.id,area:h.area,onchange:function(){i.app.trigger("refresh")}})},_fieldSlider:function(h){return new g.Slider.View({id:"field-"+h.id,precise:h.type=="float",min:h.min,max:h.max})},_fieldHidden:function(h){return new g.Hidden({id:"field-"+h.id,info:h.info})},_fieldBoolean:function(h){return new g.RadioButton.View({id:"field-"+h.id,data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]})}});return{View:f}});
\ No newline at end of file
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 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(f,o){this.app=f;this.options=o;var n=this;this.setElement("<div/>");this.list={};var m=[];if(o.type=="data_collection"){this.mode="collection"}else{if(o.multiple){this.mode="multiple"}else{this.mode="single"}}this.current=this.mode;this.list={};var j=o.extensions.toString();if(j){j=j.replace(/,/g,", ");var k=j.lastIndexOf(", ");if(k!=-1){j=j.substr(0,k)+" or "+j.substr(k+1)}}var h="No dataset available.";if(j){h="No "+j+" dataset available."}var l="No dataset list available.";if(j){l="No "+j+" dataset collection available."}if(this.mode=="single"){m.push({icon:"fa-file-o",label:"Single dataset",value:"single"});this.select_single=new e.Select.View({error_text:h,onchange:function(){n.trigger("change")}});this.list.single={field:this.select_single,type:"hda"}}if(this.mode=="single"||this.mode=="multiple"){m.push({icon:"fa-files-o",label:"Multiple datasets",value:"multiple"});this.select_multiple=new e.Select.View({multiple:true,error_text:h,onchange:function(){n.trigger("change")}});this.list.multiple={field:this.select_multiple,type:"hda"}}if(this.mode=="single"||this.mode=="collection"){m.push({icon:"fa-folder-o",label:"Dataset collection",value:"collection"});this.select_collection=new e.Select.View({error_text:l,onchange:function(){n.trigger("change")}});this.list.collection={field:this.select_collection,type:"hdca"}}this.button_type=new e.RadioButton.View({value:this.current,data:m,onchange:function(i){n.current=i;n.refresh();n.trigger("change")}});this.$batch=$(a.batchMode());if(_.size(this.list)>1){this.$el.append(c.wrap(this.button_type.$el))}for(var g in this.list){this.$el.append(this.list[g].field.$el)}this.$el.append(this.$batch);this.update(o.data);if(this.options.value!==undefined){this.value(this.options.value)}this.refresh();this.on("change",function(){if(o.onchange){o.onchange(n.value())}})},wait:function(){for(var f in this.list){this.list[f].field.wait()}},unwait:function(){for(var f in this.list){this.list[f].field.unwait()}},update:function(g){var l=[];for(var j in g.hda){var k=g.hda[j];l.push({label:k.hid+": "+k.name,value:k.id})}var f=[];for(var j in g.hdca){var h=g.hdca[j];f.push({label:h.hid+": "+h.name,value:h.id})}this.select_single&&this.select_single.update(l);this.select_multiple&&this.select_multiple.update(l);this.select_collection&&this.select_collection.update(f);this.app.content.add(g)},value:function(m){if(m&&m.values){try{var l=[];for(var h in m.values){l.push(m.values[h].id)}if(m&&m.values.length>0&&m.values[0].src=="hcda"){this.current="collection";this.select_collection.value(l[0])}else{if(this.mode=="multiple"){this.current="multiple";this.select_multiple.value(l)}else{this.current="single";this.select_single.value(l[0])}}this.refresh();var g=this._select();if(!g.validate()){g.value(g.first())}}catch(k){console.debug("tools-select-content::value() - Skipped.")}}var j=this._select().value();if(!(j instanceof Array)){j=[j]}var f={batch:this.mode=="single"&&this.current!="single",values:[]};for(var h in j){f.values.push({id:j[h],src:this.list[this.current].type})}return f},validate:function(){return this._select().validate()},refresh:function(){for(var g in this.list){var f=this.list[g].field.$el;if(this.current==g){f.show()}else{f.hide()}}if(this.mode=="single"&&this.current!="single"){this.$batch.show()}else{this.$batch.hide()}},_select:function(){return this.list[this.current].field}});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(l,g){this.app=l;this.options=g;var f=this;this.setElement("<div/>");this.list={};var j=[];if(g.type=="data_collection"){this.mode="collection"}else{if(g.multiple){this.mode="multiple"}else{this.mode="single"}}this.current=this.mode;this.list={};var k=c.textify(g.extensions);var n="No dataset available.";if(k){n="No "+k+" dataset available."}var m="No dataset list available.";if(k){m="No "+k+" dataset collection available."}if(this.mode=="single"){j.push({icon:"fa-file-o",label:"Single dataset",value:"single"});this.select_single=new e.Select.View({error_text:n,onchange:function(){f.trigger("change")}});this.list.single={field:this.select_single,type:"hda"}}if(this.mode=="single"||this.mode=="multiple"){j.push({icon:"fa-files-o",label:"Multiple datasets",value:"multiple"});this.select_multiple=new e.Select.View({multiple:true,error_text:n,onchange:function(){f.trigger("change")}});this.list.multiple={field:this.select_multiple,type:"hda"}}if(this.mode=="single"||this.mode=="collection"){j.push({icon:"fa-folder-o",label:"Dataset collection",value:"collection"});this.select_collection=new e.Select.View({error_text:m,onchange:function(){f.trigger("change")}});this.list.collection={field:this.select_collection,type:"hdca"}}this.button_type=new e.RadioButton.View({value:this.current,data:j,onchange:function(i){f.current=i;f.refresh();f.trigger("change")}});this.$batch=$(a.batchMode());if(_.size(this.list)>1){this.$el.append(c.wrap(this.button_type.$el))}for(var h in this.list){this.$el.append(this.list[h].field.$el)}this.$el.append(this.$batch);this.update(g.data);if(this.options.value!==undefined){this.value(this.options.value)}this.refresh();this.on("change",function(){if(g.onchange){g.onchange(f.value())}})},wait:function(){for(var f in this.list){this.list[f].field.wait()}},unwait:function(){for(var f in this.list){this.list[f].field.unwait()}},update:function(g){var l=[];for(var j in g.hda){var k=g.hda[j];l.push({label:k.hid+": "+k.name,value:k.id})}var f=[];for(var j in g.hdca){var h=g.hdca[j];f.push({label:h.hid+": "+h.name,value:h.id})}this.select_single&&this.select_single.update(l);this.select_multiple&&this.select_multiple.update(l);this.select_collection&&this.select_collection.update(f);this.app.content.add(g)},value:function(m){if(m&&m.values){try{var l=[];for(var h in m.values){l.push(m.values[h].id)}if(m&&m.values.length>0&&m.values[0].src=="hcda"){this.current="collection";this.select_collection.value(l[0])}else{if(this.mode=="multiple"){this.current="multiple";this.select_multiple.value(l)}else{this.current="single";this.select_single.value(l[0])}}this.refresh();var g=this._select();if(!g.validate()){g.value(g.first())}}catch(k){console.debug("tools-select-content::value() - Skipped.")}}var j=this._select().value();if(!(j instanceof Array)){j=[j]}var f={batch:this.mode=="single"&&this.current!="single",values:[]};for(var h in j){f.values.push({id:j[h],src:this.list[this.current].type})}return f},validate:function(){return this._select().validate()},refresh:function(){for(var g in this.list){var f=this.list[g].field.$el;if(this.current==g){f.show()}else{f.hide()}}if(this.mode=="single"&&this.current!="single"){this.$batch.show()}else{this.$batch.hide()}},_select:function(){return this.list[this.current].field}});return{View:d}});
\ No newline at end of file
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/packed/mvc/tools/tools-tree.js
--- a/static/scripts/packed/mvc/tools/tools-tree.js
+++ b/static/scripts/packed/mvc/tools/tools-tree.js
@@ -1,1 +1,1 @@
-define([],function(){return Backbone.Model.extend({initialize:function(a){this.app=a},finalize:function(f){var a=this;this.map_dict={};if(!this.app.section){return{}}f=f||{};var e={};var d={};this._iterate(this.app.section.$el,d);function c(i,h,g){e[i]=g;a.map_dict[i]=h}function b(n,q){for(var l in q){var j=q[l];if(j.input){var s=j.input;var m=n;if(n!=""){m+="|"}m+=s.name;switch(s.type){case"repeat":var h="section-";var v=[];var p=null;for(var u in j){var o=u.indexOf(h);if(o!=-1){o+=h.length;v.push(parseInt(u.substr(o)));if(!p){p=u.substr(0,o)}}}v.sort(function(w,i){return w-i});var l=0;for(var k in v){b(m+"_"+l++,j[p+v[k]])}break;case"conditional":var t=a.app.field_list[s.id].value();if(f[s.test_param.type]){t=f[s.test_param.type](t)}c(m+"|"+s.test_param.name,s.id,t);var g=a.matchCase(s,t);if(g!=-1){b(m,q[s.id+"-section-"+g])}break;default:var r=a.app.field_list[s.id];var t=r.value();if(f[s.type]){t=f[s.type](t)}if(!r.skip){if(s.optional&&r.validate&&!r.validate()){t=null}c(m,s.id,t)}}}}}b("",d);return e},match:function(a){return this.map_dict&&this.map_dict[a]},matchCase:function(a,c){if(a.test_param.type=="boolean"){if(c=="true"){c=a.test_param.truevalue||"true"}else{c=a.test_param.falsevalue||"false"}}for(var b in a.cases){if(a.cases[b].value==c){return b}}return -1},matchModel:function(c,e){var a={};var b=this;function d(f,o){for(var l in o){var h=o[l];var m=h.name;if(f!=""){m=f+"|"+m}switch(h.type){case"repeat":for(var k in h.cache){d(m+"_"+k,h.cache[k])}break;case"conditional":var p=h.test_param&&h.test_param.value;var g=b.matchCase(h,p);if(g!=-1){d(m,h.cases[g].inputs)}break;default:var n=b.map_dict[m];if(n){e(n,h)}}}}d("",c.inputs);return a},matchResponse:function(c){var a={};var b=this;function d(k,h){if(typeof h==="string"){var f=b.map_dict[k];if(f){a[f]=h}}else{for(var g in h){var e=g;if(k!==""){var j="|";if(h instanceof Array){j="_"}e=k+j+e}d(e,h[g])}}}d("",c);return a},_iterate:function(c,d){var a=this;var b=$(c).children();b.each(function(){var g=this;var f=$(g).attr("id");if($(g).hasClass("section-row")){d[f]={};var e=a.app.input_list[f];if(e){d[f]={input:e}}a._iterate(g,d[f])}else{a._iterate(g,d)}})}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(b){this.app=b},finalize:function(g){var b=this;this.map_dict={};if(!this.app.section){return{}}g=g||{};var f={};var e={};this._iterate(this.app.section.$el,e);function d(j,i,h){f[j]=h;b.map_dict[j]=i}function c(o,r){for(var m in r){var k=r[m];if(k.input){var t=k.input;var n=o;if(o!=""){n+="|"}n+=t.name;switch(t.type){case"repeat":var j="section-";var w=[];var q=null;for(var v in k){var p=v.indexOf(j);if(p!=-1){p+=j.length;w.push(parseInt(v.substr(p)));if(!q){q=v.substr(0,p)}}}w.sort(function(x,i){return x-i});var m=0;for(var l in w){c(n+"_"+m++,k[q+w[l]])}break;case"conditional":var u=b.app.field_list[t.id].value();if(g[t.test_param.type]){u=g[t.test_param.type](u)}d(n+"|"+t.test_param.name,t.id,u);var h=b.matchCase(t,u);if(h!=-1){c(n,r[t.id+"-section-"+h])}break;default:var s=b.app.field_list[t.id];var u=s.value();if(g[t.type]){u=g[t.type](u)}if(!s.skip){if(s.validate&&!s.validate(u)){u=null}d(n,t.id,u)}}}}}c("",e);return f},match:function(b){return this.map_dict&&this.map_dict[b]},matchCase:function(b,d){if(b.test_param.type=="boolean"){if(d=="true"){d=b.test_param.truevalue||"true"}else{d=b.test_param.falsevalue||"false"}}for(var c in b.cases){if(b.cases[c].value==d){return c}}return -1},matchModel:function(d,f){var b={};var c=this;function e(g,p){for(var m in p){var k=p[m];var n=k.name;if(g!=""){n=g+"|"+n}switch(k.type){case"repeat":for(var l in k.cache){e(n+"_"+l,k.cache[l])}break;case"conditional":var q=k.test_param&&k.test_param.value;var h=c.matchCase(k,q);if(h!=-1){e(n,k.cases[h].inputs)}break;default:var o=c.map_dict[n];if(o){f(o,k)}}}}e("",d.inputs);return b},matchResponse:function(d){var b={};var c=this;function e(l,j){if(typeof j==="string"){var g=c.map_dict[l];if(g){b[g]=j}}else{for(var h in j){var f=h;if(l!==""){var k="|";if(j instanceof Array){k="_"}f=l+k+f}e(f,j[h])}}}e("",d);return b},_iterate:function(d,e){var b=this;var c=$(d).children();c.each(function(){var h=this;var g=$(h).attr("id");if($(h).hasClass("section-row")){e[g]={};var f=b.app.input_list[g];if(f){e[g]={input:f}}b._iterate(h,e[g])}else{b._iterate(h,e)}})}})});
\ No newline at end of file
diff -r 5c33270710123171734e5c822dfbb430a4234e37 -r d9b038019163bc378b72b675ddb4e1e902384b12 static/scripts/packed/mvc/ui/ui-misc.js
--- a/static/scripts/packed/mvc/ui/ui-misc.js
+++ b/static/scripts/packed/mvc/ui/ui-misc.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(k,b,e,o,l,q,m){var d=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},_template:function(r){return'<img class="ui-image '+r.cls+'" src="'+r.url+'"/>'}});var j=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},title:function(r){this.$el.html(r)},_template:function(r){return'<label class="ui-label '+r.cls+'">'+r.title+"</label>"},value:function(){return options.title}});var c=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){return'<div><span class="fa '+r.icon+'" class="ui-icon"/> '+r.title+"</div>"}});var g=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",function(){$(".tooltip").hide();if(r.onclick){r.onclick()}});$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){var s='<button id="'+r.id+'" type="submit" style="float: '+r.floating+';" type="button" class="'+r.cls+'">';if(r.icon){s+='<i class="icon fa '+r.icon+'"></i> '}s+=r.title+"</button>";return s}});var h=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));this.$button=this.$el.find(".button");var r=this;$(this.el).on("click",function(){$(".tooltip").hide();if(s.onclick&&!r.disabled){s.onclick()}});$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled");this.disabled=true},enable:function(){this.$button.removeClass("disabled");this.disabled=false},_template:function(r){var s="";if(r.title){s="width: auto;"}var t='<div id="'+r.id+'" style="float: '+r.floating+"; "+s+'" class="'+r.cls+'">';if(r.title){t+='<div class="button"><i class="icon fa '+r.icon+'"/> <span class="title">'+r.title+"</span></div>"}else{t+='<i class="icon fa '+r.icon+'"/>'}t+="</div>";return t}});var f=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",r.onclick)},_template:function(r){return'<div><a href="javascript:void(0)" class="ui-anchor '+r.cls+'">'+r.title+"</a></div>"}});var n=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:false},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement("<div></div>");if(this.options.message){this.update(this.options)}},update:function(s){this.options=k.merge(s,this.optionsDefault);if(s.message!=""){this.$el.html(this._template(this.options));this.$el.find(".alert").append(s.message);this.$el.fadeIn();if(this.timeout){window.clearTimeout(this.timeout)}if(!s.persistent){var r=this;this.timeout=window.setTimeout(function(){if(r.$el.is(":visible")){r.$el.fadeOut()}else{r.$el.hide()}},3000)}}else{this.$el.fadeOut()}},_template:function(r){return'<div class="ui-message alert alert-'+r.status+'"/>'}});var a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));var r=this;if(this.options.onclick){this.$el.on("submit",function(u){var t=r.$el.find("#search");r.options.onclick(t.val())})}},_template:function(r){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+r.searchword+'"><button type="submit" class="btn search-btn"><i class="fa fa-search"></i></button></form></div>'}});var i=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:false,visible:true,cls:"",area:false},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}if(this.options.disabled){this.$el.prop("disabled",true)}if(!this.options.visible){this.$el.hide()}var r=this;this.$el.on("input",function(){if(r.options.onchange){r.options.onchange(r.$el.val())}})},value:function(r){if(r!==undefined){this.$el.val(r)}return this.$el.val()},_template:function(r){if(r.area){return'<textarea id="'+r.id+'" class="ui-textarea '+r.cls+'"></textarea>'}else{return'<input id="'+r.id+'" type="'+r.type+'" value="'+r.value+'" placeholder="'+r.placeholder+'" class="ui-input '+r.cls+'">'}}});var p=Backbone.View.extend({initialize:function(r){this.options=r;this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}},value:function(r){if(r!==undefined){this.$el.val(r)}return this.$el.val()},_template:function(r){return'<hidden id="'+r.id+'" value="'+r.value+'"/>'}});return{Anchor:f,Button:g,ButtonIcon:h,ButtonMenu:q,Icon:c,Image:d,Input:i,Label:j,Message:n,Modal:m,RadioButton:o.RadioButton,Checkbox:o.Checkbox,Radio:o.Radio,Searchbox:a,Select:b,Hidden:p,Slider:e,Drilldown:l}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-modal"],function(k,b,e,o,l,q,m){var d=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},_template:function(r){return'<img class="ui-image '+r.cls+'" src="'+r.url+'"/>'}});var j=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options))},title:function(r){this.$el.html(r)},_template:function(r){return'<label class="ui-label '+r.cls+'">'+r.title+"</label>"},value:function(){return options.title}});var c=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){return'<div><span class="fa '+r.icon+'" class="ui-icon"/> '+r.title+"</div>"}});var g=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",function(){$(".tooltip").hide();if(r.onclick){r.onclick()}});$(this.el).tooltip({title:r.tooltip,placement:"bottom"})},_template:function(r){var s='<button id="'+r.id+'" type="submit" style="float: '+r.floating+';" type="button" class="'+r.cls+'">';if(r.icon){s+='<i class="icon fa '+r.icon+'"></i> '}s+=r.title+"</button>";return s}});var h=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));this.$button=this.$el.find(".button");var r=this;$(this.el).on("click",function(){$(".tooltip").hide();if(s.onclick&&!r.disabled){s.onclick()}});$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled");this.disabled=true},enable:function(){this.$button.removeClass("disabled");this.disabled=false},_template:function(r){var s="";if(r.title){s="width: auto;"}var t='<div id="'+r.id+'" style="float: '+r.floating+"; "+s+'" class="'+r.cls+'">';if(r.title){t+='<div class="button"><i class="icon fa '+r.icon+'"/> <span class="title">'+r.title+"</span></div>"}else{t+='<i class="icon fa '+r.icon+'"/>'}t+="</div>";return t}});var f=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",r.onclick)},_template:function(r){return'<div><a href="javascript:void(0)" class="ui-anchor '+r.cls+'">'+r.title+"</a></div>"}});var n=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:false},initialize:function(r){this.options=k.merge(r,this.optionsDefault);this.setElement("<div></div>");if(this.options.message){this.update(this.options)}},update:function(s){this.options=k.merge(s,this.optionsDefault);if(s.message!=""){this.$el.html(this._template(this.options));this.$el.find(".alert").append(s.message);this.$el.fadeIn();if(this.timeout){window.clearTimeout(this.timeout)}if(!s.persistent){var r=this;this.timeout=window.setTimeout(function(){if(r.$el.is(":visible")){r.$el.fadeOut()}else{r.$el.hide()}},3000)}}else{this.$el.fadeOut()}},_template:function(r){return'<div class="ui-message alert alert-'+r.status+'"/>'}});var a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));var r=this;if(this.options.onclick){this.$el.on("submit",function(u){var t=r.$el.find("#search");r.options.onclick(t.val())})}},_template:function(r){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+r.searchword+'"><button type="submit" class="btn search-btn"><i class="fa fa-search"></i></button></form></div>'}});var i=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:false,visible:true,cls:"",area:false},initialize:function(s){this.options=k.merge(s,this.optionsDefault);this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}if(this.options.disabled){this.$el.prop("disabled",true)}if(!this.options.visible){this.$el.hide()}var r=this;this.$el.on("input",function(){if(r.options.onchange){r.options.onchange(r.$el.val())}})},value:function(r){if(r!==undefined){this.$el.val(r)}return this.$el.val()},_template:function(r){if(r.area){return'<textarea id="'+r.id+'" class="ui-textarea '+r.cls+'"></textarea>'}else{return'<input id="'+r.id+'" type="'+r.type+'" value="'+r.value+'" placeholder="'+r.placeholder+'" class="ui-input '+r.cls+'">'}}});var p=Backbone.View.extend({initialize:function(r){this.options=r;this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}},value:function(r){if(r!==undefined){this.$("hidden").val(r)}return this.$("hidden").val()},_template:function(s){var r='<div id="'+s.id+'" >';if(s.info){r+="<label>"+s.info+"</label>"}r+='<hidden value="'+s.value+'"/></div>';return r}});return{Anchor:f,Button:g,ButtonIcon:h,ButtonMenu:q,Icon:c,Image:d,Input:i,Label:j,Message:n,Modal:m,RadioButton:o.RadioButton,Checkbox:o.Checkbox,Radio:o.Radio,Searchbox:a,Select:b,Hidden:p,Slider:e,Drilldown:l}});
\ No newline at end of file
This diff is so big that we needed to truncate the remainder.
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.
1
0

[galaxyproject/usegalaxy-playbook] 8e55f6: Swapped CoSSci out and PreSTIGE galaxy server in, ...
by GitHub 10 Jan '15
by GitHub 10 Jan '15
10 Jan '15
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 8e55f6015a13b536c9c1afe3e29114e01b5db1c9
https://github.com/galaxyproject/usegalaxy-playbook/commit/8e55f6015a13b536…
Author: Dave Clements <clements(a)Clements-Galaxy.local>
Date: 2015-01-10 (Sat, 10 Jan 2015)
Changed paths:
A files/galaxy/common/static/welcome_img/PreSTIGEGalaxy.png
M templates/galaxy/common/static/welcome.html.j2
Log Message:
-----------
Swapped CoSSci out and PreSTIGE galaxy server in, in landing page slide rotation.
Commit: 176e3a7ef6b5a89d28259879f931742e788b5419
https://github.com/galaxyproject/usegalaxy-playbook/commit/176e3a7ef6b5a89d…
Author: Dave Clements <clements(a)Clements-Galaxy.local>
Date: 2015-01-10 (Sat, 10 Jan 2015)
Changed paths:
M templates/galaxy/common/static/welcome.html.j2
Log Message:
-----------
Still struggling with Git add ... This change should have been in previous commit.
Compare: https://github.com/galaxyproject/usegalaxy-playbook/compare/2f879e75e725...…
1
0