galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- 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
- 15302 discussions
commit/galaxy-central: jmchilton: Merged in martenson/galaxy-stable-pr/stable (pull request #520)
by commits-noreply@bitbucket.org 08 Oct '14
by commits-noreply@bitbucket.org 08 Oct '14
08 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bde1c35ef8e5/
Changeset: bde1c35ef8e5
Branch: stable
User: jmchilton
Date: 2014-10-08 20:21:35+00:00
Summary: Merged in martenson/galaxy-stable-pr/stable (pull request #520)
[STABLE] missing import
Affected #: 1 file
diff -r e98b33105381ac94f590edee1859ab550d328833 -r bde1c35ef8e53d0436507c48ed9b08b1dc5b06a3 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -5,6 +5,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy.web.form_builder import SelectField
+from galaxy.model.orm import or_
from tool_shed.metadata import metadata_generator
from tool_shed.repository_types.metadata import TipOnly
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3a193ffba363/
Changeset: 3a193ffba363
Branch: stable
User: martenson
Date: 2014-10-08 18:27:41+00:00
Summary: missing import
Affected #: 1 file
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 3a193ffba363cf10224568986c2c1c192bc8bca1 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -5,6 +5,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy.web.form_builder import SelectField
+from galaxy.model.orm import or_
from tool_shed.metadata import metadata_generator
from tool_shed.repository_types.metadata import TipOnly
https://bitbucket.org/galaxy/galaxy-central/commits/bde1c35ef8e5/
Changeset: bde1c35ef8e5
Branch: stable
User: jmchilton
Date: 2014-10-08 20:21:35+00:00
Summary: Merged in martenson/galaxy-stable-pr/stable (pull request #520)
[STABLE] missing import
Affected #: 1 file
diff -r e98b33105381ac94f590edee1859ab550d328833 -r bde1c35ef8e53d0436507c48ed9b08b1dc5b06a3 lib/tool_shed/metadata/repository_metadata_manager.py
--- a/lib/tool_shed/metadata/repository_metadata_manager.py
+++ b/lib/tool_shed/metadata/repository_metadata_manager.py
@@ -5,6 +5,7 @@
from galaxy import util
from galaxy.util import inflector
from galaxy.web.form_builder import SelectField
+from galaxy.model.orm import or_
from tool_shed.metadata import metadata_generator
from tool_shed.repository_types.metadata import TipOnly
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: Temporary tool form activation.
by commits-noreply@bitbucket.org 08 Oct '14
by commits-noreply@bitbucket.org 08 Oct '14
08 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/05f112a611b6/
Changeset: 05f112a611b6
User: guerler
Date: 2014-10-08 19:50:57+00:00
Summary: ToolForm: Temporary tool form activation.
Affected #: 2 files
diff -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa -r 05f112a611b683c82acd6f5c4918cff299daf2c5 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -1235,7 +1235,7 @@
requires_setting_metadata = True
default_tool_action = DefaultToolAction
dict_collection_visible_keys = ( 'id', 'name', 'version', 'description' )
- default_template = 'tool_form.mako'
+ default_template = 'tool_form.api.mako'
def __init__( self, config_file, root, app, guid=None, repository_id=None ):
"""Load a tool from the config named by `config_file`"""
diff -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa -r 05f112a611b683c82acd6f5c4918cff299daf2c5 templates/webapps/galaxy/tool_form.mako
--- a/templates/webapps/galaxy/tool_form.mako
+++ b/templates/webapps/galaxy/tool_form.mako
@@ -1,4 +1,4 @@
-<%inherit file="/base.mako"/>
+##<%inherit file="/base.mako"/><%namespace file="/message.mako" import="render_msg" /><%namespace file="/base_panels.mako" import="overlay" />
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: Improve collection handling
by commits-noreply@bitbucket.org 08 Oct '14
by commits-noreply@bitbucket.org 08 Oct '14
08 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a979bd1bb194/
Changeset: a979bd1bb194
User: guerler
Date: 2014-10-08 18:32:48+00:00
Summary: ToolForm: Improve collection handling
Affected #: 18 files
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-content.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-content.js
@@ -0,0 +1,132 @@
+define(['utils/utils'], function(Utils){
+ return Backbone.Model.extend({
+ // initialize
+ initialize: function(options) {
+ // backup basic url
+ this.base_url = galaxy_config.root + 'api/histories/' + options.history_id + '/contents';
+
+ // prepare content obects
+ this.datatypes = {};
+ this.summary = {};
+
+ // link this
+ var self = this;
+
+ // request datatypes
+ Utils.get({
+ url : galaxy_config.root + 'api/datatypes/mapping',
+ cache : true,
+ success : function(response) {
+ // backup datatype dictionary
+ self.datatypes = response;
+
+ // get history summary
+ Utils.get({
+ url : self.base_url + '?deleted=false',
+ success : function(response) {
+ // backup summary
+ self.summary = response;
+
+ // log
+ console.debug('tools-content::initialize() - Completed.');
+
+ // callback
+ options.success && options.success();
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for summary failed.');
+ console.debug(response);
+ }
+ });
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for datatypes failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /**
+ * Filters contents by data type.
+ */
+ filterType: function(options) {
+ // initialize parameters
+ options = options || {};
+ var result = [];
+
+ // identify content type
+ var history_content_type = 'dataset';
+ if (options.src== 'hdca') {
+ history_content_type = 'dataset_collection';
+ }
+
+ // search in summary
+ for (var i in this.summary) {
+ var content = this.summary[i];
+
+ // match datatypes
+ var found = false;
+ for (var i in options.extensions) {
+ if (this._matchType(options.extensions[i], content.extension)) {
+ found = true;
+ break;
+ }
+ }
+
+ // final match result
+ if ((content.history_content_type === history_content_type) && (found || !options.extensions)) {
+ result.push(content);
+ }
+ }
+ return result;
+ },
+
+ /** Get details of a content by id.
+ */
+ getDetails: function(options) {
+ var api_url = this.base_url + '/datasets/' + options.id;
+ if (options.src == 'hdca') {
+ api_url = this.base_url + '/dataset_collections/' + options.id;
+ }
+ Utils.get({
+ url : api_url,
+ success : function(response) {
+ options.success && options.success(response);
+ },
+ error : function(response) {
+ console.debug('tools-content::getDetails() - Ajax request for content failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /** Check if datatypes match
+ */
+ _matchType: function(target, reference) {
+ // check if target class is available
+ var target_class = this.datatypes.ext_to_class_name[target];
+ if (!target_class) {
+ console.debug('tools-content::_matchType() - Specific target class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check if reference class is available
+ var reference_class = this.datatypes.ext_to_class_name[reference];
+ if (!reference_class) {
+ console.debug('tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check reference group
+ var reference_group = this.datatypes.class_to_classes[reference_class];
+ if (reference_group[target_class]) {
+ return true;
+ }
+
+ // classes do not match
+ return false;
+ }
+ });
+});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-datasets.js
--- a/client/galaxy/scripts/mvc/tools/tools-datasets.js
+++ /dev/null
@@ -1,117 +0,0 @@
-define(['utils/utils'], function(Utils){
- return Backbone.Model.extend({
- // initialize
- initialize: function(options) {
- // prepare datasets obects
- this.datatypes = {};
- this.summary = {};
-
- // link this
- var self = this;
-
- // request datatypes
- Utils.get({
- url : galaxy_config.root + 'api/datatypes/mapping',
- cache : true,
- success : function(response) {
- // backup datatype dictionary
- self.datatypes = response;
-
- // get history summary
- Utils.get({
- url : galaxy_config.root + 'api/histories/' + options.history_id + '/contents?deleted=false',
- success : function(response) {
- // backup summary
- self.summary = response;
-
- // log
- console.debug('tools-datasets::initialize() - Completed.');
-
- // callback
- options.success && options.success();
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for summary failed.');
- console.debug(response);
- }
- });
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for datatypes failed.');
- console.debug(response);
- }
- });
- },
-
- /**
- * Filters datasets by data type.
- */
- filterType: function(options) {
- options = options || {};
- var result = [];
- for (var i in this.summary) {
- var dataset = this.summary[i];
-
- // match datatypes
- var found = false;
- for (var i in options.data_types) {
- if (this._matchType(options.data_types[i], dataset.extension)) {
- found = true;
- break;
- }
- }
-
- // final match result
- if ((dataset.history_content_type === options.content_type || !options.content_type) && (found || !options.data_types)) {
- result.push(dataset);
- }
- }
- return result;
- },
-
- /** Get details of a dataset by id.
- * @param{String} Dataset id
- */
- getDetails: function(dataset_id, callback) {
- Utils.get({
- url : galaxy_config.root + 'api/datasets/' + dataset_id,
- success : function(response) {
- callback && callback(response);
- },
- error : function(response) {
- console.debug('tools-datasets::getDetails() - Ajax request for dataset failed.');
- console.debug(response);
- }
- });
- },
-
- /** Check if datatypes match
- */
- _matchType: function(target, reference) {
- // check if target class is available
- var target_class = this.datatypes.ext_to_class_name[target];
- if (!target_class) {
- console.debug('tools-datasets::_matchType() - Specific target class unavailable. Accepting all formats.');
- return true;
- }
-
- // check if reference class is available
- var reference_class = this.datatypes.ext_to_class_name[reference];
- if (!reference_class) {
- console.debug('tools-datasets::_matchType() - Specific reference class unavailable. Accepting all formats.');
- return true;
- }
-
- // check reference group
- var reference_group = this.datatypes.class_to_classes[reference_class];
- if (reference_group[target_class]) {
- return true;
- }
-
- // classes do not match
- return false;
- }
- });
-});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa 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
@@ -3,9 +3,9 @@
*/
define(['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-datasets', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
+ 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-content', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
function(Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolDatasets, ToolSection, ToolTree, ToolJobs) {
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
// create tool model
var Model = Backbone.Model.extend({
@@ -61,8 +61,8 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize datasets
- this.datasets = new ToolDatasets({
+ // initialize contents
+ this.content = new ToolContent({
history_id : this.options.history_id,
success : function() {
self._initializeToolForm();
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa 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
@@ -1,8 +1,8 @@
/**
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _addRow() function.
*/
-define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-dataset'],
- function(Utils, Table, Ui, Repeat, SelectDataset) {
+define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content'],
+ function(Utils, Table, Ui, Repeat, SelectContent) {
// input field element wrapper
var InputElement = Backbone.View.extend({
@@ -268,12 +268,12 @@
field = this._fieldSelect(input_def);
break;
- // dataset
+ // data selector
case 'data':
field = this._fieldData(input_def);
break;
- // dataset column
+ // data column
case 'data_column':
field = this._fieldSelect(input_def);
break;
@@ -417,13 +417,15 @@
var id = input_def.id;
// select field
- return new SelectDataset.View(this.app, {
+ return new SelectContent.View(this.app, {
id : 'field-' + id,
extensions : input_def.extensions,
multiple : input_def.multiple,
onchange : function(dict) {
- // pick the first dataset only (todo: maybe collect multiple meta information)
- var value = dict.values[0].id;
+ // pick the first content only (todo: maybe collect multiple meta information)
+ var content_def = dict.values[0];
+ var content_id = content_def.id;
+ var content_src = content_def.src;
// get referenced columns
var column_list = self.app.tree.references(id, 'data_column');
@@ -440,71 +442,80 @@
column_field.wait && column_field.wait();
}
- // find selected dataset
- self.app.datasets.getDetails(value, function(dataset) {
- // meta data
- var meta = null;
-
- // check dataset
- if (dataset) {
- // log selection
- console.debug('tool-form::field_data() - Selected dataset ' + value + '.');
-
- // get meta data
- meta = dataset.metadata_column_types;
-
- // check meta data
- if (!meta) {
- console.debug('tool-form::field_data() - FAILED: Could not find metadata for dataset ' + value + '.');
+ // find selected content
+ self.app.content.getDetails({
+ id : content_id,
+ src : content_src,
+ success : function(content) {
+ // select the first dataset to represent collections
+ if (content_src == 'hdca' && content.elements && content.elements.length > 0) {
+ content = content.elements[0].object;
}
- } else {
- console.debug('tool-form::field_data() - FAILED: Could not find dataset ' + value + '.');
- }
-
- // update referenced columns
- for (var i in column_list) {
- // get column input/field
- var column_input = self.app.input_list[column_list[i]];
- var column_field = self.app.field_list[column_list[i]];
- if (!column_input || !column_field) {
- console.debug('tool-form::field_data() - FAILED: Column not found.');
+
+ // meta data
+ var meta = null;
+
+ // check content
+ if (content) {
+ // log selection
+ console.debug('tool-form::field_data() - Selected content ' + content_id + '.');
+
+ // get meta data
+ meta = content.metadata_column_types;
+
+ // check meta data
+ if (!meta) {
+ console.debug('tool-form::field_data() - FAILED: Could not find metadata for content ' + content_id + '.');
+ }
+ } else {
+ console.debug('tool-form::field_data() - FAILED: Could not find content ' + content_id + '.');
}
-
- // is numerical?
- var numerical = column_input.numerical;
- // identify column options
- var columns = [];
- for (var key in meta) {
- // get column type
- var column_type = meta[key];
+ // update referenced columns
+ for (var i in column_list) {
+ // get column input/field
+ var column_input = self.app.input_list[column_list[i]];
+ var column_field = self.app.field_list[column_list[i]];
+ if (!column_input || !column_field) {
+ console.debug('tool-form::field_data() - FAILED: Column not found.');
+ }
+
+ // is numerical?
+ var numerical = column_input.numerical;
- // column index
- var column_index = (parseInt(key) + 1);
-
- // column type label
- var column_label = 'Text';
- if (column_type == 'int' || column_type == 'float') {
- column_label = 'Number';
+ // identify column options
+ var columns = [];
+ for (var key in meta) {
+ // get column type
+ var column_type = meta[key];
+
+ // column index
+ var column_index = (parseInt(key) + 1);
+
+ // column type label
+ var column_label = 'Text';
+ if (column_type == 'int' || column_type == 'float') {
+ column_label = 'Number';
+ }
+
+ // add to selection
+ if (column_type == 'int' || column_type == 'float' || !numerical) {
+ columns.push({
+ 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
+ 'value' : column_index
+ });
+ }
}
- // add to selection
- if (column_type == 'int' || column_type == 'float' || !numerical) {
- columns.push({
- 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
- 'value' : column_index
- });
+ // update field
+ if (column_field) {
+ column_field.update(columns);
+ if (!column_field.exists(column_field.value())) {
+ column_field.value(column_field.first());
+ }
+ column_field.show();
}
}
-
- // update field
- if (column_field) {
- column_field.update(columns);
- if (!column_field.exists(column_field.value())) {
- column_field.value(column_field.first());
- }
- column_field.show();
- }
}
});
}
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-select-content.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js
@@ -0,0 +1,172 @@
+// dependencies
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
+
+var View = Backbone.View.extend({
+ // initialize
+ initialize : function(app, options) {
+ // configure options
+ this.options = options;
+
+ // link this
+ var self = this;
+
+ // add element
+ this.setElement('<div/>');
+
+ // current selection
+ this.current = 'hda';
+
+ // create button
+ this.button_new = new Ui.RadioButton.View({
+ value : this.current,
+ data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
+ { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
+ onchange: function(value) {
+ self.current = value;
+ self.refresh();
+ self.trigger('change');
+ }
+ });
+
+ //
+ // datasets
+ //
+ var datasets = app.content.filterType({
+ src : 'hda',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var dataset_options = [];
+ for (var i in datasets) {
+ dataset_options.push({
+ label: datasets[i].name,
+ value: datasets[i].id
+ });
+ }
+
+ // select field
+ this.select_datasets = new Ui.Select.View({
+ multiple : true,
+ data : dataset_options,
+ value : dataset_options[0] && dataset_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ //
+ // collections
+ //
+ var collections = app.content.filterType({
+ src : 'hdca',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var collection_options = [];
+ for (var i in collections) {
+ collection_options.push({
+ label: collections[i].name,
+ value: collections[i].id
+ });
+ }
+
+ // create select field for collections
+ this.select_collection = new Ui.Select.View({
+ data : collection_options,
+ value : collection_options[0] && collection_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ // add elements to dom
+ this.$el.append(Utils.wrap(this.button_new.$el));
+ this.$el.append(this.select_datasets.$el);
+ this.$el.append(this.select_collection.$el);
+
+ // check for batch mode
+ if (!this.options.multiple) {
+ this.$el.append(ToolTemplate.batchMode());
+ }
+
+ // refresh view
+ this.refresh();
+
+ // add change event. fires on trigger
+ this.on('change', function() {
+ if (options.onchange) {
+ options.onchange(self.value());
+ }
+ });
+ },
+
+ /** Return the currently selected dataset values */
+ value : function () {
+ // identify select element
+ var select = null;
+ switch(this.current) {
+ case 'hda':
+ select = this.select_datasets;
+ break;
+ case 'hdca':
+ select = this.select_collection;
+ break;
+ }
+
+ // transform into an array
+ var id_list = select.value();
+ if (!(id_list instanceof Array)) {
+ id_list = [id_list];
+ }
+
+ // prepare result dict
+ var result = {
+ batch : !this.options.multiple,
+ values : []
+ }
+
+ // append to dataset ids
+ for (var i in id_list) {
+ result.values.push({
+ id : id_list[i],
+ src : this.current
+ });
+ }
+
+ // return
+ return result;
+ },
+
+ /** Validate current selection
+ */
+ validate: function() {
+ switch(this.current) {
+ case 'hda':
+ return this.select_datasets.validate();
+ case 'hdca':
+ return this.select_collection.validate();
+ }
+ },
+
+ /** Refreshes data selection view */
+ refresh: function() {
+ switch (this.current) {
+ case 'hda':
+ this.select_datasets.$el.fadeIn();
+ this.select_collection.$el.hide();
+ break;
+ case 'hdca':
+ this.select_datasets.$el.hide();
+ this.select_collection.$el.fadeIn();
+ break;
+ }
+ }
+});
+
+return {
+ View: View
+}
+
+});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa client/galaxy/scripts/mvc/tools/tools-select-dataset.js
--- a/client/galaxy/scripts/mvc/tools/tools-select-dataset.js
+++ /dev/null
@@ -1,172 +0,0 @@
-// dependencies
-define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
-
-var View = Backbone.View.extend({
- // initialize
- initialize : function(app, options) {
- // configure options
- this.options = options;
-
- // link this
- var self = this;
-
- // add element
- this.setElement('<div/>');
-
- // current selection
- this.current = 'hda';
-
- // create button
- this.button_new = new Ui.RadioButton.View({
- value : this.current,
- data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
- { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
- onchange: function(value) {
- self.current = value;
- self.refresh();
- self.trigger('change');
- }
- });
-
- //
- // datasets
- //
- var datasets = app.datasets.filterType({
- content_type : 'dataset',
- data_types : options.extensions
- });
-
- // configure options fields
- var dataset_options = [];
- for (var i in datasets) {
- dataset_options.push({
- label: datasets[i].name,
- value: datasets[i].id
- });
- }
-
- // select field
- this.select_datasets = new Ui.Select.View({
- multiple : true,
- data : dataset_options,
- value : dataset_options[0] && dataset_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- //
- // collections
- //
- var collections = app.datasets.filterType({
- content_type : 'collection',
- data_types : options.extensions
- });
-
- // configure options fields
- var collection_options = [];
- for (var i in collections) {
- collection_options.push({
- label: collections[i].name,
- value: collections[i].id
- });
- }
-
- // create select field for collections
- this.select_collection = new Ui.Select.View({
- data : collection_options,
- value : collection_options[0] && collection_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- // add elements to dom
- this.$el.append(Utils.wrap(this.button_new.$el));
- this.$el.append(this.select_datasets.$el);
- this.$el.append(this.select_collection.$el);
-
- // check for batch mode
- if (!this.options.multiple) {
- this.$el.append(ToolTemplate.batchMode());
- }
-
- // refresh view
- this.refresh();
-
- // add change event. fires on trigger
- this.on('change', function() {
- if (options.onchange) {
- options.onchange(self.value());
- }
- });
- },
-
- /** Return the currently selected dataset values */
- value : function () {
- // identify select element
- var select = null;
- switch(this.current) {
- case 'hda':
- select = this.select_datasets;
- break;
- case 'hdca':
- select = this.select_collection;
- break;
- }
-
- // transform into an array
- var id_list = select.value();
- if (!(id_list instanceof Array)) {
- id_list = [id_list];
- }
-
- // prepare result dict
- var result = {
- batch : !this.options.multiple,
- values : []
- }
-
- // append to dataset ids
- for (var i in id_list) {
- result.values.push({
- id : id_list[i],
- src : this.current
- });
- }
-
- // return
- return result;
- },
-
- /** Validate current selection
- */
- validate: function() {
- switch(this.current) {
- case 'hda':
- return this.select_datasets.validate();
- case 'hdca':
- return this.select_collection.validate();
- }
- },
-
- /** Refreshes data selection view */
- refresh: function() {
- switch (this.current) {
- case 'hda':
- this.select_datasets.$el.fadeIn();
- this.select_collection.$el.hide();
- break;
- case 'hdca':
- this.select_datasets.$el.hide();
- this.select_collection.$el.fadeIn();
- break;
- }
- }
-});
-
-return {
- View: View
-}
-
-});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-content.js
--- /dev/null
+++ b/static/scripts/mvc/tools/tools-content.js
@@ -0,0 +1,132 @@
+define(['utils/utils'], function(Utils){
+ return Backbone.Model.extend({
+ // initialize
+ initialize: function(options) {
+ // backup basic url
+ this.base_url = galaxy_config.root + 'api/histories/' + options.history_id + '/contents';
+
+ // prepare content obects
+ this.datatypes = {};
+ this.summary = {};
+
+ // link this
+ var self = this;
+
+ // request datatypes
+ Utils.get({
+ url : galaxy_config.root + 'api/datatypes/mapping',
+ cache : true,
+ success : function(response) {
+ // backup datatype dictionary
+ self.datatypes = response;
+
+ // get history summary
+ Utils.get({
+ url : self.base_url + '?deleted=false',
+ success : function(response) {
+ // backup summary
+ self.summary = response;
+
+ // log
+ console.debug('tools-content::initialize() - Completed.');
+
+ // callback
+ options.success && options.success();
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for summary failed.');
+ console.debug(response);
+ }
+ });
+ },
+ error : function(response) {
+ // log request failure
+ console.debug('tools-content::initialize() - Ajax request for datatypes failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /**
+ * Filters contents by data type.
+ */
+ filterType: function(options) {
+ // initialize parameters
+ options = options || {};
+ var result = [];
+
+ // identify content type
+ var history_content_type = 'dataset';
+ if (options.src== 'hdca') {
+ history_content_type = 'dataset_collection';
+ }
+
+ // search in summary
+ for (var i in this.summary) {
+ var content = this.summary[i];
+
+ // match datatypes
+ var found = false;
+ for (var i in options.extensions) {
+ if (this._matchType(options.extensions[i], content.extension)) {
+ found = true;
+ break;
+ }
+ }
+
+ // final match result
+ if ((content.history_content_type === history_content_type) && (found || !options.extensions)) {
+ result.push(content);
+ }
+ }
+ return result;
+ },
+
+ /** Get details of a content by id.
+ */
+ getDetails: function(options) {
+ var api_url = this.base_url + '/datasets/' + options.id;
+ if (options.src == 'hdca') {
+ api_url = this.base_url + '/dataset_collections/' + options.id;
+ }
+ Utils.get({
+ url : api_url,
+ success : function(response) {
+ options.success && options.success(response);
+ },
+ error : function(response) {
+ console.debug('tools-content::getDetails() - Ajax request for content failed.');
+ console.debug(response);
+ }
+ });
+ },
+
+ /** Check if datatypes match
+ */
+ _matchType: function(target, reference) {
+ // check if target class is available
+ var target_class = this.datatypes.ext_to_class_name[target];
+ if (!target_class) {
+ console.debug('tools-content::_matchType() - Specific target class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check if reference class is available
+ var reference_class = this.datatypes.ext_to_class_name[reference];
+ if (!reference_class) {
+ console.debug('tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.');
+ return true;
+ }
+
+ // check reference group
+ var reference_group = this.datatypes.class_to_classes[reference_class];
+ if (reference_group[target_class]) {
+ return true;
+ }
+
+ // classes do not match
+ return false;
+ }
+ });
+});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-datasets.js
--- a/static/scripts/mvc/tools/tools-datasets.js
+++ /dev/null
@@ -1,117 +0,0 @@
-define(['utils/utils'], function(Utils){
- return Backbone.Model.extend({
- // initialize
- initialize: function(options) {
- // prepare datasets obects
- this.datatypes = {};
- this.summary = {};
-
- // link this
- var self = this;
-
- // request datatypes
- Utils.get({
- url : galaxy_config.root + 'api/datatypes/mapping',
- cache : true,
- success : function(response) {
- // backup datatype dictionary
- self.datatypes = response;
-
- // get history summary
- Utils.get({
- url : galaxy_config.root + 'api/histories/' + options.history_id + '/contents?deleted=false',
- success : function(response) {
- // backup summary
- self.summary = response;
-
- // log
- console.debug('tools-datasets::initialize() - Completed.');
-
- // callback
- options.success && options.success();
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for summary failed.');
- console.debug(response);
- }
- });
- },
- error : function(response) {
- // log request failure
- console.debug('tools-datasets::initialize() - Ajax request for datatypes failed.');
- console.debug(response);
- }
- });
- },
-
- /**
- * Filters datasets by data type.
- */
- filterType: function(options) {
- options = options || {};
- var result = [];
- for (var i in this.summary) {
- var dataset = this.summary[i];
-
- // match datatypes
- var found = false;
- for (var i in options.data_types) {
- if (this._matchType(options.data_types[i], dataset.extension)) {
- found = true;
- break;
- }
- }
-
- // final match result
- if ((dataset.history_content_type === options.content_type || !options.content_type) && (found || !options.data_types)) {
- result.push(dataset);
- }
- }
- return result;
- },
-
- /** Get details of a dataset by id.
- * @param{String} Dataset id
- */
- getDetails: function(dataset_id, callback) {
- Utils.get({
- url : galaxy_config.root + 'api/datasets/' + dataset_id,
- success : function(response) {
- callback && callback(response);
- },
- error : function(response) {
- console.debug('tools-datasets::getDetails() - Ajax request for dataset failed.');
- console.debug(response);
- }
- });
- },
-
- /** Check if datatypes match
- */
- _matchType: function(target, reference) {
- // check if target class is available
- var target_class = this.datatypes.ext_to_class_name[target];
- if (!target_class) {
- console.debug('tools-datasets::_matchType() - Specific target class unavailable. Accepting all formats.');
- return true;
- }
-
- // check if reference class is available
- var reference_class = this.datatypes.ext_to_class_name[reference];
- if (!reference_class) {
- console.debug('tools-datasets::_matchType() - Specific reference class unavailable. Accepting all formats.');
- return true;
- }
-
- // check reference group
- var reference_group = this.datatypes.class_to_classes[reference_class];
- if (reference_group[target_class]) {
- return true;
- }
-
- // classes do not match
- return false;
- }
- });
-});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -3,9 +3,9 @@
*/
define(['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-datasets', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
+ 'mvc/tools', 'mvc/tools/tools-template', 'mvc/tools/tools-content', 'mvc/tools/tools-section', 'mvc/tools/tools-tree', 'mvc/tools/tools-jobs'],
function(Portlet, Ui, CitationModel, CitationView,
- Tools, ToolTemplate, ToolDatasets, ToolSection, ToolTree, ToolJobs) {
+ Tools, ToolTemplate, ToolContent, ToolSection, ToolTree, ToolJobs) {
// create tool model
var Model = Backbone.Model.extend({
@@ -61,8 +61,8 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize datasets
- this.datasets = new ToolDatasets({
+ // initialize contents
+ this.content = new ToolContent({
history_id : this.options.history_id,
success : function() {
self._initializeToolForm();
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-section.js
--- a/static/scripts/mvc/tools/tools-section.js
+++ b/static/scripts/mvc/tools/tools-section.js
@@ -1,8 +1,8 @@
/**
This class creates a tool form section and populates it with input elements. It also handles repeat blocks and conditionals by recursively creating new sub sections. New input elements can be plugged in by adding cases to the switch block defined in the _addRow() function.
*/
-define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-dataset'],
- function(Utils, Table, Ui, Repeat, SelectDataset) {
+define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-misc', 'mvc/tools/tools-repeat', 'mvc/tools/tools-select-content'],
+ function(Utils, Table, Ui, Repeat, SelectContent) {
// input field element wrapper
var InputElement = Backbone.View.extend({
@@ -268,12 +268,12 @@
field = this._fieldSelect(input_def);
break;
- // dataset
+ // data selector
case 'data':
field = this._fieldData(input_def);
break;
- // dataset column
+ // data column
case 'data_column':
field = this._fieldSelect(input_def);
break;
@@ -417,13 +417,15 @@
var id = input_def.id;
// select field
- return new SelectDataset.View(this.app, {
+ return new SelectContent.View(this.app, {
id : 'field-' + id,
extensions : input_def.extensions,
multiple : input_def.multiple,
onchange : function(dict) {
- // pick the first dataset only (todo: maybe collect multiple meta information)
- var value = dict.values[0].id;
+ // pick the first content only (todo: maybe collect multiple meta information)
+ var content_def = dict.values[0];
+ var content_id = content_def.id;
+ var content_src = content_def.src;
// get referenced columns
var column_list = self.app.tree.references(id, 'data_column');
@@ -440,71 +442,80 @@
column_field.wait && column_field.wait();
}
- // find selected dataset
- self.app.datasets.getDetails(value, function(dataset) {
- // meta data
- var meta = null;
-
- // check dataset
- if (dataset) {
- // log selection
- console.debug('tool-form::field_data() - Selected dataset ' + value + '.');
-
- // get meta data
- meta = dataset.metadata_column_types;
-
- // check meta data
- if (!meta) {
- console.debug('tool-form::field_data() - FAILED: Could not find metadata for dataset ' + value + '.');
+ // find selected content
+ self.app.content.getDetails({
+ id : content_id,
+ src : content_src,
+ success : function(content) {
+ // select the first dataset to represent collections
+ if (content_src == 'hdca' && content.elements && content.elements.length > 0) {
+ content = content.elements[0].object;
}
- } else {
- console.debug('tool-form::field_data() - FAILED: Could not find dataset ' + value + '.');
- }
-
- // update referenced columns
- for (var i in column_list) {
- // get column input/field
- var column_input = self.app.input_list[column_list[i]];
- var column_field = self.app.field_list[column_list[i]];
- if (!column_input || !column_field) {
- console.debug('tool-form::field_data() - FAILED: Column not found.');
+
+ // meta data
+ var meta = null;
+
+ // check content
+ if (content) {
+ // log selection
+ console.debug('tool-form::field_data() - Selected content ' + content_id + '.');
+
+ // get meta data
+ meta = content.metadata_column_types;
+
+ // check meta data
+ if (!meta) {
+ console.debug('tool-form::field_data() - FAILED: Could not find metadata for content ' + content_id + '.');
+ }
+ } else {
+ console.debug('tool-form::field_data() - FAILED: Could not find content ' + content_id + '.');
}
-
- // is numerical?
- var numerical = column_input.numerical;
- // identify column options
- var columns = [];
- for (var key in meta) {
- // get column type
- var column_type = meta[key];
+ // update referenced columns
+ for (var i in column_list) {
+ // get column input/field
+ var column_input = self.app.input_list[column_list[i]];
+ var column_field = self.app.field_list[column_list[i]];
+ if (!column_input || !column_field) {
+ console.debug('tool-form::field_data() - FAILED: Column not found.');
+ }
+
+ // is numerical?
+ var numerical = column_input.numerical;
- // column index
- var column_index = (parseInt(key) + 1);
-
- // column type label
- var column_label = 'Text';
- if (column_type == 'int' || column_type == 'float') {
- column_label = 'Number';
+ // identify column options
+ var columns = [];
+ for (var key in meta) {
+ // get column type
+ var column_type = meta[key];
+
+ // column index
+ var column_index = (parseInt(key) + 1);
+
+ // column type label
+ var column_label = 'Text';
+ if (column_type == 'int' || column_type == 'float') {
+ column_label = 'Number';
+ }
+
+ // add to selection
+ if (column_type == 'int' || column_type == 'float' || !numerical) {
+ columns.push({
+ 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
+ 'value' : column_index
+ });
+ }
}
- // add to selection
- if (column_type == 'int' || column_type == 'float' || !numerical) {
- columns.push({
- 'label' : 'Column: ' + column_index + ' [' + column_label + ']',
- 'value' : column_index
- });
+ // update field
+ if (column_field) {
+ column_field.update(columns);
+ if (!column_field.exists(column_field.value())) {
+ column_field.value(column_field.first());
+ }
+ column_field.show();
}
}
-
- // update field
- if (column_field) {
- column_field.update(columns);
- if (!column_field.exists(column_field.value())) {
- column_field.value(column_field.first());
- }
- column_field.show();
- }
}
});
}
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-select-content.js
--- /dev/null
+++ b/static/scripts/mvc/tools/tools-select-content.js
@@ -0,0 +1,172 @@
+// dependencies
+define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
+
+var View = Backbone.View.extend({
+ // initialize
+ initialize : function(app, options) {
+ // configure options
+ this.options = options;
+
+ // link this
+ var self = this;
+
+ // add element
+ this.setElement('<div/>');
+
+ // current selection
+ this.current = 'hda';
+
+ // create button
+ this.button_new = new Ui.RadioButton.View({
+ value : this.current,
+ data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
+ { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
+ onchange: function(value) {
+ self.current = value;
+ self.refresh();
+ self.trigger('change');
+ }
+ });
+
+ //
+ // datasets
+ //
+ var datasets = app.content.filterType({
+ src : 'hda',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var dataset_options = [];
+ for (var i in datasets) {
+ dataset_options.push({
+ label: datasets[i].name,
+ value: datasets[i].id
+ });
+ }
+
+ // select field
+ this.select_datasets = new Ui.Select.View({
+ multiple : true,
+ data : dataset_options,
+ value : dataset_options[0] && dataset_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ //
+ // collections
+ //
+ var collections = app.content.filterType({
+ src : 'hdca',
+ extensions : options.extensions
+ });
+
+ // configure options fields
+ var collection_options = [];
+ for (var i in collections) {
+ collection_options.push({
+ label: collections[i].name,
+ value: collections[i].id
+ });
+ }
+
+ // create select field for collections
+ this.select_collection = new Ui.Select.View({
+ data : collection_options,
+ value : collection_options[0] && collection_options[0].value,
+ onchange : function() {
+ self.trigger('change');
+ }
+ });
+
+ // add elements to dom
+ this.$el.append(Utils.wrap(this.button_new.$el));
+ this.$el.append(this.select_datasets.$el);
+ this.$el.append(this.select_collection.$el);
+
+ // check for batch mode
+ if (!this.options.multiple) {
+ this.$el.append(ToolTemplate.batchMode());
+ }
+
+ // refresh view
+ this.refresh();
+
+ // add change event. fires on trigger
+ this.on('change', function() {
+ if (options.onchange) {
+ options.onchange(self.value());
+ }
+ });
+ },
+
+ /** Return the currently selected dataset values */
+ value : function () {
+ // identify select element
+ var select = null;
+ switch(this.current) {
+ case 'hda':
+ select = this.select_datasets;
+ break;
+ case 'hdca':
+ select = this.select_collection;
+ break;
+ }
+
+ // transform into an array
+ var id_list = select.value();
+ if (!(id_list instanceof Array)) {
+ id_list = [id_list];
+ }
+
+ // prepare result dict
+ var result = {
+ batch : !this.options.multiple,
+ values : []
+ }
+
+ // append to dataset ids
+ for (var i in id_list) {
+ result.values.push({
+ id : id_list[i],
+ src : this.current
+ });
+ }
+
+ // return
+ return result;
+ },
+
+ /** Validate current selection
+ */
+ validate: function() {
+ switch(this.current) {
+ case 'hda':
+ return this.select_datasets.validate();
+ case 'hdca':
+ return this.select_collection.validate();
+ }
+ },
+
+ /** Refreshes data selection view */
+ refresh: function() {
+ switch (this.current) {
+ case 'hda':
+ this.select_datasets.$el.fadeIn();
+ this.select_collection.$el.hide();
+ break;
+ case 'hdca':
+ this.select_datasets.$el.hide();
+ this.select_collection.$el.fadeIn();
+ break;
+ }
+ }
+});
+
+return {
+ View: View
+}
+
+});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/mvc/tools/tools-select-dataset.js
--- a/static/scripts/mvc/tools/tools-select-dataset.js
+++ /dev/null
@@ -1,172 +0,0 @@
-// dependencies
-define(['utils/utils', 'mvc/ui/ui-misc', 'mvc/ui/ui-tabs', 'mvc/tools/tools-template'], function(Utils, Ui, Tabs, ToolTemplate) {
-
-var View = Backbone.View.extend({
- // initialize
- initialize : function(app, options) {
- // configure options
- this.options = options;
-
- // link this
- var self = this;
-
- // add element
- this.setElement('<div/>');
-
- // current selection
- this.current = 'hda';
-
- // create button
- this.button_new = new Ui.RadioButton.View({
- value : this.current,
- data : [ { icon: 'fa-file-o', label : 'Select datasets', value : 'hda' },
- { icon: 'fa-files-o', label : 'Select a collection', value : 'hdca' }],
- onchange: function(value) {
- self.current = value;
- self.refresh();
- self.trigger('change');
- }
- });
-
- //
- // datasets
- //
- var datasets = app.datasets.filterType({
- content_type : 'dataset',
- data_types : options.extensions
- });
-
- // configure options fields
- var dataset_options = [];
- for (var i in datasets) {
- dataset_options.push({
- label: datasets[i].name,
- value: datasets[i].id
- });
- }
-
- // select field
- this.select_datasets = new Ui.Select.View({
- multiple : true,
- data : dataset_options,
- value : dataset_options[0] && dataset_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- //
- // collections
- //
- var collections = app.datasets.filterType({
- content_type : 'collection',
- data_types : options.extensions
- });
-
- // configure options fields
- var collection_options = [];
- for (var i in collections) {
- collection_options.push({
- label: collections[i].name,
- value: collections[i].id
- });
- }
-
- // create select field for collections
- this.select_collection = new Ui.Select.View({
- data : collection_options,
- value : collection_options[0] && collection_options[0].value,
- onchange : function() {
- self.trigger('change');
- }
- });
-
- // add elements to dom
- this.$el.append(Utils.wrap(this.button_new.$el));
- this.$el.append(this.select_datasets.$el);
- this.$el.append(this.select_collection.$el);
-
- // check for batch mode
- if (!this.options.multiple) {
- this.$el.append(ToolTemplate.batchMode());
- }
-
- // refresh view
- this.refresh();
-
- // add change event. fires on trigger
- this.on('change', function() {
- if (options.onchange) {
- options.onchange(self.value());
- }
- });
- },
-
- /** Return the currently selected dataset values */
- value : function () {
- // identify select element
- var select = null;
- switch(this.current) {
- case 'hda':
- select = this.select_datasets;
- break;
- case 'hdca':
- select = this.select_collection;
- break;
- }
-
- // transform into an array
- var id_list = select.value();
- if (!(id_list instanceof Array)) {
- id_list = [id_list];
- }
-
- // prepare result dict
- var result = {
- batch : !this.options.multiple,
- values : []
- }
-
- // append to dataset ids
- for (var i in id_list) {
- result.values.push({
- id : id_list[i],
- src : this.current
- });
- }
-
- // return
- return result;
- },
-
- /** Validate current selection
- */
- validate: function() {
- switch(this.current) {
- case 'hda':
- return this.select_datasets.validate();
- case 'hdca':
- return this.select_collection.validate();
- }
- },
-
- /** Refreshes data selection view */
- refresh: function() {
- switch (this.current) {
- case 'hda':
- this.select_datasets.$el.fadeIn();
- this.select_collection.$el.hide();
- break;
- case 'hdca':
- this.select_datasets.$el.hide();
- this.select_collection.$el.fadeIn();
- break;
- }
- }
-});
-
-return {
- View: View
-}
-
-});
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-content.js
--- /dev/null
+++ b/static/scripts/packed/mvc/tools/tools-content.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.base_url=galaxy_config.root+"api/histories/"+c.history_id+"/contents";this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:b.base_url+"?deleted=false",success:function(e){b.summary=e;console.debug("tools-content::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-content::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-content::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];var g="dataset";if(c.src=="hdca"){g="dataset_collection"}for(var d in this.summary){var e=this.summary[d];var f=false;for(var d in c.extensions){if(this._matchType(c.extensions[d],e.extension)){f=true;break}}if((e.history_content_type===g)&&(f||!c.extensions)){b.push(e)}}return b},getDetails:function(b){var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-content::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-datasets.js
--- a/static/scripts/packed/mvc/tools/tools-datasets.js
+++ /dev/null
@@ -1,1 +0,0 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:galaxy_config.root+"api/histories/"+c.history_id+"/contents?deleted=false",success:function(e){b.summary=e;console.debug("tools-datasets::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-datasets::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-datasets::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];for(var d in this.summary){var f=this.summary[d];var e=false;for(var d in c.data_types){if(this._matchType(c.data_types[d],f.extension)){e=true;break}}if((f.history_content_type===c.content_type||!c.content_type)&&(e||!c.data_types)){b.push(f)}}return b},getDetails:function(b,c){a.get({url:galaxy_config.root+"api/datasets/"+b,success:function(d){c&&c(d)},error:function(d){console.debug("tools-datasets::getDetails() - Ajax request for dataset failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-datasets::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-datasets::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa 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(["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-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
+define(["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,l,j,a,f,d,g,k,c,h){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new h(this);this.field_list={};this.input_list={};this.element_list={};this.content=new g({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new i.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa 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-dataset"],function(d,a,g,c,b){var e=Backbone.View.extend({initialize:function(h){this.setElement(this._template(h))},error:function(h){this.$el.find(".ui-table-form-error-text").html(h);this.$el.find(".ui-table-form-error").fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$el.find(".ui-table-form-error").hide();this.$el.removeClass("ui-error")},_template:function(h){var i=$('<div class="ui-table-element"/>');i.append('<div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');if(h.label){i.append('<div class="ui-table-form-title-strong">'+h.label+"</div>")}i.append(h.$el);if(h.help){i.append('<div class="ui-table-form-info">'+h.help+"</div>")}return i}});var f=Backbone.View.extend({initialize:function(i,h){this.app=i;this.inputs=h.inputs;h.cls_tr="section-row";this.table=new a.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=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(k,h)}},_addConditional:function(h){h.label=h.test_param.label;h.value=h.test_param.value;var j=this._addRow("conditional",h);for(var l in h.cases){var k=h.id+"-section-"+l;var m=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});m.$el.addClass("ui-table-form-section");this.table.add(m.$el);this.table.append(k)}},_addRepeat:function(h){var j=this;var n=0;var m=new c.View({title_new:h.title,max:h.max,onnew:function(){var i=h.id+"-section-"+(n++);var q=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:i,title:h.title,$el:q.$el,ondel:function(){m.del(i);m.retitle(h.title);j.app.refresh()}});m.retitle(h.title);j.app.refresh()}});for(var l=0;l<h.min;l++){var k=h.id+"-section-"+(n++);var p=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:k,title:h.title,$el:p.$el})}m.retitle(h.title);var o=new e({label:h.title,help:h.help,$el:m.$el});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(h.id)},_addRow:function(j,h){var l=h.id;var i=null;switch(j){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_column":i=this._fieldSelect(h);break;case"conditional":i=this._fieldConditional(h);break;case"hidden":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":i=this._fieldSelect(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 ("+j+").")}if(h.value!==undefined){i.value(h.value)}this.app.field_list[l]=i;var k=new e({label:h.label,help:h.help,$el:i.$el});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);return this.table.get(l)},_fieldConditional:function(h){var j=this;var k=[];for(var l in h.test_param.options){var m=h.test_param.options[l];k.push({label:m[0],value:m[1]})}return new g.Select.View({id:"field-"+h.id,data:k,onchange:function(u){for(var s in h.cases){var o=h.cases[s];var r=h.id+"-section-"+s;var n=j.table.get(r);var q=false;for(var p in o.inputs){var t=o.inputs[p].type;if(t&&t!=="hidden"){q=true;break}}if(o.value==u&&q){n.fadeIn("fast")}else{n.hide()}}}})},_fieldData:function(h){var i=this;var j=h.id;return new b.View(this.app,{id:"field-"+j,extensions:h.extensions,multiple:h.multiple,onchange:function(o){var n=o.values[0].id;var l=i.app.tree.references(j,"data_column");if(l.length<=0){console.debug("tool-form::field_data() - Data column parameters unavailable.");return}for(var m in l){var k=i.app.field_list[l[m]];k.wait&&k.wait()}i.app.datasets.getDetails(n,function(r){var z=null;if(r){console.debug("tool-form::field_data() - Selected dataset "+n+".");z=r.metadata_column_types;if(!z){console.debug("tool-form::field_data() - FAILED: Could not find metadata for dataset "+n+".")}}else{console.debug("tool-form::field_data() - FAILED: Could not find dataset "+n+".")}for(var t in l){var v=i.app.input_list[l[t]];var w=i.app.field_list[l[t]];if(!v||!w){console.debug("tool-form::field_data() - FAILED: Column not found.")}var s=v.numerical;var q=[];for(var y in z){var x=z[y];var p=(parseInt(y)+1);var u="Text";if(x=="int"||x=="float"){u="Number"}if(x=="int"||x=="float"||!s){q.push({label:"Column: "+p+" ["+u+"]",value:p})}}if(w){w.update(q);if(!w.exists(w.value())){w.value(w.first())}w.show()}}})}})},_fieldSelect:function(h){var j=[];for(var k in h.options){var l=h.options[k];j.push({label:l[0],value:l[1]})}var m=g.Select;switch(h.display){case"checkboxes":m=g.Checkbox;break;case"radio":m=g.Radio;break}return new m.View({id:"field-"+h.id,data:j,multiple:h.multiple})},_fieldText:function(h){return new g.Input({id:"field-"+h.id,area:h.area})},_fieldSlider:function(h){h.min=h.min||0;h.max=h.max||100000;var i=1;if(h.type=="float"){i=(h.max-h.min)/10000}return new g.Slider.View({id:"field-"+h.id,min:h.min,max:h.max,step:i})},_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"],function(d,b,g,c,a){var e=Backbone.View.extend({initialize:function(h){this.setElement(this._template(h))},error:function(h){this.$el.find(".ui-table-form-error-text").html(h);this.$el.find(".ui-table-form-error").fadeIn();this.$el.addClass("ui-error")},reset:function(){this.$el.find(".ui-table-form-error").hide();this.$el.removeClass("ui-error")},_template:function(h){var i=$('<div class="ui-table-element"/>');i.append('<div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>');if(h.label){i.append('<div class="ui-table-form-title-strong">'+h.label+"</div>")}i.append(h.$el);if(h.help){i.append('<div class="ui-table-form-info">'+h.help+"</div>")}return i}});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=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(k,h)}},_addConditional:function(h){h.label=h.test_param.label;h.value=h.test_param.value;var j=this._addRow("conditional",h);for(var l in h.cases){var k=h.id+"-section-"+l;var m=new f(this.app,{inputs:h.cases[l].inputs,cls:"ui-table-plain"});m.$el.addClass("ui-table-form-section");this.table.add(m.$el);this.table.append(k)}},_addRepeat:function(h){var j=this;var n=0;var m=new c.View({title_new:h.title,max:h.max,onnew:function(){var i=h.id+"-section-"+(n++);var q=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:i,title:h.title,$el:q.$el,ondel:function(){m.del(i);m.retitle(h.title);j.app.refresh()}});m.retitle(h.title);j.app.refresh()}});for(var l=0;l<h.min;l++){var k=h.id+"-section-"+(n++);var p=new f(j.app,{inputs:h.inputs,cls:"ui-table-plain"});m.add({id:k,title:h.title,$el:p.$el})}m.retitle(h.title);var o=new e({label:h.title,help:h.help,$el:m.$el});o.$el.addClass("ui-table-form-section");this.table.add(o.$el);this.table.append(h.id)},_addRow:function(j,h){var l=h.id;var i=null;switch(j){case"text":i=this._fieldText(h);break;case"select":i=this._fieldSelect(h);break;case"data":i=this._fieldData(h);break;case"data_column":i=this._fieldSelect(h);break;case"conditional":i=this._fieldConditional(h);break;case"hidden":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":i=this._fieldSelect(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 ("+j+").")}if(h.value!==undefined){i.value(h.value)}this.app.field_list[l]=i;var k=new e({label:h.label,help:h.help,$el:i.$el});this.app.element_list[l]=k;this.table.add(k.$el);this.table.append(l);return this.table.get(l)},_fieldConditional:function(h){var j=this;var k=[];for(var l in h.test_param.options){var m=h.test_param.options[l];k.push({label:m[0],value:m[1]})}return new g.Select.View({id:"field-"+h.id,data:k,onchange:function(u){for(var s in h.cases){var o=h.cases[s];var r=h.id+"-section-"+s;var n=j.table.get(r);var q=false;for(var p in o.inputs){var t=o.inputs[p].type;if(t&&t!=="hidden"){q=true;break}}if(o.value==u&&q){n.fadeIn("fast")}else{n.hide()}}}})},_fieldData:function(h){var i=this;var j=h.id;return new a.View(this.app,{id:"field-"+j,extensions:h.extensions,multiple:h.multiple,onchange:function(q){var o=q.values[0];var m=o.id;var p=o.src;var l=i.app.tree.references(j,"data_column");if(l.length<=0){console.debug("tool-form::field_data() - Data column parameters unavailable.");return}for(var n in l){var k=i.app.field_list[l[n]];k.wait&&k.wait()}i.app.content.getDetails({id:m,src:p,success:function(y){if(p=="hdca"&&y.elements&&y.elements.length>0){y=y.elements[0].object}var B=null;if(y){console.debug("tool-form::field_data() - Selected content "+m+".");B=y.metadata_column_types;if(!B){console.debug("tool-form::field_data() - FAILED: Could not find metadata for content "+m+".")}}else{console.debug("tool-form::field_data() - FAILED: Could not find content "+m+".")}for(var u in l){var w=i.app.input_list[l[u]];var x=i.app.field_list[l[u]];if(!w||!x){console.debug("tool-form::field_data() - FAILED: Column not found.")}var t=w.numerical;var s=[];for(var A in B){var z=B[A];var r=(parseInt(A)+1);var v="Text";if(z=="int"||z=="float"){v="Number"}if(z=="int"||z=="float"||!t){s.push({label:"Column: "+r+" ["+v+"]",value:r})}}if(x){x.update(s);if(!x.exists(x.value())){x.value(x.first())}x.show()}}}})}})},_fieldSelect:function(h){var j=[];for(var k in h.options){var l=h.options[k];j.push({label:l[0],value:l[1]})}var m=g.Select;switch(h.display){case"checkboxes":m=g.Checkbox;break;case"radio":m=g.Radio;break}return new m.View({id:"field-"+h.id,data:j,multiple:h.multiple})},_fieldText:function(h){return new g.Input({id:"field-"+h.id,area:h.area})},_fieldSlider:function(h){h.min=h.min||0;h.max=h.max||100000;var i=1;if(h.type=="float"){i=(h.max-h.min)/10000}return new g.Slider.View({id:"field-"+h.id,min:h.min,max:h.max,step:i})},_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
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-select-content.js
--- /dev/null
+++ b/static/scripts/packed/mvc/tools/tools-select-content.js
@@ -0,0 +1,1 @@
+define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.content.filterType({src:"hda",extensions:h.extensions});var k=[];for(var j in l){k.push({label:l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.content.filterType({src:"hdca",extensions:h.extensions});var f=[];for(var j in m){f.push({label:m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(){var g=null;switch(this.current){case"hda":g=this.select_datasets;break;case"hdca":g=this.select_collection;break}var j=g.value();if(!(j instanceof Array)){j=[j]}var f={batch:!this.options.multiple,values:[]};for(var h in j){f.values.push({id:j[h],src:this.current})}return f},validate:function(){switch(this.current){case"hda":return this.select_datasets.validate();case"hdca":return this.select_collection.validate()}},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}}});return{View:d}});
\ No newline at end of file
diff -r 0e99c30878af56e23f447854a7ae70b412a9d627 -r a979bd1bb19498aa93eb7da56f7a392bea14dfaa static/scripts/packed/mvc/tools/tools-select-dataset.js
--- a/static/scripts/packed/mvc/tools/tools-select-dataset.js
+++ /dev/null
@@ -1,1 +0,0 @@
-define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.datasets.filterType({content_type:"dataset",data_types:h.extensions});var k=[];for(var j in l){k.push({label:l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.datasets.filterType({content_type:"collection",data_types:h.extensions});var f=[];for(var j in m){f.push({label:m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(){var g=null;switch(this.current){case"hda":g=this.select_datasets;break;case"hdca":g=this.select_collection;break}var j=g.value();if(!(j instanceof Array)){j=[j]}var f={batch:!this.options.multiple,values:[]};for(var h in j){f.values.push({id:j[h],src:this.current})}return f},validate:function(){switch(this.current){case"hda":return this.select_datasets.validate();case"hdca":return this.select_collection.validate()}},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}}});return{View:d}});
\ 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: Fix automated form switching
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0e99c30878af/
Changeset: 0e99c30878af
User: guerler
Date: 2014-10-07 18:39:33+00:00
Summary: ToolForm: Fix automated form switching
Affected #: 3 files
diff -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 -r 0e99c30878af56e23f447854a7ae70b412a9d627 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
@@ -217,9 +217,6 @@
citations.fetch();
}
- // configure portlet and form table
- self.setElement(self.portlet.content());
-
// append tool section
self.portlet.append(self.section.$el);
diff -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 -r 0e99c30878af56e23f447854a7ae70b412a9d627 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -217,9 +217,6 @@
citations.fetch();
}
- // configure portlet and form table
- self.setElement(self.portlet.content());
-
// append tool section
self.portlet.append(self.section.$el);
diff -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 -r 0e99c30878af56e23f447854a7ae70b412a9d627 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(["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-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.setElement(n.portlet.content());n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
+define(["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-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ 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: Add download button, prepare for activation
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f94fbe948b7a/
Changeset: f94fbe948b7a
User: guerler
Date: 2014-10-07 17:52:53+00:00
Summary: ToolForm: Add download button, prepare for activation
Affected #: 5 files
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 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
@@ -42,7 +42,8 @@
// load tool model
this.model = new Model({
- id : options.id
+ id : options.id,
+ job_id : options.job_id
});
// creates a tree/json structure from the input form
@@ -93,7 +94,7 @@
}
// log
- console.debug('tools-form::refresh() - Recreated tree structure. Refresh.');
+ console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
// initialize tool form
@@ -131,6 +132,26 @@
}
});
+ // default operations
+ var operations = {
+ button_question: button_question,
+ button_search: button_search,
+ button_share: button_share
+ }
+
+ // add admin operations
+ if (Galaxy.currUser.get('is_admin')) {
+ // create download button
+ operations['button_download'] = new Ui.ButtonIcon({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + self.options.id + '/download';
+ }
+ });
+ }
+
// fetch model and render form
this.model.fetch({
error: function(response) {
@@ -155,6 +176,7 @@
self.portlet = new Portlet.View({
icon : 'fa-wrench',
title: '<b>' + self.model.get('name') + '</b> ' + self.model.get('description'),
+ operations: operations,
buttons: {
execute: new Ui.ButtonIcon({
icon : 'fa-check',
@@ -165,11 +187,6 @@
self.job_handler.submit();
}
})
- },
- operations: {
- button_question: button_question,
- button_search: button_search,
- button_share: button_share
}
});
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -264,6 +264,7 @@
toolbox=self.get_toolbox(),
tool_version_select_field=tool_version_select_field,
tool=tool,
+ job=job,
util=galaxy.util,
add_frame=add_frame,
tool_id_version_message=tool_id_version_message,
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -42,7 +42,8 @@
// load tool model
this.model = new Model({
- id : options.id
+ id : options.id,
+ job_id : options.job_id
});
// creates a tree/json structure from the input form
@@ -93,7 +94,7 @@
}
// log
- console.debug('tools-form::refresh() - Recreated tree structure. Refresh.');
+ console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
// initialize tool form
@@ -131,6 +132,26 @@
}
});
+ // default operations
+ var operations = {
+ button_question: button_question,
+ button_search: button_search,
+ button_share: button_share
+ }
+
+ // add admin operations
+ if (Galaxy.currUser.get('is_admin')) {
+ // create download button
+ operations['button_download'] = new Ui.ButtonIcon({
+ icon : 'fa-download',
+ title : 'Download',
+ tooltip : 'Download this tool',
+ onclick : function() {
+ window.location.href = galaxy_config.root + 'api/tools/' + self.options.id + '/download';
+ }
+ });
+ }
+
// fetch model and render form
this.model.fetch({
error: function(response) {
@@ -155,6 +176,7 @@
self.portlet = new Portlet.View({
icon : 'fa-wrench',
title: '<b>' + self.model.get('name') + '</b> ' + self.model.get('description'),
+ operations: operations,
buttons: {
execute: new Ui.ButtonIcon({
icon : 'fa-check',
@@ -165,11 +187,6 @@
self.job_handler.submit();
}
})
- },
- operations: {
- button_question: button_question,
- button_search: button_search,
- button_share: button_share
}
});
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 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(["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-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated tree structure. Refresh.")},_initializeToolForm:function(){var n=this;var o=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var p=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});this.model.fetch({error:function(q){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})},operations:{button_question:o,button_search:p,button_share:m}});if(!n.options.biostar_url){o.$el.hide();p.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var q=new j.ToolCitationCollection();q.tool_id=n.options.id;var r=new a.CitationListView({collection:q});r.render();q.fetch()}n.setElement(n.portlet.content());n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
+define(["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-datasets","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(h,l,j,a,f,d,i,k,c,g){var e=Backbone.Model.extend({initialize:function(m){this.url=galaxy_config.root+"api/tools/"+m.id+"?io_details=true"}});var b=Backbone.View.extend({container:"body",initialize:function(n){var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.model=new e({id:n.id,job_id:n.job_id});this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.datasets=new i({history_id:this.options.history_id,success:function(){m._initializeToolForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_initializeToolForm:function(){var n=this;var p=new l.ButtonIcon({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});var q=new l.ButtonIcon({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});var m=new l.ButtonIcon({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",galaxy_config.root+"root?tool_id="+n.options.id)}});var o={button_question:p,button_search:q,button_share:m};if(Galaxy.currUser.get("is_admin")){o.button_download=new l.ButtonIcon({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.model.fetch({error:function(r){console.debug("tools-form::_initializeToolForm() : Attempt to fetch tool model failed.")},success:function(){n.section=new k.View(n,{inputs:n.model.get("inputs"),cls:"ui-table-plain"});if(n.incompatible){n.$el.hide();$("#tool-form-classic").show();return}n.portlet=new h.View({icon:"fa-wrench",title:"<b>"+n.model.get("name")+"</b> "+n.model.get("description"),operations:o,buttons:{execute:new l.ButtonIcon({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!n.options.biostar_url){p.$el.hide();q.$el.hide()}n.$el.append(n.portlet.$el);if(n.options.help!=""){n.$el.append(d.help(n.options.help))}if(n.options.citations){n.$el.append(d.citations());var r=new j.ToolCitationCollection();r.tool_id=n.options.id;var s=new a.CitationListView({collection:r});s.render();r.fetch()}n.setElement(n.portlet.content());n.portlet.append(n.section.$el);n.refresh()}})}});return{View:b}});
\ No newline at end of file
diff -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 -r f94fbe948b7a37b386ee8e3f5591ec7e70d94d16 templates/webapps/galaxy/tool_form.api.mako
--- a/templates/webapps/galaxy/tool_form.api.mako
+++ b/templates/webapps/galaxy/tool_form.api.mako
@@ -27,7 +27,8 @@
'help' : tool_help,
'citations' : tool_citations,
'biostar_url' : trans.app.config.biostar_url,
- 'history_id' : trans.security.encode_id( trans.history.id )
+ 'history_id' : trans.security.encode_id( trans.history.id ),
+ 'job_id' : trans.security.encode_id( job.id ) if job else None
}
%>
${h.js("libs/bibtex", "libs/jquery/jquery-ui")}
@@ -40,14 +41,6 @@
});
</script>
-##%if tool.tool_shed_repository:
-## <% tool_url = tool.tool_shed_repository.get_sharable_url( tool.app ) %>
-## %if tool_url:
-## <br/>
-## ${ render_msg( 'This tool was installed from a ToolShed, you may be able to find additional information by following this link: <a href="%s" target="_blank">%s</a>' % ( tool_url, tool_url ), 'info' ) }
-## %endif
-##%endif
-
## classic tool form
<div id="tool-form-classic" style="display: none;"><%include file="tool_form.mako"/>
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: Method for using local network (e.g. NFS) to distribute cached docker images across clusters.
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a3cff55b129f/
Changeset: a3cff55b129f
User: jmchilton
Date: 2014-10-07 17:28:43+00:00
Summary: Method for using local network (e.g. NFS) to distribute cached docker images across clusters.
General idea and outline for short caching script embedded in containers.py from Kyle Ellrott.
Affected #: 4 files
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -143,6 +143,7 @@
self.cluster_files_directory = os.path.abspath( kwargs.get( "cluster_files_directory", "database/pbs" ) )
self.job_working_directory = resolve_path( kwargs.get( "job_working_directory", "database/job_working_directory" ), self.root )
self.cleanup_job = kwargs.get( "cleanup_job", "always" )
+ self.container_image_cache_path = self.resolve_path( kwargs.get( "container_image_cache_path", "database/container_images" ) )
self.outputs_to_working_directory = string_as_bool( kwargs.get( 'outputs_to_working_directory', False ) )
self.output_size_limit = int( kwargs.get( 'output_size_limit', 0 ) )
self.retry_job_output_collection = int( kwargs.get( 'retry_job_output_collection', 0 ) )
@@ -640,7 +641,8 @@
app_info = containers.AppInfo(
galaxy_root_dir,
default_file_path=file_path,
- outputs_to_working_directory=self.config.outputs_to_working_directory
+ outputs_to_working_directory=self.config.outputs_to_working_directory,
+ container_image_cache_path=self.config.container_image_cache_path,
)
self.container_finder = galaxy.tools.deps.containers.ContainerFinder(app_info)
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/tools/deps/containers.py
--- a/lib/galaxy/tools/deps/containers.py
+++ b/lib/galaxy/tools/deps/containers.py
@@ -13,6 +13,29 @@
DEFAULT_CONTAINER_TYPE = "docker"
+LOAD_CACHED_IMAGE_COMMAND_TEMPLATE = '''
+python << EOF
+import re, tarfile, json, subprocess
+t = tarfile.TarFile("${cached_image_file}")
+meta_str = t.extractfile('repositories').read()
+meta = json.loads(meta_str)
+tag, tag_value = meta.items()[0]
+rev, rev_value = tag_value.items()[0]
+cmd = "${images_cmd}"
+proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
+stdo, stde = proc.communicate()
+found = False
+for line in stdo.split("\\n"):
+ tmp = re.split(r'\s+', line)
+ if tmp[0] == tag and tmp[1] == rev and tmp[2] == rev_value:
+ found = True
+if not found:
+ print "Loading image"
+ cmd = "cat ${cached_image_file} | ${load_cmd}"
+ subprocess.check_call(cmd, shell=True)
+EOF
+'''
+
class ContainerFinder(object):
@@ -117,11 +140,18 @@
class AppInfo(object):
- def __init__(self, galaxy_root_dir=None, default_file_path=None, outputs_to_working_directory=False):
+ def __init__(
+ self,
+ galaxy_root_dir=None,
+ default_file_path=None,
+ outputs_to_working_directory=False,
+ container_image_cache_path=None,
+ ):
self.galaxy_root_dir = galaxy_root_dir
self.default_file_path = default_file_path
# TODO: Vary default value for docker_volumes based on this...
self.outputs_to_working_directory = outputs_to_working_directory
+ self.container_image_cache_path = container_image_cache_path
class ToolInfo(object):
@@ -199,7 +229,12 @@
host=prop("host", docker_util.DEFAULT_HOST),
)
- cache_command = docker_util.build_docker_cache_command(self.container_id, **docker_host_props)
+ cached_image_file = self.__get_cached_image_file()
+ if not cached_image_file:
+ # TODO: Add option to cache it once here and create cached_image_file.
+ cache_command = docker_util.build_docker_cache_command(self.container_id, **docker_host_props)
+ else:
+ cache_command = self.__cache_from_file_command(cached_image_file, docker_host_props)
run_command = docker_util.build_docker_run_command(
command,
self.container_id,
@@ -213,6 +248,29 @@
)
return "%s\n%s" % (cache_command, run_command)
+ def __cache_from_file_command(self, cached_image_file, docker_host_props):
+ images_cmd = docker_util.build_docker_images_command(truncate=False, **docker_host_props)
+ load_cmd = docker_util.build_docker_load_command(**docker_host_props)
+
+ return string.Template(LOAD_CACHED_IMAGE_COMMAND_TEMPLATE).safe_substitute(
+ cached_image_file=cached_image_file,
+ images_cmd=images_cmd,
+ load_cmd=load_cmd
+ )
+
+ def __get_cached_image_file(self):
+ container_id = self.container_id
+ cache_directory = os.path.abspath(self.__get_destination_overridable_property("container_image_cache_path"))
+ cache_path = docker_cache_path(cache_directory, container_id)
+ return cache_path if os.path.exists(cache_path) else None
+
+ def __get_destination_overridable_property(self, name):
+ prop_name = "docker_%s" % name
+ if prop_name in self.destination_info:
+ return self.destination_info[prop_name]
+ else:
+ return getattr(self.app_info, name)
+
def __expand_str(self, value):
if not value:
return value
@@ -248,6 +306,12 @@
return template.safe_substitute(variables)
+def docker_cache_path(cache_directory, container_id):
+ file_container_id = container_id.replace("/", "_slash_")
+ cache_file_name = "docker_%s.tar" % file_container_id
+ return os.path.join(cache_directory, cache_file_name)
+
+
CONTAINER_CLASSES = dict(
docker=DockerContainer,
)
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -55,14 +55,11 @@
def build_command(
image,
docker_build_path,
- docker_cmd=DEFAULT_DOCKER_COMMAND,
- sudo=DEFAULT_SUDO,
- sudo_cmd=DEFAULT_SUDO_COMMAND,
- host=DEFAULT_HOST,
+ **kwds
):
if os.path.isfile(docker_build_path):
docker_build_path = os.path.dirname(os.path.abspath(docker_build_path))
- build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts = __docker_prefix(**kwds)
build_command_parts.extend(["build", "-t", image, docker_build_path])
return build_command_parts
@@ -70,34 +67,42 @@
def build_save_image_command(
image,
destination,
- docker_cmd=DEFAULT_DOCKER_COMMAND,
- sudo=DEFAULT_SUDO,
- sudo_cmd=DEFAULT_SUDO_COMMAND,
- host=DEFAULT_HOST,
+ **kwds
):
- build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts = __docker_prefix(**kwds)
build_command_parts.extend(["save", "-o", destination, image])
return build_command_parts
def build_docker_cache_command(
image,
- docker_cmd=DEFAULT_DOCKER_COMMAND,
- sudo=DEFAULT_SUDO,
- sudo_cmd=DEFAULT_SUDO_COMMAND,
- host=DEFAULT_HOST,
+ **kwds
):
- inspect_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ inspect_command_parts = __docker_prefix(**kwds)
inspect_command_parts.extend(["inspect", image])
inspect_image_command = " ".join(inspect_command_parts)
- pull_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ pull_command_parts = __docker_prefix(**kwds)
pull_command_parts.extend(["pull", image])
pull_image_command = " ".join(pull_command_parts)
cache_command = "%s > /dev/null 2>&1\n[ $? -ne 0 ] && %s > /dev/null 2>&1\n" % (inspect_image_command, pull_image_command)
return cache_command
+def build_docker_images_command(truncate=True, **kwds):
+ images_command_parts = __docker_prefix(**kwds)
+ images_command_parts.append("images")
+ if not truncate:
+ images_command_parts.append("--no-trunc")
+ return " ".join(images_command_parts)
+
+
+def build_docker_load_command(**kwds):
+ load_command_parts = __docker_prefix(**kwds)
+ load_command_parts.append("load")
+ return " ".join(load_command_parts)
+
+
def build_docker_run_command(
container_command,
image,
@@ -116,7 +121,12 @@
auto_rm=DEFAULT_AUTO_REMOVE,
host=DEFAULT_HOST,
):
- command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ command_parts = __docker_prefix(
+ docker_cmd=docker_cmd,
+ sudo=sudo,
+ sudo_cmd=sudo_cmd,
+ host=host
+ )
command_parts.append("run")
if interactive:
command_parts.append("-i")
@@ -144,7 +154,13 @@
return " ".join(command_parts)
-def __docker_prefix(docker_cmd, sudo, sudo_cmd, host):
+def __docker_prefix(
+ docker_cmd=DEFAULT_DOCKER_COMMAND,
+ sudo=DEFAULT_SUDO,
+ sudo_cmd=DEFAULT_SUDO_COMMAND,
+ host=DEFAULT_HOST,
+ **kwds
+):
""" Prefix to issue a docker command.
"""
command_parts = []
diff -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 -r a3cff55b129fcbf9b8e359ff0f71cb844a7e9277 lib/galaxy/tools/deps/dockerfiles.py
--- a/lib/galaxy/tools/deps/dockerfiles.py
+++ b/lib/galaxy/tools/deps/dockerfiles.py
@@ -2,6 +2,7 @@
from ..deps import commands
from ..deps import docker_util
+from ..deps.containers import docker_cache_path
from ..deps.requirements import parse_requirements_from_xml
from ...tools import loader_directory
@@ -20,11 +21,13 @@
def dockerfile_build(path, dockerfile=None, error=log.error, **kwds):
expected_container_names = set()
+ tool_directories = set()
for (tool_path, tool_xml) in loader_directory.load_tool_elements_from_path(path):
requirements, containers = parse_requirements_from_xml(tool_xml)
for container in containers:
if container.type == "docker":
expected_container_names.add(container.identifier)
+ tool_directories.add(os.path.dirname(tool_path))
break
if len(expected_container_names) == 0:
@@ -34,9 +37,8 @@
error("Multiple different docker identifiers found for selected tools [%s]", expected_container_names)
image_identifier = expected_container_names.pop()
- if dockerfile is None:
- dockerfile = "Dockerfile"
+ dockerfile = __find_dockerfile(dockerfile, tool_directories)
docker_command_parts = docker_util.build_command(
image_identifier,
dockerfile,
@@ -45,10 +47,24 @@
commands.execute(docker_command_parts)
docker_image_cache = kwds['docker_image_cache']
if docker_image_cache:
- destination = os.path.join(docker_image_cache, image_identifier + ".tar")
+ destination = docker_cache_path(docker_image_cache, image_identifier)
save_image_command_parts = docker_util.build_save_image_command(
image_identifier,
destination,
**docker_host_args(**kwds)
)
commands.execute(save_image_command_parts)
+
+
+def __find_dockerfile(dockerfile, tool_directories):
+ if dockerfile is not None:
+ return dockerfile
+ search_directories = ["."]
+ if len(tool_directories) == 1:
+ tool_directory = tool_directories.pop()
+ search_directories.insert(0, tool_directory)
+ for directory in search_directories:
+ potential_dockerfile = os.path.join(directory, "Dockerfile")
+ if os.path.exists(potential_dockerfile):
+ return potential_dockerfile
+ raise Exception("Could not find dockerfile to build.")
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/47171159e9c0/
Changeset: 47171159e9c0
User: jmchilton
Date: 2014-10-07 14:23:41+00:00
Summary: Python 3 fix from planemo.
Affected #: 1 file
diff -r 9cad38925c8da6221a1ce9817d382421c6627ecd -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead lib/galaxy/util/submodules.py
--- a/lib/galaxy/util/submodules.py
+++ b/lib/galaxy/util/submodules.py
@@ -14,7 +14,7 @@
__import__(full_submodule)
submodule = getattr(module, submodule_name)
submodules.append(submodule)
- except BaseException, exception:
+ except BaseException as exception:
exception_str = str(exception)
message = "%s dynamic module could not be loaded: %s" % (full_submodule, exception_str)
log.debug(message)
https://bitbucket.org/galaxy/galaxy-central/commits/6b7782f17e84/
Changeset: 6b7782f17e84
User: jmchilton
Date: 2014-10-07 14:23:41+00:00
Summary: Bring in newer experimental components from downstream work on planemo.
This includes some utilities for working with Dockerfiles requested by Kyle Ellrott, a linting framework for Galaxy tools and a bunch of work on brew integration - most specifically a brew dependency resolver. It is obvious why the brew dependnecy resolver needs to be included in galaxy core - but I am also including the linting stuff here in case we want to reuse it in the tool shed or in the tool form. Sam's new tool form, plus the automatic tool form reloading by me and Kyle, and the tool package downloader by Dave B - is an exciting confluence of features that should really speed up tool development - adding in an GUI tool linting report would pair nicely with these features. (GUI + API work not included here - just the outline of the tool linter).
The homebrew work is tracking progress on building isolated, versioned homebrew environments here - https://github.com/jmchilton/brew-tests.
Allows deployers to add homebrew elements to config/tool_dependency_resolvers_conf.xml. Optional attributes include 'cellar' - this should be the absolute path to the homebrew Cellar to target (defaults to $HOME/.linuxbrew/Cellar under linux and to /usr/local/Cellar under that other operating system Galaxy supports).
'versionless' is another attribute supported by this tag - if set to true - it will ignore the specified package version and just resolve the latest installed homebrew version of that recipe. (If used this should always come after a resolver that respects versions.)
This should work in some superficial way for any brew installed recipe - but it is much more robust and useful for packages installed with the `brew vinstall` external command (found in https://github.com/jmchilton/brew-tests) For `install`ed packages - each dependency must be laided out as a requirement in Galaxy - so samtools 1.1 would require to second requirement tag for hstlib for instance. For `vinstall`ed packages the dependencies are recorded at install time and can be reproducibily recovered at runtime without requiring modifying the state of the Cellar or even needing brew installed at runtime on the worker (only the Cellar directory needs to be avaialable).
Affected #: 15 files
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/brew_exts.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/brew_exts.py
@@ -0,0 +1,470 @@
+#!/usr/bin/env python
+
+# % brew vinstall samtools 1.0
+# % brew vinstall samtools 0.1.19
+# % brew vinstall samtools 1.1
+# % brew env samtools 1.1
+# PATH=/home/john/.linuxbrew/Cellar/htslib/1.1/bin:/home/john/.linuxbrew/Cellar/samtools/1.1/bin:$PATH
+# export PATH
+# LD_LIBRARY_PATH=/home/john/.linuxbrew/Cellar/htslib/1.1/lib:/home/john/.linuxbrew/Cellar/samtools/1.1/lib:$LD_LIBRARY_PATH
+# export LD_LIBRARY_PATH
+# % . <(brew env samtools 1.1)
+# % which samtools
+# /home/john/.linuxbrew/Cellar/samtools/1.1/bin/samtools
+# % . <(brew env samtools 0.1.19)
+# % which samtools
+# /home/john/.linuxbrew/Cellar/samtools/0.1.19/bin/samtools
+# % brew vuninstall samtools 1.0
+# % brew vdeps samtools 1.1
+# htslib(a)1.1
+# % brew vdeps samtools 0.1.19
+
+from __future__ import print_function
+
+import argparse
+import contextlib
+import json
+import glob
+import os
+import re
+import sys
+import subprocess
+
+WHITESPACE_PATTERN = re.compile("[\s]+")
+
+DESCRIPTION = "Script built on top of linuxbrew to operate on isolated, versioned brew installed environments."
+
+if sys.platform == "darwin":
+ DEFAULT_HOMEBREW_ROOT = "/usr/local"
+else:
+ DEFAULT_HOMEBREW_ROOT = os.path.join(os.path.expanduser("~"), ".linuxbrew")
+
+NO_BREW_ERROR_MESSAGE = "Could not find brew on PATH, please place on path or pass to script with --brew argument."
+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
+
+
+class BrewContext(object):
+
+ def __init__(self, args=None):
+ ensure_brew_on_path(args)
+ raw_config = brew_execute(["config"])
+ config_lines = [l.strip().split(":", 1) for l in raw_config.split("\n") if l]
+ config = dict([(p[0].strip(), p[1].strip()) for p in config_lines])
+ # unset if "/usr/local" -> https://github.com/Homebrew/homebrew/blob/master/Library/Homebrew/cmd/confi…
+ homebrew_prefix = config.get("HOMEBREW_PREFIX", "/usr/local")
+ homebrew_cellar = config.get("HOMEBREW_CELLAR", os.path.join(homebrew_prefix, "Cellar"))
+ self.homebrew_prefix = homebrew_prefix
+ self.homebrew_cellar = homebrew_cellar
+
+
+class RecipeContext(object):
+
+ @staticmethod
+ def from_args(args, brew_context=None):
+ return RecipeContext(args.recipe, args.version, brew_context)
+
+ def __init__(self, recipe, version, brew_context=None):
+ self.recipe = recipe
+ self.version = version
+ self.brew_context = brew_context or BrewContext()
+
+ @property
+ def cellar_path(self):
+ return recipe_cellar_path(self.brew_context.homebrew_cellar, self.recipe, self.version)
+
+ @property
+ def tap_path(self):
+ return os.path.join(self.brew_context.homebrew_prefix, "Library", "Taps", self.__tap_path(self.recipe))
+
+ def __tap_path(self, recipe):
+ parts = recipe.split("/")
+ if len(parts) == 1:
+ info = brew_info(self.recipe)
+ from_url = info["from_url"]
+ if not from_url:
+ raise Exception(CANNOT_DETERMINE_TAP_ERROR_MESSAGE)
+ from_url_parts = from_url.split("/")
+ blob_index = from_url_parts.index("blob") # comes right after username and repository
+ if blob_index < 2:
+ raise Exception(CANNOT_DETERMINE_TAP_ERROR_MESSAGE)
+ username = from_url_parts[blob_index - 2]
+ repository = from_url_parts[blob_index - 1]
+ else:
+ assert len(parts) == 3
+ parts = recipe.split("/")
+ username = parts[0]
+ repository = "homebrew-%s" % parts[1]
+
+ path = os.path.join(username, repository)
+ return path
+
+
+def main():
+ global VERBOSE
+ global RELAXED
+ parser = argparse.ArgumentParser(description=DESCRIPTION)
+ parser.add_argument("--brew", help="Path to linuxbrew 'brew' executable to target")
+ actions = ["vinstall", "vuninstall", "vdeps", "vinfo", "env"]
+ action = __action(sys)
+ if not action:
+ parser.add_argument('action', metavar='action', help="Versioned action to perform.", choices=actions)
+ parser.add_argument('recipe', metavar='recipe', help="Recipe for action - should be absolute (e.g. homebrew/science/samtools).")
+ 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")
+ args = parser.parse_args()
+ if args.verbose:
+ VERBOSE = True
+ if args.relaxed:
+ RELAXED = True
+ if not action:
+ action = args.action
+ brew_context = BrewContext(args)
+ recipe_context = RecipeContext.from_args(args, brew_context)
+ if action == "vinstall":
+ versioned_install(recipe_context, args.recipe, args.version)
+ elif action == "vuninstall":
+ brew_execute(["switch", args.recipe, args.version])
+ brew_execute(["uninstall", args.recipe])
+ elif action == "vdeps":
+ print_versioned_deps(recipe_context, args.recipe, args.version)
+ elif action == "env":
+ env_statements = build_env_statements_from_recipe_context(recipe_context)
+ print(env_statements)
+ elif action == "vinfo":
+ with brew_head_at_version(recipe_context, args.recipe, args.version):
+ print(brew_info(args.recipe))
+ else:
+ raise NotImplementedError()
+
+
+class CommandLineException(Exception):
+
+ def __init__(self, command, stdout, stderr):
+ self.command = command
+ self.stdout = stdout
+ self.stderr = stderr
+ self.message = ("Failed to execute command-line %s, stderr was:\n"
+ "-------->>begin stderr<<--------\n"
+ "%s\n"
+ "-------->>end stderr<<--------\n"
+ "-------->>begin stdout<<--------\n"
+ "%s\n"
+ "-------->>end stdout<<--------\n"
+ ) % (command, stderr, stdout)
+
+ def __str__(self):
+ return self.message
+
+
+def versioned_install(recipe_context, package=None, version=None):
+ if package is None:
+ package = recipe_context.recipe
+ version = recipe_context.version
+
+ attempt_unlink(package)
+ with brew_head_at_version(recipe_context, package, version):
+ deps = brew_deps(package)
+ deps_metadata = []
+ dep_to_version = {}
+ for dep in deps:
+ version_info = brew_versions_info(dep, recipe_context.tap_path)[0]
+ dep_version = version_info[0]
+ dep_to_version[dep] = dep_version
+ versioned = version_info[2]
+ if versioned:
+ dep_to_version[dep] = dep_version
+ versioned_install(recipe_context, dep, dep_version)
+ else:
+ # Install latest.
+ dep_to_version[dep] = None
+ unversioned_install(dep)
+ try:
+ for dep in deps:
+ dep_version = dep_to_version[dep]
+ if dep_version:
+ brew_execute(["switch", dep, dep_version])
+ else:
+ brew_execute(["link", dep])
+ # dep_version obtained from brew versions doesn't
+ # include revision. This linked_keg attribute does.
+ keg_verion = brew_info(dep)["linked_keg"]
+ dep_metadata = {
+ 'name': dep,
+ 'version': keg_verion,
+ 'versioned': versioned
+ }
+ deps_metadata.append(dep_metadata)
+
+ brew_execute(["install", package])
+ deps = brew_execute(["deps", package])
+ deps = [d.strip() for d in deps.split("\n") if d]
+ metadata = {
+ 'deps': deps_metadata
+ }
+ cellar_root = recipe_context.brew_context.homebrew_cellar
+ cellar_path = recipe_cellar_path( cellar_root, package, version )
+ v_metadata_path = os.path.join(cellar_path, "INSTALL_RECEIPT_VERSIONED.json")
+ with open(v_metadata_path, "w") as f:
+ json.dump(metadata, f)
+
+ finally:
+ attempt_unlink_all(package, deps)
+
+
+def commit_for_version(recipe_context, package, version):
+ tap_path = recipe_context.tap_path
+ commit = None
+ with brew_head_at_commit("master", tap_path):
+ version_to_commit = brew_versions_info(package, tap_path)
+ if version is None:
+ version = version_to_commit[0][0]
+ commit = version_to_commit[0][1]
+ else:
+ for mapping in version_to_commit:
+ if mapping[0] == version:
+ commit = mapping[1]
+ if commit is None:
+ raise Exception("Failed to find commit for version %s" % version)
+ return commit
+
+
+def print_versioned_deps(recipe_context, recipe, version):
+ deps = load_versioned_deps(recipe_context.cellar_path)
+ for dep in deps:
+ val = dep['name']
+ if dep['versioned']:
+ val += "@%s" % dep['version']
+ print(val)
+
+
+def load_versioned_deps(cellar_path, relaxed=None):
+ if relaxed is None:
+ relaxed = RELAXED
+ v_metadata_path = os.path.join(cellar_path, "INSTALL_RECEIPT_VERSIONED.json")
+ if not os.path.isfile(v_metadata_path):
+ if RELAXED:
+ return []
+ else:
+ raise IOError("Could not locate versioned receipt file: {}".format(v_metadata_path))
+ with open(v_metadata_path, "r") as f:
+ metadata = json.load(f)
+ return metadata['deps']
+
+
+def unversioned_install(package):
+ try:
+ deps = brew_deps(package)
+ for dep in deps:
+ brew_execute(["link", dep])
+ brew_execute(["install", package])
+ finally:
+ attempt_unlink_all(package, deps)
+
+
+def attempt_unlink_all(package, deps):
+ for dep in deps:
+ attempt_unlink(dep)
+ attempt_unlink(package)
+
+
+def attempt_unlink(package):
+ try:
+ brew_execute(["unlink", package])
+ except Exception:
+ # TODO: warn
+ pass
+
+
+def brew_execute(args):
+ os.environ["HOMEBREW_NO_EMOJI"] = "1" # simplify brew parsing.
+ cmds = ["brew"] + args
+ return execute(cmds)
+
+
+def build_env_statements_from_recipe_context(recipe_context, **kwds):
+ cellar_root = recipe_context.brew_context.homebrew_cellar
+ env_statements = build_env_statements(cellar_root, recipe_context.cellar_path, **kwds)
+ return env_statements
+
+
+def build_env_statements(cellar_root, cellar_path, relaxed=None):
+ deps = load_versioned_deps(cellar_path, relaxed=relaxed)
+
+ path_appends = []
+ ld_path_appends = []
+
+ def handle_keg(cellar_path):
+ bin_path = os.path.join(cellar_path, "bin")
+ if os.path.isdir(bin_path):
+ path_appends.append(bin_path)
+ lib_path = os.path.join(cellar_path, "lib")
+ if os.path.isdir(lib_path):
+ ld_path_appends.append(lib_path)
+
+ for dep in deps:
+ package = dep['name']
+ version = dep['version']
+ dep_cellar_path = recipe_cellar_path( cellar_root, package, version )
+ 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)
+
+
+(a)contextlib.contextmanager
+def brew_head_at_version(recipe_context, package, version):
+ commit = commit_for_version(recipe_context, package, version)
+ tap_path = recipe_context.tap_path
+ with brew_head_at_commit(commit, tap_path):
+ yield
+
+
+(a)contextlib.contextmanager
+def brew_head_at_commit(commit, tap_path):
+ try:
+ os.chdir(tap_path)
+ current_commit = git_execute(["rev-parse", "HEAD"]).strip()
+ try:
+ git_execute(["checkout", commit])
+ yield
+ finally:
+ git_execute(["checkout", current_commit])
+ finally:
+ # TODO: restore chdir - or better yet just don't chdir
+ # shouldn't be needed.
+ pass
+
+
+def git_execute(args):
+ cmds = ["git"] + args
+ return execute(cmds)
+
+
+def execute(cmds):
+ p = subprocess.Popen(cmds, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+ #log = p.stdout.read()
+ global VERBOSE
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise CommandLineException(" ".join(cmds), stdout, stderr)
+ if VERBOSE:
+ print(stdout)
+ return stdout
+
+
+def brew_deps(package):
+ stdout = brew_execute(["deps", package])
+ return [p.strip() for p in stdout.split("\n") if p]
+
+
+def brew_info(recipe):
+ info_json = brew_execute(["info", "--json=v1", recipe])
+ info = json.loads(info_json)[0]
+ info.update(extended_brew_info(recipe))
+ return info
+
+
+def extended_brew_info(recipe):
+ # Extract more info from non-json variant. JSON variant should
+ # include this in a backward compatible way (TODO: Open PR).
+ raw_info = brew_execute(["info", recipe])
+ extra_info = dict(
+ from_url=None,
+ build_dependencies=[],
+ required_dependencies=[],
+ recommended_dependencies=[],
+ optional_dependencies=[],
+ )
+
+ for line in raw_info.split("\n"):
+ if line.startswith("From: "):
+ extra_info["from_url"] = line[len("From: "):].strip()
+ for dep_type in ["Build", "Required", "Recommended", "Optional"]:
+ if line.startswith("%s: " % dep_type):
+ key = "%s_dependencies" % dep_type.lower()
+ raw_val = line[len("%s: " % dep_type):]
+ extra_info[key].extend(raw_val.split(", "))
+ return extra_info
+
+
+def brew_versions_info(package, tap_path):
+
+ def versioned(recipe_path):
+ if not os.path.isabs(recipe_path):
+ recipe_path = os.path.join(os.getcwd(), recipe_path)
+ # Dependencies in the same repository should be versioned,
+ # core dependencies (presumably in base homebrew) are not
+ # versioned.
+ return tap_path in recipe_path
+
+ # TODO: Also use tags.
+ stdout = brew_execute(["versions", package])
+ version_parts = [l for l in stdout.split("\n") if l and "git checkout" in l]
+ version_parts = map(lambda l: WHITESPACE_PATTERN.split(l), version_parts)
+ info = [(p[0], p[3], versioned(p[4])) for p in version_parts]
+ return info
+
+
+def __action(sys):
+ script_name = os.path.basename(sys.argv[0])
+ if script_name.startswith("brew-"):
+ return script_name[len("brew-"):]
+ else:
+ return None
+
+
+def recipe_cellar_path(cellar_path, recipe, version):
+ recipe_base = recipe.split("/")[-1]
+ recipe_base_path = os.path.join(cellar_path, recipe_base, version)
+ revision_paths = glob.glob(recipe_base_path + "_*")
+ if revision_paths:
+ revisions = map(lambda x: int(x.rsplit("_", 1)[-1]), revision_paths)
+ max_revision = max(revisions)
+ recipe_path = "%s_%d" % (recipe_base_path, max_revision)
+ else:
+ recipe_path = recipe_base_path
+ return recipe_path
+
+
+def ensure_brew_on_path(args):
+ brew_on_path = which("brew")
+ if brew_on_path:
+ brew_on_path = os.path.abspath(brew_on_path)
+
+ def ensure_on_path(brew):
+ if brew != brew_on_path:
+ os.environ["PATH"] = "%s:%s" % (os.path.dirname(brew), os.environ["PATH"])
+
+ default_brew_path = os.path.join(DEFAULT_HOMEBREW_ROOT, "bin", "brew")
+ if args and args.brew:
+ user_brew_path = os.path.abspath(args.brew)
+ ensure_on_path(user_brew_path)
+ elif brew_on_path:
+ return brew_on_path
+ elif os.path.exists(default_brew_path):
+ ensure_on_path(default_brew_path)
+ else:
+ raise Exception(NO_BREW_ERROR_MESSAGE)
+
+
+def which(file):
+ # http://stackoverflow.com/questions/5226958/which-equivalent-function-in-pyt…
+ for path in os.environ["PATH"].split(":"):
+ if os.path.exists(path + "/" + file):
+ return path + "/" + file
+
+ return None
+
+
+if __name__ == "__main__":
+ main()
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/brew_util.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/brew_util.py
@@ -0,0 +1,40 @@
+""" brew_exts defines generic extensions to Homebrew this file
+builds on those abstraction and provides Galaxy specific functionality
+not useful to the brew external commands.
+"""
+from ..deps import brew_exts
+
+DEFAULT_TAP = "homebrew/science"
+
+
+class HomebrewRecipe(object):
+
+ def __init__(self, recipe, version, tap):
+ self.recipe = recipe
+ self.version = version
+ self.tap = tap
+
+
+def requirements_to_recipes(requirements):
+ return filter(None, map(requirement_to_recipe, requirements))
+
+
+def requirement_to_recipe(requirement):
+ if requirement.type != "package":
+ return None
+ # TOOD: Allow requirements to annotate optionalbrew specific
+ # adaptions.
+ recipe_name = requirement.name
+ recipe_version = requirement.version
+ return HomebrewRecipe(recipe_name, recipe_version, tap=DEFAULT_TAP)
+
+
+def requirements_to_recipe_contexts(requirements, brew_context):
+ def to_recipe_context(homebrew_recipe):
+ return brew_exts.RecipeContext(
+ homebrew_recipe.recipe,
+ homebrew_recipe.version,
+ brew_context
+ )
+ return map(to_recipe_context, requirements_to_recipes(requirements))
+
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/commands.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/commands.py
@@ -0,0 +1,54 @@
+import os
+import subprocess
+
+
+def shell(cmds, env=None):
+ popen_kwds = dict(
+ shell=True,
+ )
+ if env:
+ new_env = os.environ.copy()
+ new_env.update(env)
+ popen_kwds["env"] = new_env
+ p = subprocess.Popen(cmds, **popen_kwds)
+ return p.wait()
+
+
+def execute(cmds):
+ return __wait(cmds, shell=False)
+
+
+def which(file):
+ # http://stackoverflow.com/questions/5226958/which-equivalent-function-in-pyt…
+ for path in os.environ["PATH"].split(":"):
+ if os.path.exists(path + "/" + file):
+ return path + "/" + file
+
+ return None
+
+
+def __wait(cmds, **popen_kwds):
+ p = subprocess.Popen(cmds, **popen_kwds)
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ raise CommandLineException(" ".join(cmds), stdout, stderr)
+ return stdout
+
+
+class CommandLineException(Exception):
+
+ def __init__(self, command, stdout, stderr):
+ self.command = command
+ self.stdout = stdout
+ self.stderr = stderr
+ self.message = ("Failed to execute command-line %s, stderr was:\n"
+ "-------->>begin stderr<<--------\n"
+ "%s\n"
+ "-------->>end stderr<<--------\n"
+ "-------->>begin stdout<<--------\n"
+ "%s\n"
+ "-------->>end stdout<<--------\n"
+ ) % (command, stderr, stdout)
+
+ def __str__(self):
+ return self.message
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -1,3 +1,4 @@
+import os
DEFAULT_DOCKER_COMMAND = "docker"
DEFAULT_SUDO = True
@@ -51,6 +52,34 @@
return ":".join([self.from_path, self.to_path, self.how])
+def build_command(
+ image,
+ docker_build_path,
+ docker_cmd=DEFAULT_DOCKER_COMMAND,
+ sudo=DEFAULT_SUDO,
+ sudo_cmd=DEFAULT_SUDO_COMMAND,
+ host=DEFAULT_HOST,
+):
+ if os.path.isfile(docker_build_path):
+ docker_build_path = os.path.dirname(os.path.abspath(docker_build_path))
+ build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts.extend(["build", "-t", image, docker_build_path])
+ return build_command_parts
+
+
+def build_save_image_command(
+ image,
+ destination,
+ docker_cmd=DEFAULT_DOCKER_COMMAND,
+ sudo=DEFAULT_SUDO,
+ sudo_cmd=DEFAULT_SUDO_COMMAND,
+ host=DEFAULT_HOST,
+):
+ build_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
+ build_command_parts.extend(["save", "-o", destination, image])
+ return build_command_parts
+
+
def build_docker_cache_command(
image,
docker_cmd=DEFAULT_DOCKER_COMMAND,
@@ -72,6 +101,7 @@
def build_docker_run_command(
container_command,
image,
+ interactive=False,
tag=None,
volumes=[],
volumes_from=DEFAULT_VOLUMES_FROM,
@@ -88,6 +118,8 @@
):
command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
command_parts.append("run")
+ if interactive:
+ command_parts.append("-i")
for env_directive in env_directives:
command_parts.extend(["-e", env_directive])
for volume in volumes:
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/dockerfiles.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/dockerfiles.py
@@ -0,0 +1,54 @@
+import os
+
+from ..deps import commands
+from ..deps import docker_util
+from ..deps.requirements import parse_requirements_from_xml
+from ...tools import loader_directory
+
+import logging
+log = logging.getLogger(__name__)
+
+
+def docker_host_args(**kwds):
+ return dict(
+ docker_cmd=kwds["docker_cmd"],
+ sudo=kwds["docker_sudo"],
+ sudo_cmd=kwds["docker_sudo_cmd"],
+ host=kwds["docker_host"]
+ )
+
+
+def dockerfile_build(path, dockerfile=None, error=log.error, **kwds):
+ expected_container_names = set()
+ for (tool_path, tool_xml) in loader_directory.load_tool_elements_from_path(path):
+ requirements, containers = parse_requirements_from_xml(tool_xml)
+ for container in containers:
+ if container.type == "docker":
+ expected_container_names.add(container.identifier)
+ break
+
+ if len(expected_container_names) == 0:
+ error("Could not find any docker identifiers to generate.")
+
+ if len(expected_container_names) > 1:
+ error("Multiple different docker identifiers found for selected tools [%s]", expected_container_names)
+
+ image_identifier = expected_container_names.pop()
+ if dockerfile is None:
+ dockerfile = "Dockerfile"
+
+ docker_command_parts = docker_util.build_command(
+ image_identifier,
+ dockerfile,
+ **docker_host_args(**kwds)
+ )
+ commands.execute(docker_command_parts)
+ docker_image_cache = kwds['docker_image_cache']
+ if docker_image_cache:
+ destination = os.path.join(docker_image_cache, image_identifier + ".tar")
+ save_image_command_parts = docker_util.build_save_image_command(
+ image_identifier,
+ destination,
+ **docker_host_args(**kwds)
+ )
+ commands.execute(save_image_command_parts)
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/deps/resolvers/homebrew.py
--- /dev/null
+++ b/lib/galaxy/tools/deps/resolvers/homebrew.py
@@ -0,0 +1,96 @@
+"""
+This file implements a brew resolver for Galaxy requirements. In order for Galaxy
+to pick up on recursively defined and versioned brew dependencies recipes should
+be installed using the experimental `brew-vinstall` external command.
+
+More information here:
+
+https://github.com/jmchilton/brew-tests
+https://github.com/Homebrew/homebrew-science/issues/1191
+
+This is still an experimental module and there will almost certainly be backward
+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
+
+# 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 = UNKNOWN_PREFER_VERSION_MESSAGE_TEMPLATE % (PREFER_VERSION_LATEST)
+DEFAULT_PREFER_VERSION = PREFER_VERSION_LATEST
+
+
+class HomebrewDependencyResolver(DependencyResolver):
+ resolver_type = "homebrew"
+
+ def __init__(self, dependency_manager, **kwds):
+ self.versionless = _string_as_bool(kwds.get('versionless', 'false'))
+ self.prefer_version = kwds.get('prefer_version', None)
+
+ if self.prefer_version is None:
+ self.prefer_version = DEFAULT_PREFER_VERSION
+
+ 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
+
+ def resolve(self, name, version, type, **kwds):
+ if type != "package":
+ return INDETERMINATE_DEPENDENCY
+
+ if version is None or self.versionless:
+ return self._find_dep_default(name, version)
+ 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"
+
+
+__all__ = [HomebrewDependencyResolver]
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/lint.py
--- /dev/null
+++ b/lib/galaxy/tools/lint.py
@@ -0,0 +1,89 @@
+from __future__ import print_function
+import inspect
+from galaxy.util import submodules
+
+LEVEL_ALL = "all"
+LEVEL_WARN = "warn"
+LEVEL_ERROR = "error"
+
+
+def lint_xml(tool_xml, level=LEVEL_ALL, fail_level=LEVEL_WARN):
+ import galaxy.tools.linters
+ lint_context = LintContext(level=level)
+ linter_modules = submodules.submodules(galaxy.tools.linters)
+ for module in linter_modules:
+ for (name, value) in inspect.getmembers(module):
+ if callable(value) and name.startswith("lint_"):
+ lint_context.lint(module, name, value, tool_xml)
+ found_warns = lint_context.found_warns
+ found_errors = lint_context.found_errors
+ if level == LEVEL_WARN and (found_warns or found_errors):
+ return False
+ else:
+ return found_errors
+
+
+class LintContext(object):
+
+ def __init__(self, level):
+ self.level = level
+ self.found_errors = False
+ self.found_warns = False
+
+ def lint(self, module, name, lint_func, tool_xml):
+ self.printed_linter_info = False
+ self.valid_messages = []
+ self.info_messages = []
+ self.warn_messages = []
+ self.error_messages = []
+ lint_func(tool_xml, self)
+ # TODO: colorful emoji if in click CLI.
+ if self.error_messages:
+ status = "FAIL"
+ elif self.warn_messages:
+
+ status = "WARNING"
+ else:
+ status = "CHECK"
+
+ def print_linter_info():
+ if self.printed_linter_info:
+ return
+ self.printed_linter_info = True
+ print("Applying linter %s... %s" % (name, status))
+
+ for message in self.error_messages:
+ self.found_errors = True
+ print_linter_info()
+ print(".. ERROR: %s" % message)
+
+ if self.level != LEVEL_ERROR:
+ for message in self.warn_messages:
+ self.found_warns = True
+ print_linter_info()
+ print(".. WARNING: %s" % message)
+
+ if self.level == LEVEL_ALL:
+ for message in self.info_messages:
+ print_linter_info()
+ print(".. INFO: %s" % message)
+ for message in self.valid_messages:
+ print_linter_info()
+ print(".. CHECK: %s" % message)
+
+ def __handle_message(self, message_list, message, *args):
+ if args:
+ message = message % args
+ message_list.append(message)
+
+ def valid(self, message, *args):
+ self.__handle_message(self.valid_messages, message, *args)
+
+ def info(self, message, *args):
+ self.__handle_message(self.info_messages, message, *args)
+
+ def error(self, message, *args):
+ self.__handle_message(self.error_messages, message, *args)
+
+ def warn(self, message, *args):
+ self.__handle_message(self.warn_messages, message, *args)
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/__init__.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/__init__.py
@@ -0,0 +1,2 @@
+""" Framework for linting tools.
+"""
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/citations.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/citations.py
@@ -0,0 +1,27 @@
+
+
+def lint_citations(tool_xml, lint_ctx):
+ root = tool_xml.getroot()
+ citations = root.findall("citations")
+ if len(citations) > 1:
+ lint_ctx.error("More than one citation section found, behavior undefined.")
+ return
+
+ if len(citations) == 0:
+ lint_ctx.warn("No citations found, consider adding citations to your tool.")
+ return
+
+ valid_citations = 0
+ for citation in citations[0]:
+ if citation.tag != "citation":
+ lint_ctx.warn("Unknown tag discovered in citations block [%s], will be ignored." % citation.tag)
+ if "type" in citation.attrib:
+ citation_type = citation.attrib.get("type")
+ if citation_type not in ["doi", "bibtex"]:
+ lint_ctx.warn("Unknown citation type discovered [%s], will be ignored.", citation_type)
+ else:
+ valid_citations += 1
+
+ if valid_citations > 0:
+ lint_ctx.valid("Found %d likely valid citations.", valid_citations)
+
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/help.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/help.py
@@ -0,0 +1,15 @@
+
+
+def lint_help(tool_xml, lint_ctx):
+ root = tool_xml.getroot()
+ helps = root.findall("help")
+ if len(helps) > 1:
+ lint_ctx.error("More than one help section found, behavior undefined.")
+ return
+
+ if len(helps) == 0:
+ lint_ctx.warn("No help section found, consider adding a help section to your tool.")
+ return
+
+ # TODO: validate help section RST.
+ lint_ctx.valid("Tool contains help section.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/inputs.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/inputs.py
@@ -0,0 +1,38 @@
+
+
+def lint_inputs(tool_xml, lint_ctx):
+ inputs = tool_xml.findall("./inputs//param")
+ num_inputs = 0
+ for param in inputs:
+ num_inputs += 1
+ param_attrib = param.attrib
+ has_errors = False
+ if "type" not in param_attrib:
+ lint_ctx.error("Found param input with type specified.")
+ has_errors = True
+ if "name" not in param_attrib:
+ lint_ctx.error("Found param input with not name specified.")
+ has_errors = True
+
+ if has_errors:
+ continue
+
+ param_type = param_attrib["type"]
+ param_name = param_attrib["name"]
+ if param_type == "data_input":
+ if "format" not in param_attrib:
+ lint_ctx.warn("Found param input %s contains no format specified - 'data' format will be assumed.", param_name)
+ # TODO: Validate type, much more...
+ if num_inputs:
+ lint_ctx.info("Found %d input parameters.", num_inputs)
+ else:
+ lint_ctx.warn("Found not input parameters.")
+
+
+def lint_repeats(tool_xml, lint_ctx):
+ repeats = tool_xml.findall("./inputs//repeat")
+ for repeat in repeats:
+ if "name" not in repeat.attrib:
+ lint_ctx.error("Repeat does not specify name attribute.")
+ if "title" not in repeat.attrib:
+ lint_ctx.error("Repeat does not specify title attribute.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/outputs.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/outputs.py
@@ -0,0 +1,25 @@
+
+
+def lint_output(tool_xml, lint_ctx):
+ outputs = tool_xml.findall("./outputs/data")
+ if not outputs:
+ lint_ctx.warn("Tool contains no outputs, most tools should produce outputs..")
+ return
+
+ num_outputs = 0
+ for output in outputs:
+ num_outputs += 1
+ output_attrib = output.attrib
+ format_set = False
+ if "format" in output_attrib:
+ format_set = True
+ format = output_attrib["format"]
+ if format == "input":
+ lint_ctx.warn("Using format='input' on output data, format_source attribute is less ambigious and should be used instead.")
+ elif "format_source" in output_attrib:
+ format_set = True
+
+ if not format_set:
+ lint_ctx.warn("Tool data output doesn't define an output format.")
+
+ lint_ctx.info("%d output datasets found.", num_outputs)
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/tests.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/tests.py
@@ -0,0 +1,20 @@
+
+
+# Misspelled so as not be picked up by nosetests.
+def lint_tsts(tool_xml, lint_ctx):
+ tests = tool_xml.findall("./tests/test")
+ if not tests:
+ lint_ctx.warn("No tests found, most tools should define test cases.")
+
+ num_valid_tests = 0
+ for test in tests:
+ outputs = test.findall("output")
+ if not outputs:
+ lint_ctx.warn("No outputs defined for tests, this test is likely invalid.")
+ else:
+ num_valid_tests += 1
+
+ if num_valid_tests:
+ lint_ctx.valid("%d test(s) found.", num_valid_tests)
+ else:
+ lint_ctx.warn("No valid test(s) found.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/linters/top_level.py
--- /dev/null
+++ b/lib/galaxy/tools/linters/top_level.py
@@ -0,0 +1,17 @@
+
+def lint_top_level(tree, lint_ctx):
+ root = tree.getroot()
+ if "version" not in root.attrib:
+ lint_ctx.error("Tool does not define a version attribute.")
+ else:
+ lint_ctx.valid("Tool defines a version.")
+
+ if "name" not in root.attrib:
+ lint_ctx.error("Tool does not define a name attribute.")
+ else:
+ lint_ctx.valid("Tool defines a name.")
+
+ if "id" not in root.attrib:
+ lint_ctx.error("Tool does not define an id attribute.")
+ else:
+ lint_ctx.valid("Tool defines an id name.")
diff -r 47171159e9c05fba08a6ed5e6f2883c3ef8e1ead -r 6b7782f17e84b357c968c7e8e14d1f50c3668008 lib/galaxy/tools/loader_directory.py
--- /dev/null
+++ b/lib/galaxy/tools/loader_directory.py
@@ -0,0 +1,31 @@
+import glob
+import os
+from ..tools import loader
+
+PATH_DOES_NOT_EXIST_ERROR = "Could not load tools from path [%s] - this path does not exist."
+
+
+def load_tool_elements_from_path(path):
+ tool_elements = []
+ for file in __find_tool_files(path):
+ if __looks_like_a_tool(file):
+ tool_elements.append((file, loader.load_tool(file)))
+ return tool_elements
+
+
+def __looks_like_a_tool(path):
+ with open(path) as f:
+ for i in range(10):
+ line = f.next()
+ if "<tool" in line:
+ return True
+ return False
+
+
+def __find_tool_files(path):
+ if not os.path.exists(path):
+ raise Exception(PATH_DOES_NOT_EXIST_ERROR)
+ if not os.path.isdir(path):
+ return [os.path.abspath(path)]
+ else:
+ return map(os.path.abspath, glob.glob(path + "/**.xml"))
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: Update master API key handling in tests for d7dd1f9.
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9cad38925c8d/
Changeset: 9cad38925c8d
User: jmchilton
Date: 2014-10-07 01:25:30+00:00
Summary: Update master API key handling in tests for d7dd1f9.
Now aware of anyone actually overriding this with GALAXY_TEST_MASTER_API_KEY so not maintaining backward compatibility with respect to that environment variable.
Affected #: 1 file
diff -r d7dd1f92d5b8e35ed9530fc5f0494e160ff8c4da -r 9cad38925c8da6221a1ce9817d382421c6627ecd test/base/api_util.py
--- a/test/base/api_util.py
+++ b/test/base/api_util.py
@@ -9,7 +9,11 @@
configured as a master API key and should be able to create additional
users and keys.
"""
- return os.environ.get( "GALAXY_TEST_MASTER_API_KEY", DEFAULT_GALAXY_MASTER_API_KEY )
+ for key in ["GALAXY_CONFIG_MASTER_API_KEY", "GALAXY_CONFIG_OVERRIDE_MASTER_API_KEY"]:
+ value = os.environ.get(key, None)
+ if value:
+ return value
+ return DEFAULT_GALAXY_MASTER_API_KEY
def get_user_api_key():
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: Make functional tests to respect GALAXY_CONFIG_ environment variables.
by commits-noreply@bitbucket.org 07 Oct '14
by commits-noreply@bitbucket.org 07 Oct '14
07 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d7dd1f92d5b8/
Changeset: d7dd1f92d5b8
User: jmchilton
Date: 2014-10-07 00:56:58+00:00
Summary: Make functional tests to respect GALAXY_CONFIG_ environment variables.
Functional tests don't work without the tweak to imports in cloudlaunch - not sure if that has always been a problem and I am just running the tests in a different Galaxy instance or if the earlier import of util caused the problem.
Regardless I guess we shoud update to a version of bioblend that doesn't require simplejson.
Affected #: 2 files
diff -r 594b48fe90b7b17ed22f5c597837022d8204db47 -r d7dd1f92d5b8e35ed9530fc5f0494e160ff8c4da lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
--- a/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
+++ b/lib/galaxy/webapps/galaxy/controllers/cloudlaunch.py
@@ -17,6 +17,7 @@
eggs.require('PyYAML')
eggs.require('boto')
+eggs.require('simplejson')
eggs.require('bioblend')
from boto.exception import EC2ResponseError
diff -r 594b48fe90b7b17ed22f5c597837022d8204db47 -r d7dd1f92d5b8e35ed9530fc5f0494e160ff8c4da scripts/functional_tests.py
--- a/scripts/functional_tests.py
+++ b/scripts/functional_tests.py
@@ -16,6 +16,7 @@
from base.tool_shed_util import parse_tool_panel_config
from galaxy import eggs
+from galaxy.util.properties import load_app_properties
eggs.require( "nose" )
eggs.require( "NoseHTML" )
@@ -401,6 +402,9 @@
kwargs[ 'global_conf' ] = get_webapp_global_conf()
kwargs[ 'global_conf' ][ '__file__' ] = galaxy_config_file
kwargs[ 'config_file' ] = galaxy_config_file
+ kwargs = load_app_properties(
+ kwds=kwargs
+ )
# Build the Universe Application
app = UniverseApplication( **kwargs )
database_contexts.galaxy_context = app.model.context
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: natefoo: Added tag latest_2014.10.06 for changeset 2092948937ac
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e98b33105381/
Changeset: e98b33105381
Branch: stable
User: natefoo
Date: 2014-10-06 19:31:09+00:00
Summary: Added tag latest_2014.10.06 for changeset 2092948937ac
Affected #: 1 file
diff -r 3b3cd242b4b7cd20b9c868c393c455524b31b87c -r e98b33105381ac94f590edee1859ab550d328833 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,3 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
+2092948937ac30ef82f71463a235c66d34987088 latest_2014.10.06
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
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 7899e122b8cb0ab19b0de9e565822f9d6c1bd844
https://github.com/galaxyproject/usegalaxy-playbook/commit/7899e122b8cb0ab1…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-10-06 (Mon, 06 Oct 2014)
Changed paths:
M production/group_vars/all.yml
Log Message:
-----------
Update Main.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/769e8dca49f0/
Changeset: 769e8dca49f0
Branch: next-stable
User: natefoo
Date: 2014-10-06 16:58:28+00:00
Summary: Close next-stable branch for release_2014.10.06
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/2092948937ac/
Changeset: 2092948937ac
Branch: stable
User: natefoo
Date: 2014-10-06 16:58:53+00:00
Summary: Merge next-stable to stable for release_2014.10.06
Affected #: 951 files
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 README.txt
--- a/README.txt
+++ b/README.txt
@@ -1,31 +1,34 @@
-GALAXY
-======
-http://galaxyproject.org/
-
-The latest information about Galaxy is always available via the Galaxy
-website above.
-
-HOW TO START
-============
-Galaxy requires Python 2.6 or 2.7. To check your python version, run:
-
-% python -V
-Python 2.7.3
-
-Start Galaxy:
-
-% sh run.sh
-
-Once Galaxy completes startup, you should be able to view Galaxy in your
-browser at:
-
-http://localhost:8080
-
-You may wish to make changes from the default configuration. This can be done
-in the universe_wsgi.ini file. Tools are configured in tool_conf.xml. Details
-on adding tools can be found on the Galaxy website (linked above).
-
-Not all dependencies are included for the tools provided in the sample
-tool_conf.xml. A full list of external dependencies is available at:
-
-https://wiki.galaxyproject.org/Admin/Tools/ToolDependencies
+GALAXY
+======
+http://galaxyproject.org/
+
+The latest information about Galaxy is always available via the Galaxy
+website above.
+
+HOW TO START
+============
+Galaxy requires Python 2.6 or 2.7. To check your python version, run:
+
+% python -V
+Python 2.7.3
+
+Start Galaxy:
+
+% sh run.sh
+
+Once Galaxy completes startup, you should be able to view Galaxy in your
+browser at:
+
+http://localhost:8080
+
+You may wish to make changes from the default configuration. This can be done
+in the config/galaxy.ini file. Tools can be either installed from the Tool Shed
+or added manually. For details please see the Galaxy wiki:
+
+https://wiki.galaxyproject.org/Admin/Tools/AddToolFromToolShedTutorial
+
+
+Not all dependencies are included for the tools provided in the sample
+tool_conf.xml. A full list of external dependencies is available at:
+
+https://wiki.galaxyproject.org/Admin/Tools/ToolDependencies
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 buildbot_setup.sh
--- a/buildbot_setup.sh
+++ b/buildbot_setup.sh
@@ -42,25 +42,6 @@
/galaxy/software/tool-data/gatk
"
-SAMPLES="
-tool_conf.xml.sample
-datatypes_conf.xml.sample
-universe_wsgi.ini.sample
-tool_data_table_conf.xml.sample
-tool_sheds_conf.xml.sample
-shed_tool_data_table_conf.xml.sample
-migrated_tools_conf.xml.sample
-data_manager_conf.xml.sample
-shed_data_manager_conf.xml.sample
-tool-data/shared/ensembl/builds.txt.sample
-tool-data/shared/igv/igv_build_sites.txt.sample
-tool-data/shared/ncbi/builds.txt.sample
-tool-data/shared/rviewer/rviewer_build_sites.txt.sample
-tool-data/shared/ucsc/builds.txt.sample
-tool-data/shared/ucsc/publicbuilds.txt.sample
-tool-data/shared/ucsc/ucsc_build_sites.txt.sample
-"
-
DIRS="
database
database/files
@@ -108,14 +89,11 @@
;;
esac
-for sample in $SAMPLES; do
- file=${sample%.sample}
- echo "Copying $sample to $file"
- cp $sample $file
-done
+# set up configs from samples.
+./scripts/common_startup.sh
echo "Copying job_conf.xml.sample_basic to job_conf.xml"
-cp job_conf.xml.sample_basic job_conf.xml
+cp config/job_conf.xml.sample_basic config/job_conf.xml
for dir in $DIRS; do
if [ ! -d $dir ]; then
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/GruntFile.js
--- /dev/null
+++ b/client/GruntFile.js
@@ -0,0 +1,88 @@
+module.exports = function(grunt) {
+
+ // Project configuration.
+ grunt.initConfig({
+ pkg: grunt.file.readJSON( 'package.json' ),
+
+ // default task
+ // use 'grunt copy' to copy the entire <galaxy>/client/galaxy/scripts dir into <galaxy>/static/scripts
+ copy: {
+ main: {
+ files: [
+ {
+ expand : true,
+ cwd : 'galaxy/scripts/',
+ src : '**',
+ dest : '../static/scripts'
+ }
+ ]
+ }
+ },
+
+ // use 'grunt pack' to call pack_scripts.py to pack all or selected files in static/scripts
+ exec: {
+ packScripts: {
+ cwd: '../static/scripts',
+ target: [],
+ cmd: function(){
+ var targets = grunt.config( 'exec.packScripts.target' );
+ // if nothing was passed in pack all scripts
+ if( !targets.length ){
+ return './pack_scripts.py';
+ }
+
+ grunt.log.write( 'packing: ' + targets + '\n' );
+ return targets.map( function( target ){
+ return './pack_scripts.py ' + target;
+ }).join( '; ' );
+ }
+ }
+ },
+
+ // use 'grunt watch' (from a new tab in your terminal) to have grunt re-copy changed files automatically
+ watch: {
+ // watch for changes in the src dir
+ files: [ 'galaxy/scripts/**' ],
+ tasks: [ 'copy', 'pack' ],
+ options: {
+ spawn: false
+ }
+ }
+ });
+
+ grunt.loadNpmTasks( 'grunt-contrib-watch' );
+ grunt.loadNpmTasks( 'grunt-contrib-copy');
+ grunt.loadNpmTasks('grunt-exec');
+
+ grunt.registerTask( 'pack', [ 'exec' ] );
+ grunt.registerTask( 'default', [ 'copy', 'pack' ] );
+
+ // -------------------------------------------------------------------------- copy,pack only those changed
+ // adapted from grunt-contrib-watch jslint example
+ //TODO: a bit hacky and there's prob. a better way
+ //NOTE: copy will fail silently if a file isn't found
+
+ // outer scope variable for the event handler and onChange fn - begin with empty hash
+ var changedFiles = Object.create(null);
+
+ // when files are changed, set the copy src and packScripts target to the filenames of the updated files
+ var onChange = grunt.util._.debounce(function() {
+ grunt.config( 'copy.main.files', [{
+ expand: true,
+ cwd: 'galaxy/scripts',
+ src: Object.keys( changedFiles ),
+ dest: '../static/scripts/'
+ }]);
+ grunt.config( 'exec.packScripts.target', Object.keys( changedFiles ) );
+ changedFiles = Object.create(null);
+ }, 200);
+
+ grunt.event.on('watch', function(action, filepath) {
+ // store each filepath in a Files obj, the debounced fn above will use it as an aggregate list for copying
+ // we need to take galaxy/scripts out of the filepath or it will be copied to the wrong loc
+ filepath = filepath.replace( /galaxy\/scripts\//, '' );
+ changedFiles[filepath] = action;
+ onChange();
+ });
+
+};
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/README.txt
--- /dev/null
+++ b/client/README.txt
@@ -0,0 +1,42 @@
+Client Build System
+===================
+
+Builds and moves the client-side scripts necessary for running the Galaxy webapps. There's no need to use this system
+unless you are modifying or developing client-side scripts.
+
+You'll need Node and the Node Package Manager (npm): nodejs.org.
+
+Once npm is installed, install the grunt task manager and it's command line into your global scope:
+
+ npm install -g grunt grunt-cli
+
+Next, from within this directory, install the local build dependencies:
+
+ cd client
+ npm install
+
+You're now ready to re-build the client scripts after modifying them.
+
+
+Rebuilding
+==========
+
+There are two methods for rebuilding: a complete rebuild and automatic, partial rebuilds while you develop.
+
+A complete rebuild can be done with the following (from the `client` directory):
+
+ grunt
+
+This will copy any files in `client/galaxy/scripts` to `static/scripts` and run `static/scripts/pack_scripts.py` on all.
+
+Grunt can also do an automatic, partial rebuild of any files you change *as you develop* by:
+
+ 1. opening a new terminal session
+ 2. `cd client`
+ 3. `grunt watch`
+
+This starts a new grunt watch process that will monitor the files in `client/galaxy/scripts` for changes and copy and
+pack them when they change.
+
+You can stop the `grunt watch` task by pressing `Ctrl+C`. Note: you should also be able to background that task if you
+prefer.
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/galaxy/scripts/base.js
--- /dev/null
+++ b/client/galaxy/scripts/base.js
@@ -0,0 +1,15 @@
+define( ["libs/backbone/backbone"], function( Backbone ) {
+
+ var Base = function() {
+ if( this.initialize ) {
+ this.initialize.apply(this, arguments);
+ }
+ };
+ Base.extend = Backbone.Model.extend;
+
+ return {
+ Base: Base,
+ Backbone: Backbone
+ };
+
+});
\ No newline at end of file
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/galaxy/scripts/galaxy-app-base.js
--- /dev/null
+++ b/client/galaxy/scripts/galaxy-app-base.js
@@ -0,0 +1,160 @@
+define([
+ 'mvc/user/user-model',
+ 'utils/metrics-logger',
+ 'utils/add-logging',
+ 'utils/localization',
+ 'bootstrapped-data'
+], function( userModel, metricsLogger, addLogging, localize, bootstrapped ){
+// ============================================================================
+/** Base galaxy client-side application.
+ * Iniitializes:
+ * logger : the logger/metrics-logger
+ * localize : the string localizer
+ * config : the current configuration (any k/v in
+ * galaxy.ini available from the configuration API)
+ * user : the current user (as a mvc/user/user-model)
+ */
+function GalaxyApp( options ){
+ var self = this;
+ return self._init( options || {} );
+}
+
+// add logging shortcuts for this object
+addLogging( GalaxyApp, 'GalaxyApp' );
+
+/** default options */
+GalaxyApp.prototype.defaultOptions = {
+ /** monkey patch attributes from existing window.Galaxy object? */
+ patchExisting : true,
+ /** root url of this app */
+ // move to self.root?
+ root : '/'
+};
+
+/** initalize options and sub-components */
+GalaxyApp.prototype._init = function init( options ){
+ var self = this;
+ _.extend( self, Backbone.Events );
+
+ self._processOptions( options );
+ self.debug( 'GalaxyApp.options: ', self.options );
+
+ self._patchGalaxy( window.Galaxy );
+
+ self._initLogger( options.loggerOptions || {} );
+ self.debug( 'GalaxyApp.logger: ', self.logger );
+
+ self._initLocale();
+ self.debug( 'GalaxyApp.localize: ', self.localize );
+
+ self.config = options.config || bootstrapped.config || {};
+ self.debug( 'GalaxyApp.config: ', self.config );
+
+ self._initUser( options.user || bootstrapped.user || {} );
+ self.debug( 'GalaxyApp.user: ', self.user );
+
+ //TODO: temp
+ self.trigger( 'ready', self );
+ //if( typeof options.onload === 'function' ){
+ // options.onload();
+ //}
+
+ self._setUpListeners();
+
+ return self;
+};
+
+/** add an option from options if the key matches an option in defaultOptions */
+GalaxyApp.prototype._processOptions = function _processOptions( options ){
+ var self = this,
+ defaults = self.defaultOptions;
+ self.debug( '_processOptions: ', options );
+
+ self.options = {};
+ for( var k in defaults ){
+ if( defaults.hasOwnProperty( k ) ){
+ self.options[ k ] = ( options.hasOwnProperty( k ) )?( options[ k ] ):( defaults[ k ] );
+ }
+ }
+ return self;
+};
+
+/** add an option from options if the key matches an option in defaultOptions */
+GalaxyApp.prototype._patchGalaxy = function _processOptions( patchWith ){
+ var self = this;
+ // in case req or plain script tag order has created a prev. version of the Galaxy obj...
+ if( self.options.patchExisting && patchWith ){
+ self.debug( 'found existing Galaxy object:', patchWith );
+ // ...(for now) monkey patch any added attributes that the previous Galaxy may have had
+ //TODO: move those attributes to more formal assignment in GalaxyApp
+ for( var k in patchWith ){
+ if( patchWith.hasOwnProperty( k ) ){
+ self.debug( '\t patching in ' + k + ' to Galaxy' );
+ self[ k ] = patchWith[ k ];
+ }
+ }
+ }
+};
+
+/** set up the metrics logger (utils/metrics-logger) and pass loggerOptions */
+GalaxyApp.prototype._initLogger = function _initLogger( loggerOptions ){
+ var self = this;
+ self.debug( '_initLogger:', loggerOptions );
+ self.logger = new metricsLogger.MetricsLogger( loggerOptions );
+ return self;
+};
+
+/** add the localize fn to this object and the window namespace (as '_l') */
+GalaxyApp.prototype._initLocale = function _initLocale( options ){
+ var self = this;
+ self.debug( '_initLocale:', options );
+ self.localize = localize;
+ // add to window as global shortened alias
+ window._l = self.localize;
+ return self;
+};
+
+/** set up the current user as a Backbone model (mvc/user/user-model) */
+GalaxyApp.prototype._initUser = function _initUser( userJSON ){
+ var self = this;
+ self.debug( '_initUser:', userJSON );
+ self.user = new userModel.User( userJSON );
+ //TODO: temp - old alias
+ self.currUser = self.user;
+ return self;
+};
+
+/** Set up DOM/jQuery/Backbone event listeners enabled for all pages */
+GalaxyApp.prototype._setUpListeners = function _setUpListeners(){
+ var self = this;
+
+ // hook to jq beforeSend to record the most recent ajax call and cache some data about it
+ /** cached info about the last ajax call made through jQuery */
+ self.lastAjax = {};
+ $( document ).bind( 'ajaxSend', function( ev, xhr, options ){
+ var data = options.data;
+ try {
+ data = JSON.parse( data );
+ } catch( err ){}
+
+ self.lastAjax = {
+ url : location.href.slice( 0, -1 ) + options.url,
+ data : data
+ };
+ //TODO:?? we might somehow manage to *retry* ajax using either this hook or Backbone.sync
+ });
+
+};
+
+/** string rep */
+GalaxyApp.prototype.toString = function toString(){
+ var userEmail = this.user.get( 'email' ) || '(anonymous)';
+ return 'GalaxyApp(' + userEmail + ')';
+};
+
+
+// ============================================================================
+ return {
+ GalaxyApp : GalaxyApp
+ };
+});
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/galaxy/scripts/galaxy.autocom_tagging.js
--- /dev/null
+++ b/client/galaxy/scripts/galaxy.autocom_tagging.js
@@ -0,0 +1,368 @@
+/**
+* JQuery extension for tagging with autocomplete.
+* @author: Jeremy Goecks
+* @require: jquery.autocomplete plugin
+*/
+//
+// Initialize "tag click functions" for tags.
+//
+function init_tag_click_function(tag_elt, click_func) {
+ $(tag_elt).find('.tag-name').each( function() {
+ $(this).click( function() {
+ var tag_str = $(this).text();
+ var tag_name_and_value = tag_str.split(":");
+ click_func(tag_name_and_value[0], tag_name_and_value[1]);
+ return true;
+ });
+ });
+}
+
+jQuery.fn.autocomplete_tagging = function(options) {
+
+ var defaults = {
+ get_toggle_link_text_fn: function(tags) {
+ var text = "";
+ var num_tags = obj_length(tags);
+ if (num_tags > 0) {
+ text = num_tags + (num_tags > 1 ? " Tags" : " Tag");
+ } else {
+ text = "Add tags";
+ }
+ return text;
+ },
+ tag_click_fn : function (name, value) {},
+ editable: true,
+ input_size: 20,
+ in_form: false,
+ tags : {},
+ use_toggle_link: true,
+ item_id: "",
+ add_tag_img: "",
+ add_tag_img_rollover: "",
+ delete_tag_img: "",
+ ajax_autocomplete_tag_url: "",
+ ajax_retag_url: "",
+ ajax_delete_tag_url: "",
+ ajax_add_tag_url: ""
+ };
+
+ var settings = jQuery.extend(defaults, options);
+
+ //
+ // Initalize object's elements.
+ //
+
+ // Get elements for this object. For this_obj, assume the last element with the id is the "this"; this is somewhat of a hack to address the problem
+ // that there may be two tagging elements for a single item if there are both community and individual tags for an element.
+ var this_obj = $(this);
+ var tag_area = this_obj.find('.tag-area');
+ var toggle_link = this_obj.find('.toggle-link');
+ var tag_input_field = this_obj.find('.tag-input');
+ var add_tag_button = this_obj.find('.add-tag-button');
+
+ // Initialize toggle link.
+ toggle_link.click( function() {
+ // Take special actions depending on whether toggle is showing or hiding link.
+ var after_toggle_fn;
+ if (tag_area.is(":hidden")) {
+ after_toggle_fn = function() {
+ // If there are no tags, go right to editing mode by generating a click on the area.
+ var num_tags = $(this).find('.tag-button').length;
+ if (num_tags === 0) {
+ tag_area.click();
+ }
+ };
+ } else {
+ after_toggle_fn = function() {
+ tag_area.blur();
+ };
+ }
+ tag_area.slideToggle("fast", after_toggle_fn);
+ return $(this);
+ });
+
+ // Initialize tag input field.
+ if (settings.editable) {
+ tag_input_field.hide();
+ }
+ tag_input_field.keyup( function(e) {
+ if ( e.keyCode === 27 ) {
+ // Escape key
+ $(this).trigger( "blur" );
+ } else if (
+ ( e.keyCode === 13 ) || // Return Key
+ ( e.keyCode === 188 ) || // Comma
+ ( e.keyCode === 32 ) // Space
+ ) {
+ //
+ // Check input.
+ //
+
+ var new_value = this.value;
+
+ // Suppress space after a ":"
+ if ( new_value.indexOf(": ", new_value.length - 2) !== -1) {
+ this.value = new_value.substring(0, new_value.length-1);
+ return false;
+ }
+
+ // Remove trigger keys from input.
+ if ( (e.keyCode === 188) || (e.keyCode === 32) ) {
+ new_value = new_value.substring( 0 , new_value.length - 1 );
+ }
+
+ // Trim whitespace.
+ new_value = $.trim(new_value);
+
+ // Too short?
+ if (new_value.length < 2) {
+ return false;
+ }
+
+ //
+ // New tag OK - apply it.
+ //
+
+ this.value = ""; // Reset text field now that tag is being added
+
+ // Add button for tag after all other tag buttons.
+ var new_tag_button = build_tag_button(new_value);
+ var tag_buttons = tag_area.children(".tag-button");
+ if (tag_buttons.length !== 0) {
+ var last_tag_button = tag_buttons.slice(tag_buttons.length-1);
+ last_tag_button.after(new_tag_button);
+ } else {
+ tag_area.prepend(new_tag_button);
+ }
+
+ // Add tag to internal list.
+ var tag_name_and_value = new_value.split(":");
+ settings.tags[tag_name_and_value[0]] = tag_name_and_value[1];
+
+ // Update toggle link text.
+ var new_text = settings.get_toggle_link_text_fn(settings.tags);
+ toggle_link.text(new_text);
+
+ // Commit tag to server.
+ var zz = $(this);
+ $.ajax({
+ url: settings.ajax_add_tag_url,
+ data: { new_tag: new_value },
+ error: function() {
+ // Failed. Roll back changes and show alert.
+ new_tag_button.remove();
+ delete settings.tags[tag_name_and_value[0]];
+ var new_text = settings.get_toggle_link_text_fn(settings.tags);
+ toggle_link.text(new_text);
+ alert( "Add tag failed" );
+ },
+ success: function() {
+ // Flush autocomplete cache because it's not out of date.
+ // TODO: in the future, we could remove the particular item
+ // that was chosen from the cache rather than flush it.
+ zz.data('autocompleter').cacheFlush();
+ }
+ });
+
+ return false;
+ }
+ });
+
+ // Add autocomplete to input.
+ var format_item_func = function(key, row_position, num_rows, value, search_term) {
+ var tag_name_and_value = value.split(":");
+ return (tag_name_and_value.length === 1 ? tag_name_and_value[0] : tag_name_and_value[1]);
+ };
+ var autocomplete_options = { selectFirst: false, formatItem: format_item_func,
+ autoFill: false, highlight: false };
+ tag_input_field.autocomplete(settings.ajax_autocomplete_tag_url, autocomplete_options);
+
+
+ // Initialize delete tag images for current tags.
+ this_obj.find('.delete-tag-img').each(function() {
+ init_delete_tag_image( $(this) );
+ });
+
+
+ // Initialize tag click function.
+ init_tag_click_function($(this), settings.tag_click_fn);
+
+ // Initialize "add tag" button.
+ add_tag_button.click( function() {
+ $(this).hide();
+
+ // Clicking on button is the same as clicking on the tag area.
+ tag_area.click();
+ return false;
+ });
+
+ //
+ // Set up tag area interactions; these are needed only if tags are editable.
+ //
+ if (settings.editable) {
+ // When the tag area blurs, go to "view tag" mode.
+ tag_area.bind("blur", function(e) {
+ if (obj_length(settings.tags) > 0) {
+ add_tag_button.show();
+ tag_input_field.hide();
+ tag_area.removeClass("active-tag-area");
+ // tag_area.addClass("tooltip");
+ } else {
+ // No tags, so do nothing to ensure that input is still visible.
+ }
+ });
+
+ // On click, enable user to add tags.
+ tag_area.click( function(e) {
+ var is_active = $(this).hasClass("active-tag-area");
+
+ // If a "delete image" object was pressed and area is inactive, do nothing.
+ if ($(e.target).hasClass("delete-tag-img") && !is_active) {
+ return false;
+ }
+
+ // If a "tag name" object was pressed and area is inactive, do nothing.
+ if ($(e.target).hasClass("tag-name") && !is_active) {
+ return false;
+ }
+
+ // Remove tooltip.
+ // $(this).removeClass("tooltip");
+
+ // Hide add tag button, show tag_input field. Change background to show
+ // area is active.
+ $(this).addClass("active-tag-area");
+ add_tag_button.hide();
+ tag_input_field.show();
+ tag_input_field.focus();
+
+ // Add handler to document that will call blur when the tag area is blurred;
+ // a tag area is blurred when a user clicks on an element outside the area.
+ var handle_document_click = function(e) {
+ var check_click = function(tag_area, target) {
+ var tag_area_id = tag_area.attr("id");
+ // Blur the tag area if the element clicked on is not in the tag area.
+ if (target !== tag_area) {
+ tag_area.blur();
+ $(window).unbind("click.tagging_blur");
+ $(this).addClass("tooltip");
+ }
+ };
+ check_click(tag_area, $(e.target));
+ };
+ // TODO: we should attach the click handler to all frames in order to capture
+ // clicks outside the frame that this element is in.
+ //window.parent.document.onclick = handle_document_click;
+ //var temp = $(window.parent.document.body).contents().find("iframe").html();
+ //alert(temp);
+ //$(document).parent().click(handle_document_click);
+ $(window).bind("click.tagging_blur", handle_document_click);
+
+ return false;
+ });
+ }
+
+ // If using toggle link, hide the tag area. Otherwise, show the tag area.
+ if (settings.use_toggle_link) {
+ tag_area.hide();
+ }
+
+ //
+ // Helper functions.
+ //
+
+ //
+ // Collapse tag name + value into a single string.
+ //
+ function build_tag_str(tag_name, tag_value) {
+ return tag_name + ( tag_value ? ":" + tag_value : "");
+ }
+
+
+ // Initialize a "delete tag image": when click, delete tag from UI and send delete request to server.
+ function init_delete_tag_image(delete_img) {
+ $(delete_img).mouseenter( function () {
+ $(this).attr("src", settings.delete_tag_img_rollover);
+ });
+ $(delete_img).mouseleave( function () {
+ $(this).attr("src", settings.delete_tag_img);
+ });
+ $(delete_img).click( function () {
+ // Tag button is image's parent.
+ var tag_button = $(this).parent();
+
+ // Get tag name, value.
+ var tag_name_elt = tag_button.find(".tag-name").eq(0);
+ var tag_str = tag_name_elt.text();
+ var tag_name_and_value = tag_str.split(":");
+ var tag_name = tag_name_and_value[0];
+ var tag_value = tag_name_and_value[1];
+
+ var prev_button = tag_button.prev();
+ tag_button.remove();
+
+ // Remove tag from local list for consistency.
+ delete settings.tags[tag_name];
+
+ // Update toggle link text.
+ var new_text = settings.get_toggle_link_text_fn(settings.tags);
+ toggle_link.text(new_text);
+
+ // Delete tag.
+ $.ajax({
+ url: settings.ajax_delete_tag_url,
+ data: { tag_name: tag_name },
+ error: function() {
+ // Failed. Roll back changes and show alert.
+ settings.tags[tag_name] = tag_value;
+ if (prev_button.hasClass("tag-button")) {
+ prev_button.after(tag_button);
+ } else {
+ tag_area.prepend(tag_button);
+ }
+ alert( "Remove tag failed" );
+
+ toggle_link.text(settings.get_toggle_link_text_fn(settings.tags));
+
+ // TODO: no idea why it's necessary to set this up again.
+ delete_img.mouseenter( function () {
+ $(this).attr("src", settings.delete_tag_img_rollover);
+ });
+ delete_img.mouseleave( function () {
+ $(this).attr("src", settings.delete_tag_img);
+ });
+ },
+ success: function() {}
+ });
+
+ return true;
+ });
+ }
+
+ //
+ // Function that builds a tag button.
+ //
+ function build_tag_button(tag_str) {
+ // Build "delete tag" image.
+ var delete_img = $("<img/>").attr("src", settings.delete_tag_img).addClass("delete-tag-img");
+ init_delete_tag_image(delete_img);
+
+ // Build tag button.
+ var tag_name_elt = $("<span>").text(tag_str).addClass("tag-name");
+ tag_name_elt.click( function() {
+ var tag_name_and_value = tag_str.split(":");
+ settings.tag_click_fn(tag_name_and_value[0], tag_name_and_value[1]);
+ return true;
+ });
+
+ var tag_button = $("<span></span>").addClass("tag-button");
+ tag_button.append(tag_name_elt);
+ // Allow delete only if element is editable.
+ if (settings.editable) {
+ tag_button.append(delete_img);
+ }
+
+ return tag_button;
+ }
+
+};
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/galaxy/scripts/galaxy.base.js
--- /dev/null
+++ b/client/galaxy/scripts/galaxy.base.js
@@ -0,0 +1,658 @@
+// requestAnimationFrame polyfill
+(function() {
+ var lastTime = 0;
+ var vendors = ['ms', 'moz', 'webkit', 'o'];
+ for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
+ window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
+ window.cancelRequestAnimationFrame = window[vendors[x]+
+ 'CancelRequestAnimationFrame'];
+ }
+
+ if (!window.requestAnimationFrame)
+ window.requestAnimationFrame = function(callback, element) {
+ var currTime = new Date().getTime();
+ var timeToCall = Math.max(0, 16 - (currTime - lastTime));
+ var id = window.setTimeout(function() { callback(currTime + timeToCall); },
+ timeToCall);
+ lastTime = currTime + timeToCall;
+ return id;
+ };
+
+ if (!window.cancelAnimationFrame)
+ window.cancelAnimationFrame = function(id) {
+ clearTimeout(id);
+ };
+}());
+
+// IE doesn't implement Array.indexOf
+if (!Array.indexOf) {
+ Array.prototype.indexOf = function(obj) {
+ for (var i = 0, len = this.length; i < len; i++) {
+ if (this[i] == obj) {
+ return i;
+ }
+ }
+ return -1;
+ };
+}
+
+// Returns the number of keys (elements) in an array/dictionary.
+function obj_length(obj) {
+ if (obj.length !== undefined) {
+ return obj.length;
+ }
+
+ var count = 0;
+ for (var element in obj) {
+ count++;
+ }
+ return count;
+}
+
+$.fn.makeAbsolute = function(rebase) {
+ return this.each(function() {
+ var el = $(this);
+ var pos = el.position();
+ el.css({
+ position: "absolute",
+ marginLeft: 0, marginTop: 0,
+ top: pos.top, left: pos.left,
+ right: $(window).width() - ( pos.left + el.width() )
+ });
+ if (rebase) {
+ el.remove().appendTo("body");
+ }
+ });
+};
+
+/**
+ * Sets up popupmenu rendering and binds options functions to the appropriate links.
+ * initial_options is a dict with text describing the option pointing to either (a) a
+ * function to perform; or (b) another dict with two required keys, 'url' and 'action' (the
+ * function to perform. (b) is useful for exposing the underlying URL of the option.
+ */
+function make_popupmenu(button_element, initial_options) {
+ /* Use the $.data feature to store options with the link element.
+ This allows options to be changed at a later time
+ */
+ var element_menu_exists = (button_element.data("menu_options"));
+ button_element.data("menu_options", initial_options);
+
+ // If element already has menu, nothing else to do since HTML and actions are already set.
+ if (element_menu_exists) { return; }
+
+ button_element.bind("click.show_popup", function(e) {
+ // Close existing visible menus
+ $(".popmenu-wrapper").remove();
+
+ // Need setTimeouts so clicks don't interfere with each other
+ setTimeout( function() {
+ // Dynamically generate the wrapper holding all the selectable options of the menu.
+ var menu_element = $( "<ul class='dropdown-menu' id='" + button_element.attr('id') + "-menu'></ul>" );
+ var options = button_element.data("menu_options");
+ if (obj_length(options) <= 0) {
+ $("<li>No Options.</li>").appendTo(menu_element);
+ }
+ $.each( options, function( k, v ) {
+ if (v) {
+ // Action can be either an anonymous function and a mapped dict.
+ var action = v.action || v;
+ menu_element.append( $("<li></li>").append( $("<a>").attr("href", v.url).html(k).click(action) ) );
+ } else {
+ menu_element.append( $("<li></li>").addClass( "head" ).append( $("<a href='#'></a>").html(k) ) );
+ }
+ });
+ var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" )
+ .append( menu_element ).appendTo( "body" );
+
+ var x = e.pageX - wrapper.width() / 2 ;
+ x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 5 );
+ x = Math.max( x, $(document).scrollLeft() + 5 );
+
+ wrapper.css({
+ top: e.pageY,
+ left: x
+ });
+ }, 10);
+
+ setTimeout( function() {
+ // Bind click event to current window and all frames to remove any visible menus
+ // Bind to document object instead of window object for IE compat
+ var close_popup = function(el) {
+ $(el).bind("click.close_popup", function() {
+ $(".popmenu-wrapper").remove();
+ el.unbind("click.close_popup");
+ });
+ };
+ close_popup( $(window.document) ); // Current frame
+ close_popup( $(window.top.document) ); // Parent frame
+ for (var frame_id = window.top.frames.length; frame_id--;) { // Sibling frames
+ var frame = $(window.top.frames[frame_id].document);
+ close_popup(frame);
+ }
+ }, 50);
+
+ return false;
+ });
+
+}
+
+/**
+ * Convert two seperate (often adjacent) divs into galaxy popupmenu
+ * - div 1 contains a number of anchors which become the menu options
+ * - div 1 should have a 'popupmenu' attribute
+ * - this popupmenu attribute contains the id of div 2
+ * - div 2 becomes the 'face' of the popupmenu
+ *
+ * NOTE: make_popup_menus finds and operates on all divs with a popupmenu attr (no need to point it at something)
+ * but (since that selector searches the dom on the page), you can send a parent in
+ * NOTE: make_popup_menus, and make_popupmenu are horrible names
+ */
+function make_popup_menus( parent ) {
+ // find all popupmenu menu divs (divs that contains anchors to be converted to menu options)
+ // either in the parent or the document if no parent passed
+ parent = parent || document;
+ $( parent ).find( "div[popupmenu]" ).each( function() {
+ var options = {};
+ var menu = $(this);
+
+ // find each anchor in the menu, convert them into an options map: { a.text : click_function }
+ menu.find( "a" ).each( function() {
+ var link = $(this),
+ link_dom = link.get(0),
+ confirmtext = link_dom.getAttribute( "confirm" ),
+ href = link_dom.getAttribute( "href" ),
+ target = link_dom.getAttribute( "target" );
+
+ // no href - no function (gen. a label)
+ if (!href) {
+ options[ link.text() ] = null;
+
+ } else {
+ options[ link.text() ] = {
+ url: href,
+ action: function() {
+
+ // if theres confirm text, send the dialog
+ if ( !confirmtext || confirm( confirmtext ) ) {
+ // link.click() doesn't use target for some reason,
+ // so manually do it here.
+ if (target) {
+ window.open(href, target);
+ return false;
+ }
+ // For all other links, do the default action.
+ else {
+ link.click();
+ }
+ }
+ }
+ };
+ }
+ });
+ // locate the element with the id corresponding to the menu's popupmenu attr
+ var box = $( parent ).find( "#" + menu.attr( 'popupmenu' ) );
+
+ // For menus with clickable link text, make clicking on the link go through instead
+ // of activating the popup menu
+ box.find("a").bind("click", function(e) {
+ e.stopPropagation(); // Stop bubbling so clicking on the link goes through
+ return true;
+ });
+
+ // attach the click events and menu box building to the box element
+ make_popupmenu(box, options);
+ box.addClass("popup");
+ menu.remove();
+ });
+}
+
+// Alphanumeric/natural sort fn
+function naturalSort(a, b) {
+ // setup temp-scope variables for comparison evauluation
+ var re = /(-?[0-9\.]+)/g,
+ x = a.toString().toLowerCase() || '',
+ y = b.toString().toLowerCase() || '',
+ nC = String.fromCharCode(0),
+ xN = x.replace( re, nC + '$1' + nC ).split(nC),
+ yN = y.replace( re, nC + '$1' + nC ).split(nC),
+ xD = (new Date(x)).getTime(),
+ yD = xD ? (new Date(y)).getTime() : null;
+ // natural sorting of dates
+ if ( yD ) {
+ if ( xD < yD ) { return -1; }
+ else if ( xD > yD ) { return 1; }
+ }
+ // natural sorting through split numeric strings and default strings
+ var oFxNcL, oFyNcL;
+ for ( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) {
+ oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc];
+ oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc];
+ if (oFxNcL < oFyNcL) { return -1; }
+ else if (oFxNcL > oFyNcL) { return 1; }
+ }
+ return 0;
+}
+
+$.fn.refresh_select2 = function() {
+ var select_elt = $(this);
+ var options = { placeholder:'Click to select',
+ closeOnSelect: !select_elt.is("[MULTIPLE]"),
+ dropdownAutoWidth : true,
+ containerCssClass: 'select2-minwidth'
+ };
+ return select_elt.select2( options );
+}
+
+// Replace select box with a text input box + autocomplete.
+function replace_big_select_inputs(min_length, max_length, select_elts) {
+ // To do replace, the select2 plugin must be loaded.
+
+ if (!jQuery.fn.select2) {
+ return;
+ }
+
+ // Set default for min_length and max_length
+ if (min_length === undefined) {
+ min_length = 20;
+ }
+ if (max_length === undefined) {
+ max_length = 3000;
+ }
+
+ select_elts = select_elts || $('select');
+
+ select_elts.each( function() {
+ var select_elt = $(this).not('[multiple]');
+ // Make sure that options is within range.
+ var num_options = select_elt.find('option').length;
+ if ( (num_options < min_length) || (num_options > max_length) ) {
+ return;
+ }
+
+ if (select_elt.hasClass("no-autocomplete")) {
+ return;
+ }
+
+ /* Replaced jQuery.autocomplete with select2, notes:
+ * - multiple selects are supported
+ * - the original element is updated with the value, convert_to_values should not be needed
+ * - events are fired when updating the original element, so refresh_on_change should just work
+ *
+ * - should we still sort dbkey fields here?
+ */
+ select_elt.refresh_select2();
+ });
+}
+
+/**
+ * Make an element with text editable: (a) when user clicks on text, a textbox/area
+ * is provided for editing; (b) when enter key pressed, element's text is set and on_finish
+ * is called.
+ */
+// TODO: use this function to implement async_save_text (implemented below).
+$.fn.make_text_editable = function(config_dict) {
+ // Get config options.
+ var num_cols = ("num_cols" in config_dict ? config_dict.num_cols : 30),
+ num_rows = ("num_rows" in config_dict ? config_dict.num_rows : 4),
+ use_textarea = ("use_textarea" in config_dict ? config_dict.use_textarea : false),
+ on_finish = ("on_finish" in config_dict ? config_dict.on_finish : null),
+ help_text = ("help_text" in config_dict ? config_dict.help_text : null);
+
+ // Add element behavior.
+ var container = $(this);
+ container.addClass("editable-text").click(function(e) {
+ // If there's already an input element, editing is active, so do nothing.
+ if ($(this).children(":input").length > 0) {
+ return;
+ }
+
+ container.removeClass("editable-text");
+
+ // Handler for setting element text.
+ var set_text = function(new_text) {
+ container.find(":input").remove();
+
+ if (new_text !== "") {
+ container.text(new_text);
+ }
+ else {
+ // No text; need a line so that there is a click target.
+ container.html("<br>");
+ }
+ container.addClass("editable-text");
+
+ if (on_finish) {
+ on_finish(new_text);
+ }
+ };
+
+ // Create input element(s) for editing.
+ var cur_text = ("cur_text" in config_dict ? config_dict.cur_text : container.text() ),
+ input_elt, button_elt;
+
+ if (use_textarea) {
+ input_elt = $("<textarea/>")
+ .attr({ rows: num_rows, cols: num_cols }).text($.trim(cur_text))
+ .keyup(function(e) {
+ if (e.keyCode === 27) {
+ // Escape key.
+ set_text(cur_text);
+ }
+ });
+ button_elt = $("<button/>").text("Done").click(function() {
+ set_text(input_elt.val());
+ // Return false so that click does not propogate to container.
+ return false;
+ });
+ }
+ else {
+ input_elt = $("<input type='text'/>").attr({ value: $.trim(cur_text), size: num_cols })
+ .blur(function() {
+ set_text(cur_text);
+ }).keyup(function(e) {
+ if (e.keyCode === 27) {
+ // Escape key.
+ $(this).trigger("blur");
+ } else if (e.keyCode === 13) {
+ // Enter key.
+ set_text($(this).val());
+ }
+
+ // Do not propogate event to avoid unwanted side effects.
+ e.stopPropagation();
+ });
+ }
+
+ // Replace text with input object(s) and focus & select.
+ container.text("");
+ container.append(input_elt);
+ if (button_elt) {
+ container.append(button_elt);
+ }
+ input_elt.focus();
+ input_elt.select();
+
+ // Do not propogate to elements below b/c that blurs input and prevents it from being used.
+ e.stopPropagation();
+ });
+
+ // Add help text if there some.
+ if (help_text) {
+ container.attr("title", help_text).tooltip();
+ }
+
+ return container;
+};
+
+/**
+ * Edit and save text asynchronously.
+ */
+function async_save_text( click_to_edit_elt, text_elt_id, save_url,
+ text_parm_name, num_cols, use_textarea, num_rows, on_start, on_finish ) {
+ // Set defaults if necessary.
+ if (num_cols === undefined) {
+ num_cols = 30;
+ }
+ if (num_rows === undefined) {
+ num_rows = 4;
+ }
+
+ // Set up input element.
+ $("#" + click_to_edit_elt).click(function() {
+ // Check if this is already active
+ if ( $("#renaming-active").length > 0) {
+ return;
+ }
+ var text_elt = $("#" + text_elt_id),
+ old_text = text_elt.text(),
+ t;
+
+ if (use_textarea) {
+ t = $("<textarea></textarea>").attr({ rows: num_rows, cols: num_cols }).text( $.trim(old_text) );
+ } else {
+ t = $("<input type='text'></input>").attr({ value: $.trim(old_text), size: num_cols });
+ }
+ t.attr("id", "renaming-active");
+ t.blur( function() {
+ $(this).remove();
+ text_elt.show();
+ if (on_finish) {
+ on_finish(t);
+ }
+ });
+ t.keyup( function( e ) {
+ if ( e.keyCode === 27 ) {
+ // Escape key
+ $(this).trigger( "blur" );
+ } else if ( e.keyCode === 13 ) {
+ // Enter key submits
+ var ajax_data = {};
+ ajax_data[text_parm_name] = $(this).val();
+ $(this).trigger( "blur" );
+ $.ajax({
+ url: save_url,
+ data: ajax_data,
+ error: function() {
+ alert( "Text editing for elt " + text_elt_id + " failed" );
+ // TODO: call finish or no? For now, let's not because error occurred.
+ },
+ success: function(processed_text) {
+ // Set new text and call finish method.
+ if (processed_text !== "") {
+ text_elt.text(processed_text);
+ } else {
+ text_elt.html("<em>None</em>");
+ }
+ if (on_finish) {
+ on_finish(t);
+ }
+ }
+ });
+ }
+ });
+
+ if (on_start) {
+ on_start(t);
+ }
+ // Replace text with input object and focus & select.
+ text_elt.hide();
+ t.insertAfter(text_elt);
+ t.focus();
+ t.select();
+
+ return;
+ });
+}
+
+function commatize( number ) {
+ number += ''; // Convert to string
+ var rgx = /(\d+)(\d{3})/;
+ while (rgx.test(number)) {
+ number = number.replace(rgx, '$1' + ',' + '$2');
+ }
+ return number;
+}
+
+// Reset tool search to start state.
+function reset_tool_search( initValue ) {
+ // Function may be called in top frame or in tool_menu_frame;
+ // in either case, get the tool menu frame.
+ var tool_menu_frame = $("#galaxy_tools").contents();
+ if (tool_menu_frame.length === 0) {
+ tool_menu_frame = $(document);
+ }
+
+ // Remove classes that indicate searching is active.
+ $(this).removeClass("search_active");
+ tool_menu_frame.find(".toolTitle").removeClass("search_match");
+
+ // Reset visibility of tools and labels.
+ tool_menu_frame.find(".toolSectionBody").hide();
+ tool_menu_frame.find(".toolTitle").show();
+ tool_menu_frame.find(".toolPanelLabel").show();
+ tool_menu_frame.find(".toolSectionWrapper").each( function() {
+ if ($(this).attr('id') !== 'recently_used_wrapper') {
+ // Default action.
+ $(this).show();
+ } else if ($(this).hasClass("user_pref_visible")) {
+ $(this).show();
+ }
+ });
+ tool_menu_frame.find("#search-no-results").hide();
+
+ // Reset search input.
+ tool_menu_frame.find("#search-spinner").hide();
+ if (initValue) {
+ var search_input = tool_menu_frame.find("#tool-search-query");
+ search_input.val("search tools");
+ }
+}
+
+// Create GalaxyAsync object.
+var GalaxyAsync = function(log_action) {
+ this.url_dict = {};
+ this.log_action = (log_action === undefined ? false : log_action);
+};
+
+GalaxyAsync.prototype.set_func_url = function( func_name, url ) {
+ this.url_dict[func_name] = url;
+};
+
+// Set user preference asynchronously.
+GalaxyAsync.prototype.set_user_pref = function( pref_name, pref_value ) {
+ // Get URL.
+ var url = this.url_dict[arguments.callee];
+ if (url === undefined) { return false; }
+ $.ajax({
+ url: url,
+ data: { "pref_name" : pref_name, "pref_value" : pref_value },
+ error: function() { return false; },
+ success: function() { return true; }
+ });
+};
+
+// Log user action asynchronously.
+GalaxyAsync.prototype.log_user_action = function( action, context, params ) {
+ if (!this.log_action) { return; }
+
+ // Get URL.
+ var url = this.url_dict[arguments.callee];
+ if (url === undefined) { return false; }
+ $.ajax({
+ url: url,
+ data: { "action" : action, "context" : context, "params" : params },
+ error: function() { return false; },
+ success: function() { return true; }
+ });
+};
+
+// Initialize refresh events.
+function init_refresh_on_change () {
+ $("select[refresh_on_change='true']")
+ .off('change')
+ .change(function() {
+ var select_field = $(this),
+ select_val = select_field.val(),
+ refresh = false,
+ ref_on_change_vals = select_field.attr("refresh_on_change_values");
+ if (ref_on_change_vals) {
+ ref_on_change_vals = ref_on_change_vals.split(',');
+ var last_selected_value = select_field.attr("last_selected_value");
+ if ($.inArray(select_val, ref_on_change_vals) === -1 && $.inArray(last_selected_value, ref_on_change_vals) === -1) {
+ return;
+ }
+ }
+ $(window).trigger("refresh_on_change");
+ $(document).trigger("convert_to_values"); // Convert autocomplete text to values
+ select_field.get(0).form.submit();
+ });
+
+ // checkboxes refresh on change
+ $(":checkbox[refresh_on_change='true']")
+ .off('click')
+ .click( function() {
+ var select_field = $(this),
+ select_val = select_field.val(),
+ refresh = false,
+ ref_on_change_vals = select_field.attr("refresh_on_change_values");
+ if (ref_on_change_vals) {
+ ref_on_change_vals = ref_on_change_vals.split(',');
+ var last_selected_value = select_field.attr("last_selected_value");
+ if ($.inArray(select_val, ref_on_change_vals) === -1 && $.inArray(last_selected_value, ref_on_change_vals) === -1) {
+ return;
+ }
+ }
+ $(window).trigger("refresh_on_change");
+ select_field.get(0).form.submit();
+ });
+
+ // Links with confirmation
+ $( "a[confirm]" )
+ .off('click')
+ .click( function() {
+ return confirm( $(this).attr("confirm") );
+ });
+};
+
+
+// jQuery plugin to prevent double submission of forms
+// Ref: http://stackoverflow.com/questions/2830542/prevent-double-submission-of-for…
+jQuery.fn.preventDoubleSubmission = function() {
+ $(this).on('submit',function(e){
+ var $form = $(this);
+
+ if ($form.data('submitted') === true) {
+ // Previously submitted - don't submit again
+ e.preventDefault();
+ } else {
+ // Mark it so that the next submit can be ignored
+ $form.data('submitted', true);
+ }
+ });
+
+ // Keep chainability
+ return this;
+};
+
+$(document).ready( function() {
+
+ // Refresh events for form fields.
+ init_refresh_on_change();
+
+ // Tooltips
+ if ( $.fn.tooltip ) {
+ // Put tooltips below items in panel header so that they do not overlap masthead.
+ $(".unified-panel-header [title]").tooltip( { placement: 'bottom' } );
+
+ // default tooltip initialization, it will follow the data-placement tag for tooltip location
+ // and fallback to 'top' if not present
+ $("[title]").tooltip();
+ }
+ // Make popup menus.
+ make_popup_menus();
+
+ // Replace big selects.
+ replace_big_select_inputs(20, 1500);
+
+ // If galaxy_main frame does not exist and link targets galaxy_main,
+ // add use_panels=True and set target to self.
+ $("a").click( function() {
+ var anchor = $(this);
+ var galaxy_main_exists = (parent.frames && parent.frames.galaxy_main);
+ if ( ( anchor.attr( "target" ) == "galaxy_main" ) && ( !galaxy_main_exists ) ) {
+ var href = anchor.attr("href");
+ if (href.indexOf("?") == -1) {
+ href += "?";
+ }
+ else {
+ href += "&";
+ }
+ href += "use_panels=True";
+ anchor.attr("href", href);
+ anchor.attr("target", "_self");
+ }
+ return anchor;
+ });
+
+});
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/galaxy/scripts/galaxy.frame.js
--- /dev/null
+++ b/client/galaxy/scripts/galaxy.frame.js
@@ -0,0 +1,224 @@
+// dependencies
+define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) {
+
+// frame manager
+var GalaxyFrame = Backbone.View.extend(
+{
+ // base element
+ el_main: 'body',
+
+ // frame active/disabled
+ active: false,
+
+ // button active
+ button_active: null,
+
+ // button load
+ button_load : null,
+
+ // initialize
+ initialize : function(options)
+ {
+ // add to masthead menu
+ var self = this;
+
+ // create frames
+ this.frames = new Frames.View({
+ visible: false,
+ });
+
+ // add activate icon
+ this.button_active = new mod_masthead.GalaxyMastheadIcon (
+ {
+ icon : 'fa-th',
+ tooltip : 'Enable/Disable Scratchbook',
+ onclick : function() { self._activate(); },
+ onunload : function() {
+ if (self.frames.length() > 0) {
+ return "You opened " + self.frames.length() + " frame(s) which will be lost.";
+ }
+ }
+ });
+
+ // add to masthead
+ Galaxy.masthead.append(this.button_active);
+
+ // add load icon
+ this.button_load = new mod_masthead.GalaxyMastheadIcon (
+ {
+ icon : 'fa-eye',
+ tooltip : 'Show/Hide Scratchbook',
+ onclick : function(e) {
+ if (self.frames.visible) {
+ self.frames.hide();
+ } else {
+ self.frames.show();
+ }
+ },
+ with_number : true
+ });
+
+ // add to masthead
+ Galaxy.masthead.append(this.button_load);
+
+ // create
+ this.setElement(this.frames.$el);
+
+ // append to main
+ $(this.el_main).append(this.$el);
+
+ // refresh menu
+ this.frames.setOnChange(function() {
+ self._refresh();
+ });
+ this._refresh();
+ },
+
+ /**
+ * Add a dataset to the frames.
+ */
+ add_dataset: function(dataset_id) {
+ var self = this;
+ require(['mvc/data'], function(DATA) {
+ var dataset = new DATA.Dataset({ id: dataset_id });
+ $.when( dataset.fetch() ).then( function() {
+ // Construct frame config based on dataset's type.
+ var frame_config = {
+ title: dataset.get('name')
+ },
+ // HACK: For now, assume 'tabular' and 'interval' are the only
+ // modules that contain tabular files. This needs to be replaced
+ // will a is_datatype() function.
+ is_tabular = _.find(['tabular', 'interval'], function(data_type) {
+ return dataset.get('data_type').indexOf(data_type) !== -1;
+ });
+
+ // Use tabular chunked display if dataset is tabular; otherwise load via URL.
+ if (is_tabular) {
+ var tabular_dataset = new DATA.TabularDataset(dataset.toJSON());
+ _.extend(frame_config, {
+ type: 'other',
+ content: function( parent_elt ) {
+ DATA.createTabularDatasetChunkedView({
+ model: tabular_dataset,
+ parent_elt: parent_elt,
+ embedded: true,
+ height: '100%'
+ });
+ }
+ });
+ }
+ else {
+ _.extend(frame_config, {
+ type: 'url',
+ content: galaxy_config.root + 'datasets/' +
+ dataset.id + '/display/?preview=True'
+ });
+ }
+
+ self.add(frame_config);
+
+ });
+ });
+
+ },
+
+ /**
+ * Add and display a new frame/window based on options.
+ */
+ add: function(options)
+ {
+ // open new tab
+ if (options.target == '_blank')
+ {
+ window.open(options.content);
+ return;
+ }
+
+ // reload entire window
+ if (options.target == '_top' || options.target == '_parent' || options.target == '_self')
+ {
+ window.location = options.content;
+ return;
+ }
+
+ // validate
+ if (!this.active)
+ {
+ // fix url if main frame is unavailable
+ var $galaxy_main = $(window.parent.document).find('#galaxy_main');
+ if (options.target == 'galaxy_main' || options.target == 'center')
+ {
+ if ($galaxy_main.length === 0)
+ {
+ var href = options.content;
+ if (href.indexOf('?') == -1)
+ href += '?';
+ else
+ href += '&';
+ href += 'use_panels=True';
+ window.location = href;
+ } else {
+ $galaxy_main.attr('src', options.content);
+ }
+ } else
+ window.location = options.content;
+
+ // stop
+ return;
+ }
+
+ // add to frames view
+ this.frames.add(options);
+ },
+
+ // activate/disable panel
+ _activate: function ()
+ {
+ // check
+ if (this.active)
+ {
+ // disable
+ this.active = false;
+
+ // toggle
+ this.button_active.untoggle();
+
+ // hide panel
+ this.frames.hide();
+ } else {
+ // activate
+ this.active = true;
+
+ // untoggle
+ this.button_active.toggle();
+ }
+ },
+
+ // update frame counter
+ _refresh: function()
+ {
+ // update on screen counter
+ this.button_load.number(this.frames.length());
+
+ // check
+ if(this.frames.length() === 0)
+ this.button_load.hide();
+ else
+ this.button_load.show();
+
+ // check
+ if (this.frames.visible) {
+ this.button_load.toggle();
+ } else {
+ this.button_load.untoggle();
+ }
+ }
+});
+
+// return
+return {
+ GalaxyFrame: GalaxyFrame
+};
+
+});
diff -r 007f6a80629a74650b72d67821a9505932d284f3 -r 2092948937ac30ef82f71463a235c66d34987088 client/galaxy/scripts/galaxy.library.js
--- /dev/null
+++ b/client/galaxy/scripts/galaxy.library.js
@@ -0,0 +1,169 @@
+// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
+// === MAIN GALAXY LIBRARY MODULE ====
+// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM
+
+define([
+ "galaxy.masthead",
+ "utils/utils",
+ "libs/toastr",
+ "mvc/base-mvc",
+ "mvc/library/library-model",
+ "mvc/library/library-folderlist-view",
+ "mvc/library/library-librarylist-view",
+ "mvc/library/library-librarytoolbar-view",
+ "mvc/library/library-foldertoolbar-view",
+ "mvc/library/library-dataset-view",
+ "mvc/library/library-library-view",
+ "mvc/library/library-folder-view"
+ ],
+function(mod_masthead,
+ mod_utils,
+ mod_toastr,
+ mod_baseMVC,
+ mod_library_model,
+ mod_folderlist_view,
+ mod_librarylist_view,
+ mod_librarytoolbar_view,
+ mod_foldertoolbar_view,
+ mod_library_dataset_view,
+ mod_library_library_view,
+ mod_library_folder_view
+ ) {
+
+// ============================================================================
+// ROUTER
+var LibraryRouter = Backbone.Router.extend({
+ initialize: function() {
+ this.routesHit = 0;
+ //keep count of number of routes handled by the application
+ Backbone.history.on('route', function() { this.routesHit++; }, this);
+ },
+
+ routes: {
+ "" : "libraries",
+ "library/:library_id/permissions" : "library_permissions",
+ "folders/:folder_id/permissions" : "folder_permissions",
+ "folders/:id" : "folder_content",
+ "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
+ "folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions",
+ "folders/:folder_id/datasets/:dataset_id/versions/:ldda_id" : "dataset_version",
+ "folders/:folder_id/download/:format" : "download",
+ "folders/:folder_id/import/:source" : "import_datasets"
+ },
+
+ back: function() {
+ if(this.routesHit > 1) {
+ //more than one route hit -> user did not land to current page directly
+ window.history.back();
+ } else {
+ //otherwise go to the home page. Use replaceState if available so
+ //the navigation doesn't create an extra history entry
+ this.navigate('#', {trigger:true, replace:true});
+ }
+ }
+});
+
+// ============================================================================
+/** session storage for library preferences */
+var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({
+ defaults : {
+ with_deleted : false,
+ sort_order : 'asc',
+ sort_by : 'name'
+ }
+});
+
+// ============================================================================
+// Main controller of Galaxy Library
+var GalaxyLibrary = Backbone.View.extend({
+
+ libraryToolbarView: null,
+ libraryListView: null,
+ library_router: null,
+ libraryView: null,
+ folderToolbarView: null,
+ folderListView: null,
+ datasetView: null,
+
+ initialize : function(){
+ Galaxy.libraries = this;
+
+ this.preferences = new LibraryPrefs( {id: 'global-lib-prefs'} );
+
+ this.library_router = new LibraryRouter();
+
+ this.library_router.on('route:libraries', function() {
+ Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
+ Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView();
+ });
+
+ this.library_router.on('route:folder_content', function(id) {
+ if (Galaxy.libraries.folderToolbarView){
+ Galaxy.libraries.folderToolbarView.$el.unbind('click');
+ }
+ Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id});
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id});
+ });
+
+ this.library_router.on('route:download', function(folder_id, format) {
+ if ($('#folder_list_body').find(':checked').length === 0) {
+ mod_toastr.info( 'You must select at least one dataset to download' );
+ Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true});
+ } else {
+ Galaxy.libraries.folderToolbarView.download(folder_id, format);
+ Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true});
+ }
+ });
+
+ this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){
+ if (Galaxy.libraries.datasetView){
+ Galaxy.libraries.datasetView.$el.unbind('click');
+ }
+ Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id});
+ });
+ this.library_router.on('route:dataset_version', function(folder_id, dataset_id, ldda_id){
+ if (Galaxy.libraries.datasetView){
+ Galaxy.libraries.datasetView.$el.unbind('click');
+ }
+ Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true});
+ });
+
+ this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){
+ if (Galaxy.libraries.datasetView){
+ Galaxy.libraries.datasetView.$el.unbind('click');
+ }
+ Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true});
+ });
+
+ this.library_router.on('route:library_permissions', function(library_id){
+ if (Galaxy.libraries.libraryView){
+ Galaxy.libraries.libraryView.$el.unbind('click');
+ }
+ Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true});
+ });
+
+ this.library_router.on('route:folder_permissions', function(folder_id){
+ if (Galaxy.libraries.folderView){
+ Galaxy.libraries.folderView.$el.unbind('click');
+ }
+ Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true});
+ });
+ this.library_router.on('route:import_datasets', function(folder_id, source){
+ if (Galaxy.libraries.folderToolbarView && Galaxy.libraries.folderListView){
+ Galaxy.libraries.folderToolbarView.showImportModal({source:source});
+ } else {
+ Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: folder_id});
+ Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id});
+ Galaxy.libraries.folderToolbarView.showImportModal({source: source});
+ }
+ });
+
+ Backbone.history.start({pushState: false});
+ }
+});
+
+return {
+ GalaxyApp: GalaxyLibrary
+};
+
+});
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/3b3cd242b4b7/
Changeset: 3b3cd242b4b7
Branch: stable
User: natefoo
Date: 2014-10-06 16:59:17+00:00
Summary: Added tag release_2014.10.06 for changeset 2092948937ac
Affected #: 1 file
diff -r 2092948937ac30ef82f71463a235c66d34987088 -r 3b3cd242b4b7cd20b9c868c393c455524b31b87c .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -19,3 +19,4 @@
2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
+2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
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] 4e4247: Add rodeo destination even though it doesn't work.
by GitHub 06 Oct '14
by GitHub 06 Oct '14
06 Oct '14
Branch: refs/heads/master
Home: https://github.com/galaxyproject/usegalaxy-playbook
Commit: 4e4247588aaf520f449dc923029080a9eb4f2f3c
https://github.com/galaxyproject/usegalaxy-playbook/commit/4e4247588aaf520f…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-10-06 (Mon, 06 Oct 2014)
Changed paths:
M templates/galaxy/test.galaxyproject.org/config/job_conf.xml.j2
Log Message:
-----------
Add rodeo destination even though it doesn't work.
Commit: c0f18b86fd5c6af84777421b0cc8db13fec1b7c2
https://github.com/galaxyproject/usegalaxy-playbook/commit/c0f18b86fd5c6af8…
Author: Nate Coraor <nate(a)bx.psu.edu>
Date: 2014-10-06 (Mon, 06 Oct 2014)
Changed paths:
M stage/group_vars/all.yml
Log Message:
-----------
Update Test.
Compare: https://github.com/galaxyproject/usegalaxy-playbook/compare/c3d57de7f661...…
1
0
commit/galaxy-central: dan: Remove deprecation warnings from util.json methods.
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8f372abd1912/
Changeset: 8f372abd1912
Branch: next-stable
User: dan
Date: 2014-10-06 15:49:09+00:00
Summary: Remove deprecation warnings from util.json methods.
Affected #: 1 file
diff -r 054d8af08f098c76b9b64eb5d60835956abc8ae1 -r 8f372abd19124a95fa79f0eeb7da497dc88682f5 lib/galaxy/util/json.py
--- a/lib/galaxy/util/json.py
+++ b/lib/galaxy/util/json.py
@@ -17,12 +17,10 @@
def to_json_string(*args, **kwargs):
- log.warning("Using deprecated function to_json_string.")
return json.dumps(*args, **kwargs)
def from_json_string(*args, **kwargs):
- log.warning("Using deprecated function from_json_string.")
return json.loads(*args, **kwargs)
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: dan: Remove deprecation warnings from util.json methods.
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/594b48fe90b7/
Changeset: 594b48fe90b7
User: dan
Date: 2014-10-06 15:49:09+00:00
Summary: Remove deprecation warnings from util.json methods.
Affected #: 1 file
diff -r ae1a6cb7f4aae2ee7746fdee01d83d96cff5a0a2 -r 594b48fe90b7b17ed22f5c597837022d8204db47 lib/galaxy/util/json.py
--- a/lib/galaxy/util/json.py
+++ b/lib/galaxy/util/json.py
@@ -17,12 +17,10 @@
def to_json_string(*args, **kwargs):
- log.warning("Using deprecated function to_json_string.")
return json.dumps(*args, **kwargs)
def from_json_string(*args, **kwargs):
- log.warning("Using deprecated function from_json_string.")
return json.loads(*args, **kwargs)
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: Eliminate Galaxy dependencies from lib/galaxy/tools/loader.py.
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ae1a6cb7f4aa/
Changeset: ae1a6cb7f4aa
User: jmchilton
Date: 2014-10-06 13:24:53+00:00
Summary: Eliminate Galaxy dependencies from lib/galaxy/tools/loader.py.
Should allow for reuse in command-line tools that operate on Galaxy tools. Updates for targetting Python 2.6+.
Affected #: 1 file
diff -r 8f746975db66785dcec2ef16f943052d767b01d4 -r ae1a6cb7f4aae2ee7746fdee01d83d96cff5a0a2 lib/galaxy/tools/loader.py
--- a/lib/galaxy/tools/loader.py
+++ b/lib/galaxy/tools/loader.py
@@ -1,10 +1,8 @@
-from __future__ import with_statement
+from xml.etree import ElementTree, ElementInclude
from copy import deepcopy
import os
-from galaxy.util import parse_xml
-
def load_tool(path):
"""
@@ -16,7 +14,7 @@
_import_macros(root, path)
# Expand xml macros
- macro_dict = _macros_of_type(root, 'xml', lambda el: list(el.getchildren()))
+ macro_dict = _macros_of_type(root, 'xml', lambda el: list(el))
_expand_macros([root], macro_dict)
# Expand tokens
@@ -42,7 +40,7 @@
""" Load raw (no macro expansion) tree representation of tool represented
at the specified path.
"""
- tree = parse_xml(path)
+ tree = _parse_xml(path)
return tree
@@ -54,7 +52,7 @@
def _import_macros(root, path):
tool_dir = os.path.dirname(path)
macros_el = _macros_el(root)
- if macros_el:
+ if macros_el is not None:
macro_els = _load_macros(macros_el, tool_dir)
_xml_set_children(macros_el, macro_els)
@@ -66,7 +64,7 @@
def _macros_of_type(root, type, el_func):
macros_el = root.find('macros')
macro_dict = {}
- if macros_el:
+ if macros_el is not None:
macro_els = macros_el.findall('macro')
macro_dict = dict([(macro_el.get("name"), el_func(macro_el)) \
for macro_el in macro_els \
@@ -88,7 +86,7 @@
new_value = _expand_tokens_str(value, tokens)
if not (new_value is value):
element.attrib[key] = new_value
- _expand_tokens(list(element.getchildren()), tokens)
+ _expand_tokens(list(element), tokens)
def _expand_tokens_str(str, tokens):
@@ -129,7 +127,7 @@
def _expand_yield_statements(macro_def, expand_el):
yield_els = [yield_el for macro_def_el in macro_def for yield_el in macro_def_el.findall('.//yield')]
- expand_el_children = expand_el.getchildren()
+ expand_el_children = list(expand_el)
macro_def_parent_map = \
dict((c, p) for macro_def_el in macro_def for p in macro_def_el.getiterator() for c in p)
@@ -151,7 +149,7 @@
macro_els = []
# attribute typed macro
- if macros_el:
+ if macros_el is not None:
macro_els = macros_el.findall("macro")
for macro in macro_els:
if 'type' not in macro.attrib:
@@ -163,7 +161,7 @@
typed_tag = ['template', 'xml', 'token']
for tag in typed_tag:
macro_els = []
- if macros_el:
+ if macros_el is not None:
macro_els = macros_el.findall(tag)
for macro_el in macro_els:
macro_el.attrib['type'] = tag
@@ -188,7 +186,7 @@
def _imported_macro_paths_from_el(macros_el):
imported_macro_paths = []
macro_import_els = []
- if macros_el:
+ if macros_el is not None:
macro_import_els = macros_el.findall("import")
for macro_import_el in macro_import_els:
raw_import_path = macro_import_el.text
@@ -199,13 +197,13 @@
def _load_macro_file(path, tool_dir):
- tree = parse_xml(path)
+ tree = _parse_xml(path)
root = tree.getroot()
return _load_macros(root, tool_dir)
def _xml_set_children(element, new_children):
- for old_child in element.getchildren():
+ for old_child in element:
element.remove(old_child)
for i, new_child in enumerate(new_children):
element.insert(i, new_child)
@@ -216,7 +214,7 @@
parent_el = parent_map[query]
matching_index = -1
#for index, el in enumerate(parent_el.iter('.')): ## Something like this for newer implementation
- for index, el in enumerate(parent_el.getchildren()):
+ for index, el in enumerate(list(parent_el)):
if el == query:
matching_index = index
break
@@ -226,3 +224,10 @@
current_index += 1
parent_el.insert(current_index, deepcopy(target))
parent_el.remove(query)
+
+
+def _parse_xml(fname):
+ tree = ElementTree.parse(fname)
+ root = tree.getroot()
+ ElementInclude.include(root)
+ return tree
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
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/75304086e0b9/
Changeset: 75304086e0b9
Branch: docker-work
User: davebgx
Date: 2014-10-06 13:10:58+00:00
Summary: Close merged branch docker-work.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/89c5e7289942/
Changeset: 89c5e7289942
Branch: tool-autoload
User: davebgx
Date: 2014-10-06 13:11:16+00:00
Summary: Close merged branch tool-autoload.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/92ccf23d883c/
Changeset: 92ccf23d883c
Branch: tool-extract
User: davebgx
Date: 2014-10-06 13:11:28+00:00
Summary: Close merged branch tool-extract.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/1f36c142db9c/
Changeset: 1f36c142db9c
Branch: jjohnson/sqlite-needs-to-import-re-and-sqlite-in--1412274859337
User: davebgx
Date: 2014-10-06 13:11:40+00:00
Summary: Close merged branch jjohnson/sqlite-needs-to-import-re-and-sqlite-in--1412274859337.
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/8f746975db66/
Changeset: 8f746975db66
User: davebgx
Date: 2014-10-06 13:12:06+00:00
Summary: Add api method to reload a tool's configuration.
Affected #: 2 files
diff -r d252ac015734d6e382ff07a0497a84ac575059e2 -r 8f746975db66785dcec2ef16f943052d767b01d4 lib/galaxy/webapps/galaxy/api/tools.py
--- a/lib/galaxy/webapps/galaxy/api/tools.py
+++ b/lib/galaxy/webapps/galaxy/api/tools.py
@@ -3,6 +3,7 @@
from galaxy import exceptions
from galaxy import web, util
from galaxy.web import _future_expose_api_anonymous
+from galaxy.web import _future_expose_api
from galaxy.web.base.controller import BaseAPIController
from galaxy.web.base.controller import UsesVisualizationMixin
from galaxy.web.base.controller import UsesHistoryMixin
@@ -12,6 +13,8 @@
from galaxy.managers.collections_util import dictify_dataset_collection_instance
+import galaxy.queue_worker
+
import logging
log = logging.getLogger( __name__ )
@@ -58,6 +61,18 @@
tool = self._get_tool( id )
return tool.to_dict( trans, io_details=io_details, link_details=link_details )
+ @_future_expose_api
+ @web.require_admin
+ def reload( self, trans, tool_id, **kwd ):
+ """
+ GET /api/tools/{tool_id}/reload
+ Reload specified tool.
+ """
+ toolbox = trans.app.toolbox
+ galaxy.queue_worker.send_control_task( trans, 'reload_tool', noop_self=True, kwargs={ 'tool_id': tool_id } )
+ message, status = trans.app.toolbox.reload_tool_by_id( tool_id )
+ return { status: message }
+
@_future_expose_api_anonymous
def citations( self, trans, id, **kwds ):
tool = self._get_tool( id )
diff -r d252ac015734d6e382ff07a0497a84ac575059e2 -r 8f746975db66785dcec2ef16f943052d767b01d4 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -179,6 +179,7 @@
webapp.mapper.resource( 'ftp_file', 'ftp_files', path_prefix='/api' )
webapp.mapper.resource( 'group', 'groups', path_prefix='/api' )
webapp.mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' )
+ webapp.mapper.connect( '/api/tools/{id:.+?}/reload', action='reload', controller="tools" )
webapp.mapper.connect( '/api/tools/{id:.+?}/citations', action='citations', controller="tools" )
webapp.mapper.connect( '/api/tools/{id:.+?}/download', action='download', controller="tools" )
webapp.mapper.connect( '/api/tools/{id:.+?}', action='show', controller="tools" )
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: Merged in kellrott/galaxy-farm/docker-work (pull request #516)
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d252ac015734/
Changeset: d252ac015734
User: jmchilton
Date: 2014-10-06 01:45:08+00:00
Summary: Merged in kellrott/galaxy-farm/docker-work (pull request #516)
Running docker with 'auto-remove' be default
Affected #: 3 files
diff -r 37cf5505992bcccfc54f133d04b857076e7164ac -r d252ac015734d6e382ff07a0497a84ac575059e2 config/job_conf.xml.sample_advanced
--- a/config/job_conf.xml.sample_advanced
+++ b/config/job_conf.xml.sample_advanced
@@ -77,7 +77,7 @@
of old LWR job runner. If your Pulsar server is running on a
Windows machine for instance this runner should still be used.
- These destinations still needs to target a Pulsar server,
+ These destinations still needs to target a Pulsar server,
older LWR plugins and destinations still work in Galaxy can
target LWR servers, but this support should be considered
deprecated and will disappear with a future release of Galaxy.
@@ -110,7 +110,7 @@
<destination id="local" runner="local"/><destination id="multicore_local" runner="local"><param id="local_slots">4</param><!-- Specify GALAXY_SLOTS for local jobs. -->
- <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over
+ <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over
allocating machine define a second local runner with different name and fewer workers
to run this destination. --><param id="embed_metadata_in_job">True</param>
@@ -119,7 +119,7 @@
try it early - it will slightly speed up local jobs by
embedding metadata calculation in job script itself.
-->
- <job_metrics />
+ <job_metrics /><!-- Above element demonstrates embedded job metrics definition - see
job_metrics_conf.xml.sample for full documentation on possible nested
elements. This empty block will simply disable job metrics for the
@@ -134,12 +134,12 @@
destination - but be sure to add any library paths or data incides
that may be needed read-only.
-->
- <!--
+ <!--
<param id="docker_volumes">$defaults,/mnt/galaxyData/libraries:ro,/mnt/galaxyData/indices:ro</param>
--><!-- For a stock Galaxy instance and traditional job runner $defaults will
expand out as:
-
+
$galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:rw
This assumes most of what is needed is available under Galaxy's root directory,
@@ -153,7 +153,7 @@
$galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:ro
- If using the Pulsar, defaults will be even further restricted because the
+ If using the Pulsar, defaults will be even further restricted because the
Pulsar will (by default) stage all needed inputs into the job's job_directory
(so there is not need to allow the docker container to read all the
files - let alone write over them). Defaults in this case becomes:
@@ -173,15 +173,15 @@
<!-- Control memory allocatable by docker container with following option:
--><!-- <param id="docker_memory">24G</param> -->
- <!-- By default Docker will need to runnable by Galaxy using
+ <!-- By default Docker will need to runnable by Galaxy using
password-less sudo - this can be configured by adding the
following line to the sudoers file of all compute nodes
with docker enabled:
-
+
galaxy ALL = (root) NOPASSWD: SETENV: /usr/bin/docker
- The follow option is set to false to disable sudo (docker
- must likewise be configured to allow this).
+ The follow option is set to false to disable sudo (docker
+ must likewise be configured to allow this).
--><!-- <param id="docker_sudo">false</param> --><!-- Following option can be used to tweak sudo command used by
@@ -192,6 +192,11 @@
http://docs.docker.io/reference/run/#network-settings
--><!-- <param id="docker_net">bridge</param> -->
+ <!-- By default, a container will live on past its run. By
+ adding the '--rm' flag to the command line, the container
+ will be removed automatically after the program is complete.
+ -->
+ <!-- <param id="docker_auto_rm">false</param> --><!-- Following command can be used to tweak docker command. --><!-- <param id="docker_cmd">/usr/local/custom_docker/docker</param> --><!-- Following can be used to connect to docke server in different
@@ -265,7 +270,7 @@
<!-- Burst out from static destination local_cluster_8_core to
static destination shared_cluster_8_core when there are about
50 Galaxy jobs assigned to any of the local_cluster_XXX
- destinations (either running or queued). If there are fewer
+ destinations (either running or queued). If there are fewer
than 50 jobs, just use local_cluster_8_core destination.
Uncomment job_state parameter to make this bursting happen when
@@ -294,8 +299,8 @@
configuration. --><param id="private_token">123456789changeme</param><!-- Uncomment the following statement to disable file staging (e.g.
- if there is a shared file system between Galaxy and the Pulsar
- server). Alternatively action can be set to 'copy' - to replace
+ if there is a shared file system between Galaxy and the Pulsar
+ server). Alternatively action can be set to 'copy' - to replace
http transfers with file system copies, 'remote_transfer' to cause
the Pulsar to initiate HTTP transfers instead of Galaxy, or
'remote_copy' to cause Pulsar to initiate file system copies.
@@ -337,7 +342,7 @@
instead. This may be required if remote host is Windows machine
but probably not otherwise.
-->
- <!-- <param id="rewrite_parameters">false</params> -->
+ <!-- <param id="rewrite_parameters">false</params> --></destination><destination id="pulsar_mq_dest" runner="amqp_pulsar" ><!-- The RESTful Pulsar client sends a request to Pulsar
diff -r 37cf5505992bcccfc54f133d04b857076e7164ac -r d252ac015734d6e382ff07a0497a84ac575059e2 lib/galaxy/tools/deps/containers.py
--- a/lib/galaxy/tools/deps/containers.py
+++ b/lib/galaxy/tools/deps/containers.py
@@ -208,6 +208,7 @@
env_directives=env_directives,
working_directory=working_directory,
net=prop("net", "none"), # By default, docker instance has networking disabled
+ auto_rm=prop("auto_rm", docker_util.DEFAULT_AUTO_REMOVE),
**docker_host_props
)
return "%s\n%s" % (cache_command, run_command)
diff -r 37cf5505992bcccfc54f133d04b857076e7164ac -r d252ac015734d6e382ff07a0497a84ac575059e2 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -8,6 +8,7 @@
DEFAULT_NET = None
DEFAULT_MEMORY = None
DEFAULT_VOLUMES_FROM = None
+DEFAULT_AUTO_REMOVE = True
class DockerVolume(object):
@@ -82,6 +83,7 @@
docker_cmd=DEFAULT_DOCKER_COMMAND,
sudo=DEFAULT_SUDO,
sudo_cmd=DEFAULT_SUDO_COMMAND,
+ auto_rm=DEFAULT_AUTO_REMOVE,
host=DEFAULT_HOST,
):
command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
@@ -100,6 +102,8 @@
command_parts.extend(["-w", working_directory])
if net:
command_parts.extend(["--net", net])
+ if auto_rm:
+ command_parts.append("--rm")
full_image = image
if tag:
full_image = "%s:%s" % (full_image, tag)
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/db93990f8def/
Changeset: db93990f8def
Branch: docker-work
User: kell...(a)gmail.com
Date: 2014-10-05 23:23:55+00:00
Summary: Adding behavior that docker is called with '--rm' flag by default, so containers will automatically be removed. This can be disabled via job_config
Affected #: 3 files
diff -r 4aca849f229f538770376d091fac30e4a76854a8 -r db93990f8def9e20c979337dbca0ef1e7e06f400 config/job_conf.xml.sample_advanced
--- a/config/job_conf.xml.sample_advanced
+++ b/config/job_conf.xml.sample_advanced
@@ -77,7 +77,7 @@
of old LWR job runner. If your Pulsar server is running on a
Windows machine for instance this runner should still be used.
- These destinations still needs to target a Pulsar server,
+ These destinations still needs to target a Pulsar server,
older LWR plugins and destinations still work in Galaxy can
target LWR servers, but this support should be considered
deprecated and will disappear with a future release of Galaxy.
@@ -110,7 +110,7 @@
<destination id="local" runner="local"/><destination id="multicore_local" runner="local"><param id="local_slots">4</param><!-- Specify GALAXY_SLOTS for local jobs. -->
- <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over
+ <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over
allocating machine define a second local runner with different name and fewer workers
to run this destination. --><param id="embed_metadata_in_job">True</param>
@@ -119,7 +119,7 @@
try it early - it will slightly speed up local jobs by
embedding metadata calculation in job script itself.
-->
- <job_metrics />
+ <job_metrics /><!-- Above element demonstrates embedded job metrics definition - see
job_metrics_conf.xml.sample for full documentation on possible nested
elements. This empty block will simply disable job metrics for the
@@ -134,12 +134,12 @@
destination - but be sure to add any library paths or data incides
that may be needed read-only.
-->
- <!--
+ <!--
<param id="docker_volumes">$defaults,/mnt/galaxyData/libraries:ro,/mnt/galaxyData/indices:ro</param>
--><!-- For a stock Galaxy instance and traditional job runner $defaults will
expand out as:
-
+
$galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:rw
This assumes most of what is needed is available under Galaxy's root directory,
@@ -153,7 +153,7 @@
$galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:ro
- If using the Pulsar, defaults will be even further restricted because the
+ If using the Pulsar, defaults will be even further restricted because the
Pulsar will (by default) stage all needed inputs into the job's job_directory
(so there is not need to allow the docker container to read all the
files - let alone write over them). Defaults in this case becomes:
@@ -173,15 +173,15 @@
<!-- Control memory allocatable by docker container with following option:
--><!-- <param id="docker_memory">24G</param> -->
- <!-- By default Docker will need to runnable by Galaxy using
+ <!-- By default Docker will need to runnable by Galaxy using
password-less sudo - this can be configured by adding the
following line to the sudoers file of all compute nodes
with docker enabled:
-
+
galaxy ALL = (root) NOPASSWD: SETENV: /usr/bin/docker
- The follow option is set to false to disable sudo (docker
- must likewise be configured to allow this).
+ The follow option is set to false to disable sudo (docker
+ must likewise be configured to allow this).
--><!-- <param id="docker_sudo">false</param> --><!-- Following option can be used to tweak sudo command used by
@@ -192,6 +192,11 @@
http://docs.docker.io/reference/run/#network-settings
--><!-- <param id="docker_net">bridge</param> -->
+ <!-- By default, a container will live on past its run. By
+ adding the '--rm' flag to the command line, the container
+ will be removed automatically after the program is complete.
+ -->
+ <!-- <param id="docker_auto_rm">false</param> --><!-- Following command can be used to tweak docker command. --><!-- <param id="docker_cmd">/usr/local/custom_docker/docker</param> --><!-- Following can be used to connect to docke server in different
@@ -265,7 +270,7 @@
<!-- Burst out from static destination local_cluster_8_core to
static destination shared_cluster_8_core when there are about
50 Galaxy jobs assigned to any of the local_cluster_XXX
- destinations (either running or queued). If there are fewer
+ destinations (either running or queued). If there are fewer
than 50 jobs, just use local_cluster_8_core destination.
Uncomment job_state parameter to make this bursting happen when
@@ -294,8 +299,8 @@
configuration. --><param id="private_token">123456789changeme</param><!-- Uncomment the following statement to disable file staging (e.g.
- if there is a shared file system between Galaxy and the Pulsar
- server). Alternatively action can be set to 'copy' - to replace
+ if there is a shared file system between Galaxy and the Pulsar
+ server). Alternatively action can be set to 'copy' - to replace
http transfers with file system copies, 'remote_transfer' to cause
the Pulsar to initiate HTTP transfers instead of Galaxy, or
'remote_copy' to cause Pulsar to initiate file system copies.
@@ -337,7 +342,7 @@
instead. This may be required if remote host is Windows machine
but probably not otherwise.
-->
- <!-- <param id="rewrite_parameters">false</params> -->
+ <!-- <param id="rewrite_parameters">false</params> --></destination><destination id="pulsar_mq_dest" runner="amqp_pulsar" ><!-- The RESTful Pulsar client sends a request to Pulsar
diff -r 4aca849f229f538770376d091fac30e4a76854a8 -r db93990f8def9e20c979337dbca0ef1e7e06f400 lib/galaxy/tools/deps/containers.py
--- a/lib/galaxy/tools/deps/containers.py
+++ b/lib/galaxy/tools/deps/containers.py
@@ -208,6 +208,7 @@
env_directives=env_directives,
working_directory=working_directory,
net=prop("net", "none"), # By default, docker instance has networking disabled
+ auto_rm=prop("auto_rm", docker_util.DEFAULT_AUTO_REMOVE),
**docker_host_props
)
return "%s\n%s" % (cache_command, run_command)
diff -r 4aca849f229f538770376d091fac30e4a76854a8 -r db93990f8def9e20c979337dbca0ef1e7e06f400 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -8,6 +8,7 @@
DEFAULT_NET = None
DEFAULT_MEMORY = None
DEFAULT_VOLUMES_FROM = None
+DEFAULT_AUTO_REMOVE = True
class DockerVolume(object):
@@ -82,6 +83,7 @@
docker_cmd=DEFAULT_DOCKER_COMMAND,
sudo=DEFAULT_SUDO,
sudo_cmd=DEFAULT_SUDO_COMMAND,
+ auto_rm=DEFAULT_AUTO_REMOVE,
host=DEFAULT_HOST,
):
command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
@@ -100,6 +102,8 @@
command_parts.extend(["-w", working_directory])
if net:
command_parts.extend(["--net", net])
+ if auto_rm:
+ command_parts.append("--rm")
full_image = image
if tag:
full_image = "%s:%s" % (full_image, tag)
https://bitbucket.org/galaxy/galaxy-central/commits/d252ac015734/
Changeset: d252ac015734
User: jmchilton
Date: 2014-10-06 01:45:08+00:00
Summary: Merged in kellrott/galaxy-farm/docker-work (pull request #516)
Running docker with 'auto-remove' be default
Affected #: 3 files
diff -r 37cf5505992bcccfc54f133d04b857076e7164ac -r d252ac015734d6e382ff07a0497a84ac575059e2 config/job_conf.xml.sample_advanced
--- a/config/job_conf.xml.sample_advanced
+++ b/config/job_conf.xml.sample_advanced
@@ -77,7 +77,7 @@
of old LWR job runner. If your Pulsar server is running on a
Windows machine for instance this runner should still be used.
- These destinations still needs to target a Pulsar server,
+ These destinations still needs to target a Pulsar server,
older LWR plugins and destinations still work in Galaxy can
target LWR servers, but this support should be considered
deprecated and will disappear with a future release of Galaxy.
@@ -110,7 +110,7 @@
<destination id="local" runner="local"/><destination id="multicore_local" runner="local"><param id="local_slots">4</param><!-- Specify GALAXY_SLOTS for local jobs. -->
- <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over
+ <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over
allocating machine define a second local runner with different name and fewer workers
to run this destination. --><param id="embed_metadata_in_job">True</param>
@@ -119,7 +119,7 @@
try it early - it will slightly speed up local jobs by
embedding metadata calculation in job script itself.
-->
- <job_metrics />
+ <job_metrics /><!-- Above element demonstrates embedded job metrics definition - see
job_metrics_conf.xml.sample for full documentation on possible nested
elements. This empty block will simply disable job metrics for the
@@ -134,12 +134,12 @@
destination - but be sure to add any library paths or data incides
that may be needed read-only.
-->
- <!--
+ <!--
<param id="docker_volumes">$defaults,/mnt/galaxyData/libraries:ro,/mnt/galaxyData/indices:ro</param>
--><!-- For a stock Galaxy instance and traditional job runner $defaults will
expand out as:
-
+
$galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:rw
This assumes most of what is needed is available under Galaxy's root directory,
@@ -153,7 +153,7 @@
$galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:ro
- If using the Pulsar, defaults will be even further restricted because the
+ If using the Pulsar, defaults will be even further restricted because the
Pulsar will (by default) stage all needed inputs into the job's job_directory
(so there is not need to allow the docker container to read all the
files - let alone write over them). Defaults in this case becomes:
@@ -173,15 +173,15 @@
<!-- Control memory allocatable by docker container with following option:
--><!-- <param id="docker_memory">24G</param> -->
- <!-- By default Docker will need to runnable by Galaxy using
+ <!-- By default Docker will need to runnable by Galaxy using
password-less sudo - this can be configured by adding the
following line to the sudoers file of all compute nodes
with docker enabled:
-
+
galaxy ALL = (root) NOPASSWD: SETENV: /usr/bin/docker
- The follow option is set to false to disable sudo (docker
- must likewise be configured to allow this).
+ The follow option is set to false to disable sudo (docker
+ must likewise be configured to allow this).
--><!-- <param id="docker_sudo">false</param> --><!-- Following option can be used to tweak sudo command used by
@@ -192,6 +192,11 @@
http://docs.docker.io/reference/run/#network-settings
--><!-- <param id="docker_net">bridge</param> -->
+ <!-- By default, a container will live on past its run. By
+ adding the '--rm' flag to the command line, the container
+ will be removed automatically after the program is complete.
+ -->
+ <!-- <param id="docker_auto_rm">false</param> --><!-- Following command can be used to tweak docker command. --><!-- <param id="docker_cmd">/usr/local/custom_docker/docker</param> --><!-- Following can be used to connect to docke server in different
@@ -265,7 +270,7 @@
<!-- Burst out from static destination local_cluster_8_core to
static destination shared_cluster_8_core when there are about
50 Galaxy jobs assigned to any of the local_cluster_XXX
- destinations (either running or queued). If there are fewer
+ destinations (either running or queued). If there are fewer
than 50 jobs, just use local_cluster_8_core destination.
Uncomment job_state parameter to make this bursting happen when
@@ -294,8 +299,8 @@
configuration. --><param id="private_token">123456789changeme</param><!-- Uncomment the following statement to disable file staging (e.g.
- if there is a shared file system between Galaxy and the Pulsar
- server). Alternatively action can be set to 'copy' - to replace
+ if there is a shared file system between Galaxy and the Pulsar
+ server). Alternatively action can be set to 'copy' - to replace
http transfers with file system copies, 'remote_transfer' to cause
the Pulsar to initiate HTTP transfers instead of Galaxy, or
'remote_copy' to cause Pulsar to initiate file system copies.
@@ -337,7 +342,7 @@
instead. This may be required if remote host is Windows machine
but probably not otherwise.
-->
- <!-- <param id="rewrite_parameters">false</params> -->
+ <!-- <param id="rewrite_parameters">false</params> --></destination><destination id="pulsar_mq_dest" runner="amqp_pulsar" ><!-- The RESTful Pulsar client sends a request to Pulsar
diff -r 37cf5505992bcccfc54f133d04b857076e7164ac -r d252ac015734d6e382ff07a0497a84ac575059e2 lib/galaxy/tools/deps/containers.py
--- a/lib/galaxy/tools/deps/containers.py
+++ b/lib/galaxy/tools/deps/containers.py
@@ -208,6 +208,7 @@
env_directives=env_directives,
working_directory=working_directory,
net=prop("net", "none"), # By default, docker instance has networking disabled
+ auto_rm=prop("auto_rm", docker_util.DEFAULT_AUTO_REMOVE),
**docker_host_props
)
return "%s\n%s" % (cache_command, run_command)
diff -r 37cf5505992bcccfc54f133d04b857076e7164ac -r d252ac015734d6e382ff07a0497a84ac575059e2 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -8,6 +8,7 @@
DEFAULT_NET = None
DEFAULT_MEMORY = None
DEFAULT_VOLUMES_FROM = None
+DEFAULT_AUTO_REMOVE = True
class DockerVolume(object):
@@ -82,6 +83,7 @@
docker_cmd=DEFAULT_DOCKER_COMMAND,
sudo=DEFAULT_SUDO,
sudo_cmd=DEFAULT_SUDO_COMMAND,
+ auto_rm=DEFAULT_AUTO_REMOVE,
host=DEFAULT_HOST,
):
command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
@@ -100,6 +102,8 @@
command_parts.extend(["-w", working_directory])
if net:
command_parts.extend(["--net", net])
+ if auto_rm:
+ command_parts.append("--rm")
full_image = image
if tag:
full_image = "%s:%s" % (full_image, tag)
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/054d8af08f09/
Changeset: 054d8af08f09
Branch: next-stable
User: jmchilton
Date: 2014-10-06 01:36:27+00:00
Summary: Backport Kyle's fix to docker's host argument from default.
See https://bitbucket.org/galaxy/galaxy-central/pull-request/515/fixing-how-doc….
Affected #: 1 file
diff -r 12497a97f7d22d08c6fdafe0c544b4f7a906da98 -r 054d8af08f098c76b9b64eb5d60835956abc8ae1 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -116,5 +116,5 @@
command_parts.append(sudo_cmd)
command_parts.append(docker_cmd)
if host:
- command_parts.append(["-H", host])
+ command_parts.extend(["-H", host])
return command_parts
https://bitbucket.org/galaxy/galaxy-central/commits/37cf5505992b/
Changeset: 37cf5505992b
User: jmchilton
Date: 2014-10-06 01:36:43+00:00
Summary: Merge next-stable.
Affected #: 1 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: jmchilton: Merged in kellrott/galaxy-farm (pull request #515)
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b42fee58bc40/
Changeset: b42fee58bc40
User: jmchilton
Date: 2014-10-06 01:35:01+00:00
Summary: Merged in kellrott/galaxy-farm (pull request #515)
Fixing how docker_utils.__docker_prefix adds host info to command line
Affected #: 1 file
diff -r 3aa7288f5a97970df22fd38c400237028fe33e4b -r b42fee58bc402de82fb4667baa575cb81ab55f4b lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -116,5 +116,5 @@
command_parts.append(sudo_cmd)
command_parts.append(docker_cmd)
if host:
- command_parts.append(["-H", host])
+ command_parts.extend(["-H", host])
return command_parts
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/b94303434f03/
Changeset: b94303434f03
User: kell...(a)gmail.com
Date: 2014-10-05 05:01:12+00:00
Summary: Fixing how docker_util.__docker_prefix sets the host information
Affected #: 1 file
diff -r e7708503e1aacf07dfbbd3fa116de5bd54353b17 -r b94303434f031569a3484edb14e5d1b7a29c36d5 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -59,6 +59,7 @@
):
inspect_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
inspect_command_parts.extend(["inspect", image])
+ print inspect_command_parts
inspect_image_command = " ".join(inspect_command_parts)
pull_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
@@ -116,5 +117,5 @@
command_parts.append(sudo_cmd)
command_parts.append(docker_cmd)
if host:
- command_parts.append(["-H", host])
+ command_parts.extend(["-H", host])
return command_parts
https://bitbucket.org/galaxy/galaxy-central/commits/4aca849f229f/
Changeset: 4aca849f229f
User: kell...(a)gmail.com
Date: 2014-10-05 05:05:38+00:00
Summary: Removing stray print statement
Affected #: 1 file
diff -r b94303434f031569a3484edb14e5d1b7a29c36d5 -r 4aca849f229f538770376d091fac30e4a76854a8 lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -59,7 +59,6 @@
):
inspect_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
inspect_command_parts.extend(["inspect", image])
- print inspect_command_parts
inspect_image_command = " ".join(inspect_command_parts)
pull_command_parts = __docker_prefix(docker_cmd, sudo, sudo_cmd, host)
https://bitbucket.org/galaxy/galaxy-central/commits/b42fee58bc40/
Changeset: b42fee58bc40
User: jmchilton
Date: 2014-10-06 01:35:01+00:00
Summary: Merged in kellrott/galaxy-farm (pull request #515)
Fixing how docker_utils.__docker_prefix adds host info to command line
Affected #: 1 file
diff -r 3aa7288f5a97970df22fd38c400237028fe33e4b -r b42fee58bc402de82fb4667baa575cb81ab55f4b lib/galaxy/tools/deps/docker_util.py
--- a/lib/galaxy/tools/deps/docker_util.py
+++ b/lib/galaxy/tools/deps/docker_util.py
@@ -116,5 +116,5 @@
command_parts.append(sudo_cmd)
command_parts.append(docker_cmd)
if host:
- command_parts.append(["-H", host])
+ command_parts.extend(["-H", host])
return command_parts
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: Merged in kellrott/galaxy-farm/tool-autoload (pull request #512)
by commits-noreply@bitbucket.org 06 Oct '14
by commits-noreply@bitbucket.org 06 Oct '14
06 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/3aa7288f5a97/
Changeset: 3aa7288f5a97
User: jmchilton
Date: 2014-10-06 01:31:21+00:00
Summary: Merged in kellrott/galaxy-farm/tool-autoload (pull request #512)
Adding tool_library_dir to tool_conf parser
Affected #: 3 files
diff -r 342ee791fe55b3bca0bbbe86c2e58509a9f96df6 -r 3aa7288f5a97970df22fd38c400237028fe33e4b lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -235,7 +235,8 @@
elif elem.tag == 'label':
self.load_label_tag_set( elem, self.tool_panel, self.integrated_tool_panel, load_panel_dict, index=index )
elif elem.tag == 'tool_dir':
- self.__watch_directory( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+ self.load_tooldir_tag_set( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+
if parsing_shed_tool_conf:
shed_tool_conf_dict = dict( config_filename=config_filename,
tool_path=tool_path,
@@ -687,7 +688,7 @@
elif sub_elem.tag == 'label':
self.load_label_tag_set( sub_elem, elems, integrated_elems, load_panel_dict, index=sub_index )
elif sub_elem.tag == 'tool_dir':
- self.__watch_directory( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
+ self.load_tooldir_tag_set( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
if load_panel_dict:
self.tool_panel[ key ] = section
# Always load sections into the integrated_tool_panel.
@@ -696,8 +697,12 @@
else:
self.integrated_tool_panel.insert( index, key, integrated_section )
- def __watch_directory( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict ):
+ def load_tooldir_tag_set(self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
+ recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
+ self.__watch_directory( directory, elems, integrated_elems, load_panel_dict, recursive )
+
+ def __watch_directory( self, directory, elems, integrated_elems, load_panel_dict, recursive):
def quick_load( tool_file, async=True ):
try:
@@ -717,16 +722,21 @@
# will be False when things like functional tests are the caller.
self.fix_integrated_tool_panel_dict()
self.write_integrated_tool_panel_config_file()
-
return tool.id
except Exception:
log.exception("Failed to load potential tool %s." % tool_file)
return None
+ tool_loaded = False
for name in os.listdir( directory ):
- if name.endswith( ".xml" ):
- quick_load( os.path.join( directory, name), async=False )
- self.tool_watcher.watch_directory( directory, quick_load )
+ child_path = os.path.join(directory, name)
+ if os.path.isdir(child_path) and recursive:
+ self.__watch_directory(child_path, elems, integrated_elems, load_panel_dict, recursive)
+ elif name.endswith( ".xml" ):
+ quick_load( child_path, async=False )
+ tool_loaded = True
+ if tool_loaded:
+ self.tool_watcher.watch_directory( directory, quick_load )
def load_tool( self, config_file, guid=None, repository_id=None, **kwds ):
"""Load a single tool from the file named by `config_file` and return an instance of `Tool`."""
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
7 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7666506937e2/
Changeset: 7666506937e2
Branch: tool-autoload
User: kell...(a)gmail.com
Date: 2014-09-25 22:24:31+00:00
Summary: Adding in the ability to configure a tool 'auto-load' directory.
Affected #: 3 files
diff -r 82f8d68414f5c9a0e5aeaaabca85cf7044e06183 -r 7666506937e21d70856474a9406f444799579349 config/galaxy.ini.sample
--- a/config/galaxy.ini.sample
+++ b/config/galaxy.ini.sample
@@ -120,7 +120,7 @@
# tool shed install data. There are many situtations in which it is
# valuable to seperate these - for instance bootstrapping fresh Galaxy
# instances with pretested installs. The following optin can be used to
-# separate the tool shed install database (all other options listed above
+# separate the tool shed install database (all other options listed above
# but prefixed with install_ are also available).
#install_database_connection = sqlite:///./database/universe.sqlite?isolation_level=IMMEDIATE
@@ -160,6 +160,14 @@
# Other tool config files must include the tool_path as an attribute in the <toolbox> tag.
#tool_path = tools
+# Path to autoload tools from.
+# Every directory inside the autoload directory will be scanned for *.xml files
+# and those will be loaded as tool descriptors
+#tool_autoload_dir = ./tool-autoload
+
+# Autoload Panel, for all tools that are autoloaded, they are placed in this tool section
+#tool_autoload_section = Development
+
# Path to the directory in which tool dependencies are placed. This is used by
# the tool shed to install dependencies and can also be used by administrators
# to manually install or link to dependencies. For details, see:
@@ -173,7 +181,7 @@
#tool_sheds_config_file = config/tool_sheds_conf.xml
# Enable automatic polling of relative tool sheds to see if any updates
-# are available for installed repositories. Ideally only one Galaxy
+# are available for installed repositories. Ideally only one Galaxy
# server process should be able to check for repository updates. The
# setting for hours_between_check should be an integer between 1 and 24.
#enable_tool_shed_check = False
@@ -238,7 +246,7 @@
#citation_cache_data_dir = database/citations/data
#citation_cache_lock_dir = database/citations/lock
-# External service types config file, defines what types of external_services configurations
+# External service types config file, defines what types of external_services configurations
# are available in Galaxy (.sample is used if default does not exist).
#external_service_type_config_file = config/external_service_types_conf.xml
@@ -347,15 +355,15 @@
# -- Account activation
-# This is user account activation feature global flag. If set to "False" the rest of the Account
+# This is user account activation feature global flag. If set to "False" the rest of the Account
# activation configuration is ignored and user activation is disabled (a.k.a. accounts are active since registration).
# Note the activation is also not working in case the smtp server is not defined.
#user_activation_on = False
-# Activation grace period. Activation is not forced (login is not disabled) until
+# Activation grace period. Activation is not forced (login is not disabled) until
# grace period has passed. Users under grace period can't run jobs (see inactivity_box_content).
-# In hours. Default is 3. Enter 0 to disable grace period.
-# Users with OpenID logins have grace period forever.
+# In hours. Default is 3. Enter 0 to disable grace period.
+# Users with OpenID logins have grace period forever.
#activation_grace_period = 0
# Used for warning box for inactive accounts (unable to run jobs).
@@ -415,7 +423,7 @@
# - $iso8601 (complete format string as specified by ISO 8601 international standard).
# pretty_datetime_format = $locale (UTC)
-# The URL of the page to display in Galaxy's middle pane when loaded. This can be
+# The URL of the page to display in Galaxy's middle pane when loaded. This can be
# an absolute or relative URL.
#welcome_url = /static/welcome.html
@@ -447,7 +455,7 @@
# The URL linked by the "Galaxy Q&A" link in the "Help" menu
# The Galaxy Q&A site is under development; when the site is done, this URL
# will be set and uncommented.
-#qa_url =
+#qa_url =
# Serve static content, which must be enabled if you're not serving it via a
# proxy server. These options should be self explanatory and so are not
@@ -600,7 +608,7 @@
# if testing shows that Galaxy is able to create files using these formats.
# Specific formats can be disabled with this option, separate more than one
# format with commas. Available formats are currently 'zip', 'gz', and 'bz2'.
-#disable_library_comptypes =
+#disable_library_comptypes =
# Some sequencer integration features in beta allow you to automatically
# transfer datasets. This is done using a lightweight transfer manager which
@@ -750,7 +758,7 @@
# File where Data Managers are configured (.sample used if default does not
# exist)
#data_manager_config_file = config/data_manager_conf.xml
-# File where Tool Shed based Data Managers are configured
+# File where Tool Shed based Data Managers are configured
#shed_data_manager_config_file = config/shed_data_manager_conf.xml
# Directory to store Data Manager based tool-data; defaults to tool_data_path
#galaxy_data_manager_data_path = tool-data
@@ -869,11 +877,11 @@
# ---- Galaxy External Message Queue -------------------------------------------------
-# Galaxy uses AMQ protocol to receive messages from external sources like
+# Galaxy uses AMQ protocol to receive messages from external sources like
# bar code scanners. Galaxy has been tested against RabbitMQ AMQP implementation.
-# For Galaxy to receive messages from a message queue the RabbitMQ server has
+# For Galaxy to receive messages from a message queue the RabbitMQ server has
# to be set up with a user account and other parameters listed below. The 'host'
-# and 'port' fields should point to where the RabbitMQ server is running.
+# and 'port' fields should point to where the RabbitMQ server is running.
[galaxy_amqp]
@@ -886,4 +894,3 @@
#exchange = galaxy_exchange
#routing_key = bar_code_scanner
#rabbitmqctl_path = /path/to/rabbitmqctl
-
diff -r 82f8d68414f5c9a0e5aeaaabca85cf7044e06183 -r 7666506937e21d70856474a9406f444799579349 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -88,6 +88,9 @@
self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True )
self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True )
+ self.tool_autoload_dir = kwargs.get( "tool_autoload_dir", None )
+ self.tool_autoload_section = kwargs.get( "tool_autoload_section", None )
+
# Check for tools defined in the above non-shed tool configs (i.e., tool_conf.xml) tht have
# been migrated from the Galaxy code distribution to the Tool Shed.
self.check_migrate_tools = string_as_bool( kwargs.get( 'check_migrate_tools', True ) )
diff -r 82f8d68414f5c9a0e5aeaaabca85cf7044e06183 -r 7666506937e21d70856474a9406f444799579349 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -157,6 +157,23 @@
self.init_tools( config_filename )
except:
log.exception( "Error loading tools defined in config %s", config_filename )
+ if self.app.config.tool_autoload_dir is not None:
+ log.info("Autoloading tool directory: %s" % (self.app.config.tool_autoload_dir))
+
+ auto_load_section = ToolSection({
+ 'id' : "__tool_autoload__",
+ 'version' : "1.0.0",
+ 'name' : self.app.config.tool_autoload_section})
+
+ for tool_xml_path in glob.glob(os.path.join(self.app.config.tool_autoload_dir, "*", "*.xml")):
+ log.info("AutoLoading: %s" % (tool_xml_path))
+ tool = self.load_tool(tool_xml_path)
+ self.tools_by_id[ tool.id ] = tool
+ self.__add_tool_to_tool_panel( tool, auto_load_section, section=True )
+
+ self.tool_panel[ "__tool_autoload__" ] = auto_load_section
+ #self.__add_tool_to_tool_panel( auto_load_section, self.tool_panel, section=False )
+
if self.app.name == 'galaxy' and self.integrated_tool_panel_config_has_contents:
# Load self.tool_panel based on the order in self.integrated_tool_panel.
self.load_tool_panel()
@@ -816,7 +833,7 @@
if len( data_table_definitions ) > 0:
# Put the data table definition XML in a temporary file.
table_definition = '<?xml version="1.0" encoding="utf-8"?>\n<tables>\n %s</tables>'
- table_definition = table_definition % '\n'.join( data_table_definitions )
+ table_definition = table_definition % '\n'.join( data_table_definitions )
fd, table_conf = tempfile.mkstemp()
os.close( fd )
file( table_conf, 'w' ).write( table_definition )
https://bitbucket.org/galaxy/galaxy-central/commits/3a03061c4a85/
Changeset: 3a03061c4a85
Branch: tool-autoload
User: kell...(a)gmail.com
Date: 2014-10-01 06:10:09+00:00
Summary: Default Merge
Affected #: 116 files
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/galaxy.frame.js
--- a/client/galaxy/scripts/galaxy.frame.js
+++ b/client/galaxy/scripts/galaxy.frame.js
@@ -1,9 +1,8 @@
// dependencies
define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) {
-// frame manager
-var GalaxyFrame = Backbone.View.extend(
-{
+/** Frame manager uses the ui-frames to create the scratch book masthead icon and functionality **/
+var GalaxyFrame = Backbone.View.extend({
// base element
el_main: 'body',
@@ -17,8 +16,7 @@
button_load : null,
// initialize
- initialize : function(options)
- {
+ initialize : function(options) {
// add to masthead menu
var self = this;
@@ -28,8 +26,7 @@
});
// add activate icon
- this.button_active = new mod_masthead.GalaxyMastheadIcon (
- {
+ this.button_active = new mod_masthead.GalaxyMastheadIcon({
icon : 'fa-th',
tooltip : 'Enable/Disable Scratchbook',
onclick : function() { self._activate(); },
@@ -44,8 +41,7 @@
Galaxy.masthead.append(this.button_active);
// add load icon
- this.button_load = new mod_masthead.GalaxyMastheadIcon (
- {
+ this.button_load = new mod_masthead.GalaxyMastheadIcon({
icon : 'fa-eye',
tooltip : 'Show/Hide Scratchbook',
onclick : function(e) {
@@ -122,35 +118,77 @@
});
},
+
+ /**
+ * Add a trackster visualization to the frames.
+ */
+ add_trackster_viz: function(viz_id) {
+ var self = this;
+ require(['viz/visualization', 'viz/trackster'], function(visualization, trackster) {
+ var viz = new visualization.Visualization({id: viz_id});
+ $.when( viz.fetch() ).then( function() {
+ var ui = new trackster.TracksterUI(galaxy_config.root);
+
+ // Construct frame config based on dataset's type.
+ var frame_config = {
+ title: viz.get('name'),
+ type: 'other',
+ content: function(parent_elt) {
+ // Create view config.
+ var view_config = {
+ container: parent_elt,
+ name: viz.get('title'),
+ id: viz.id,
+ // FIXME: this will not work with custom builds b/c the dbkey needed to be encoded.
+ dbkey: viz.get('dbkey'),
+ stand_alone: false
+ },
+ latest_revision = viz.get('latest_revision'),
+ drawables = latest_revision.config.view.drawables;
+
+ // Set up datasets in drawables.
+ _.each(drawables, function(d) {
+ d.dataset = {
+ hda_ldda: d.hda_ldda,
+ id: d.dataset_id
+ };
+ });
+
+ view = ui.create_visualization(view_config,
+ latest_revision.config.viewport,
+ latest_revision.config.view.drawables,
+ latest_revision.config.bookmarks,
+ false);
+ }
+ };
+
+ self.add(frame_config);
+ });
+ });
+ },
/**
* Add and display a new frame/window based on options.
*/
- add: function(options)
- {
+ add: function(options){
// open new tab
- if (options.target == '_blank')
- {
+ if (options.target == '_blank'){
window.open(options.content);
return;
}
// reload entire window
- if (options.target == '_top' || options.target == '_parent' || options.target == '_self')
- {
+ if (options.target == '_top' || options.target == '_parent' || options.target == '_self'){
window.location = options.content;
return;
}
// validate
- if (!this.active)
- {
+ if (!this.active){
// fix url if main frame is unavailable
var $galaxy_main = $(window.parent.document).find('#galaxy_main');
- if (options.target == 'galaxy_main' || options.target == 'center')
- {
- if ($galaxy_main.length === 0)
- {
+ if (options.target == 'galaxy_main' || options.target == 'center'){
+ if ($galaxy_main.length === 0){
var href = options.content;
if (href.indexOf('?') == -1)
href += '?';
@@ -173,11 +211,9 @@
},
// activate/disable panel
- _activate: function ()
- {
+ _activate: function (){
// check
- if (this.active)
- {
+ if (this.active){
// disable
this.active = false;
@@ -196,8 +232,7 @@
},
// update frame counter
- _refresh: function()
- {
+ _refresh: function(){
// update on screen counter
this.button_load.number(this.frames.length());
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/galaxy.masthead.js
--- a/client/galaxy/scripts/galaxy.masthead.js
+++ b/client/galaxy/scripts/galaxy.masthead.js
@@ -1,9 +1,8 @@
// dependencies
define([], function() {
-// masthead
-var GalaxyMasthead = Backbone.View.extend(
-{
+/** Masthead **/
+var GalaxyMasthead = Backbone.View.extend({
// base element
el_masthead: '#everything',
@@ -17,8 +16,7 @@
list: [],
// initialize
- initialize : function(options)
- {
+ initialize : function(options) {
// update options
this.options = options;
@@ -51,27 +49,23 @@
},
// configure events
- events:
- {
+ events: {
'click' : '_click',
'mousedown' : function(e) { e.preventDefault() }
},
// adds a new item to the masthead
- append : function(item)
- {
+ append : function(item) {
return this._add(item, true);
},
// adds a new item to the masthead
- prepend : function(item)
- {
+ prepend : function(item) {
return this._add(item, false);
},
// activate
- highlight: function(id)
- {
+ highlight: function(id) {
var current = $(this.el).find('#' + id + '> li');
if (current) {
current.addClass('active');
@@ -79,11 +73,9 @@
},
// adds a new item to the masthead
- _add : function(item, append)
- {
+ _add : function(item, append) {
var $loc = $(this.el).find('#' + item.location);
- if ($loc)
- {
+ if ($loc){
// create frame for new item
var $current = $(item.el);
@@ -106,8 +98,7 @@
},
// handle click event
- _click: function(e)
- {
+ _click: function(e) {
// close all popups
var $all = $(this.el).find('.popup');
if ($all) {
@@ -129,8 +120,7 @@
*/
// fill template
- _template: function(options)
- {
+ _template: function(options) {
var brand_text = options.brand ? ("/ " + options.brand) : "" ;
return '<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse">' +
'<div style="position: relative; right: -50%; float: left;">' +
@@ -150,12 +140,10 @@
}
});
-// icon
-var GalaxyMastheadIcon = Backbone.View.extend(
-{
+/** Masthead icon **/
+var GalaxyMastheadIcon = Backbone.View.extend({
// icon options
- options:
- {
+ options:{
id : '',
icon : 'fa-cog',
tooltip : '',
@@ -169,8 +157,7 @@
location: 'iconbar',
// initialize
- initialize: function (options)
- {
+ initialize: function (options){
// read in defaults
if (options)
this.options = _.defaults(options, this.options);
@@ -189,20 +176,17 @@
},
// show
- show: function()
- {
+ show: function(){
$(this.el).css({visibility : 'visible'});
},
// show
- hide: function()
- {
+ hide: function(){
$(this.el).css({visibility : 'hidden'});
},
// switch icon
- icon: function (new_icon)
- {
+ icon: function (new_icon){
// update icon class
$(this.el).find('.icon').removeClass(this.options.icon)
.addClass(new_icon);
@@ -212,26 +196,22 @@
},
// toggle
- toggle: function()
- {
+ toggle: function(){
$(this.el).addClass('toggle');
},
// untoggle
- untoggle: function()
- {
+ untoggle: function(){
$(this.el).removeClass('toggle');
},
// set/get number
- number: function(new_number)
- {
+ number: function(new_number){
$(this.el).find('.number').text(new_number);
},
// fill template icon
- _template: function (options)
- {
+ _template: function (options){
var tmpl = '<div id="' + options.id + '" class="symbol">' +
'<div class="icon fa fa-2x ' + options.icon + '"></div>';
if (options.with_number)
@@ -243,12 +223,10 @@
}
});
-// tab
-var GalaxyMastheadTab = Backbone.View.extend(
-{
+/** Masthead tab **/
+var GalaxyMastheadTab = Backbone.View.extend({
// main options
- options:
- {
+ options:{
id : '',
title : '',
target : '_parent',
@@ -268,14 +246,12 @@
$menu: null,
// events
- events:
- {
+ events:{
'click .head' : '_head'
},
// initialize
- initialize: function (options)
- {
+ initialize: function (options){
// read in defaults
if (options)
this.options = _.defaults(options, this.options);
@@ -300,20 +276,17 @@
},
// show
- show: function()
- {
+ show: function(){
$(this.el).css({visibility : 'visible'});
},
// show
- hide: function()
- {
+ hide: function(){
$(this.el).css({visibility : 'hidden'});
},
// add menu item
- add: function (options)
- {
+ add: function (options){
// menu option defaults
var menuOptions = {
title : 'Title',
@@ -333,8 +306,7 @@
menuOptions.content = galaxy_config.root + menuOptions.content;
// check if submenu element is available
- if (!this.$menu)
- {
+ if (!this.$menu){
// insert submenu element into root
$(this.el).find('.root').append(this._templateMenu());
@@ -353,8 +325,7 @@
// add events
var self = this;
- $item.on('click', function(e)
- {
+ $item.on('click', function(e){
// prevent default
e.preventDefault();
@@ -372,8 +343,7 @@
},
// show menu on header click
- _head: function(e)
- {
+ _head: function(e){
// prevent default
e.preventDefault();
@@ -387,8 +357,7 @@
}
},
- _attachPopover : function()
- {
+ _attachPopover : function(){
var $popover_element = $(this.el).find('.head');
$popover_element.popover({
html: true,
@@ -402,25 +371,21 @@
},
// fill template header
- _templateMenuItem: function (options)
- {
+ _templateMenuItem: function (options){
return '<li><a href="' + options.content + '" target="' + options.target + '">' + options.title + '</a></li>';
},
// fill template header
- _templateMenu: function ()
- {
+ _templateMenu: function (){
return '<ul class="popup dropdown-menu"></ul>';
},
- _templateDivider: function()
- {
+ _templateDivider: function(){
return '<li class="divider"></li>';
},
// fill template
- _template: function (options)
- {
+ _template: function (options){
// start template
var tmpl = '<ul id="' + options.id + '" class="nav navbar-nav" border="0" cellspacing="0">' +
'<li class="root dropdown" style="">' +
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/galaxy.menu.js
--- a/client/galaxy/scripts/galaxy.menu.js
+++ b/client/galaxy/scripts/galaxy.menu.js
@@ -1,13 +1,8 @@
-/*
- galaxy menu
-*/
-
// dependencies
define(["galaxy.masthead"], function(mod_masthead) {
-// frame manager
-var GalaxyMenu = Backbone.Model.extend(
-{
+/** GalaxyMenu uses the GalaxyMasthead class in order to add menu items and icons to the Masthead **/
+var GalaxyMenu = Backbone.Model.extend({
// options
options: null,
@@ -15,16 +10,14 @@
masthead: null,
// initialize
- initialize: function(options)
- {
+ initialize: function(options) {
this.options = options.config;
this.masthead = options.masthead;
this.create();
},
// default menu
- create: function()
- {
+ create: function(){
//
// Analyze data tab.
//
@@ -137,8 +130,7 @@
var tab_visualization = new mod_masthead.GalaxyMastheadTab(visualization_options);
- if (this.options.user.valid) //add submenu only when user is logged in
- {
+ if (this.options.user.valid){ //add submenu only when user is logged in
tab_visualization.add({
title : "New Track Browser",
content : "visualization/trackster",
@@ -155,8 +147,7 @@
//
// Cloud menu.
//
- if (this.options.enable_cloud_launch)
- {
+ if (this.options.enable_cloud_launch){
var tab_cloud = new mod_masthead.GalaxyMastheadTab({
id : "cloud",
title : "Cloud",
@@ -172,8 +163,7 @@
//
// Admin.
//
- if (this.options.is_admin_user)
- {
+ if (this.options.is_admin_user) {
var tab_admin = new mod_masthead.GalaxyMastheadTab({
id : "admin",
title : "Admin",
@@ -192,8 +182,7 @@
title : "Help",
title_attribute : 'Support, contact, and community hubs'
});
- if (this.options.biostar_url)
- {
+ if (this.options.biostar_url){
tab_help.add({
title : "Galaxy Biostar",
content : this.options.biostar_url_redirect,
@@ -235,8 +224,7 @@
content : this.options.citation_url,
target : "_blank"
});
- if (this.options.terms_url)
- {
+ if (this.options.terms_url){
tab_help.add({
title : "Terms and Conditions",
content : this.options.terms_url,
@@ -248,8 +236,7 @@
//
// User tab.
//
- if (!this.options.user.valid)
- {
+ if (!this.options.user.valid){
var tab_user = new mod_masthead.GalaxyMastheadTab({
id : "user",
title : "User",
@@ -265,8 +252,7 @@
});
// register
- if (this.options.allow_user_creation)
- {
+ if (this.options.allow_user_creation){
tab_user.add({
title : "Register",
content : "user/create",
@@ -331,8 +317,7 @@
target : "galaxy_main"
});
- if (this.options.use_remote_user)
- {
+ if (this.options.use_remote_user){
tab_user.add({
title : "Public Name",
content : "user/edit_username?cntrller=user",
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/base-mvc.js
--- a/client/galaxy/scripts/mvc/base-mvc.js
+++ b/client/galaxy/scripts/mvc/base-mvc.js
@@ -380,11 +380,6 @@
/** allow the view to be dragged, set up event handlers */
draggableOn : function(){
this.draggable = true;
- //TODO: I have no idea why this doesn't work with the events hash or jq.on()...
- //this.$el.find( '.title-bar' )
- // .attr( 'draggable', true )
- // .bind( 'dragstart', this.dragStartHandler, false )
- // .bind( 'dragend', this.dragEndHandler, false );
this.dragStartHandler = _.bind( this._dragStartHandler, this );
this.dragEndHandler = _.bind( this._dragEndHandler, this );
@@ -402,23 +397,22 @@
},
/** sets the dataTransfer data to the model's toJSON
- * @fires dragstart (bbone event) which is passed this view
+ * @fires draggable:dragstart (bbone event) which is passed the event and this view
*/
_dragStartHandler : function( event ){
- //this.debug( 'dragStartHandler:', this, event, arguments )
- this.trigger( 'dragstart', this );
event.dataTransfer.effectAllowed = 'move';
+ //ASSUMES: this.model
//TODO: all except IE: should be 'application/json', IE: must be 'text'
event.dataTransfer.setData( 'text', JSON.stringify( this.model.toJSON() ) );
+ this.trigger( 'draggable:dragstart', event, this );
return false;
},
/** handle the dragend
- * @fires dragend (bbone event) which is passed this view
+ * @fires draggable:dragend (bbone event) which is passed the event and this view
*/
_dragEndHandler : function( event ){
- this.trigger( 'dragend', this );
- //this.debug( 'dragEndHandler:', event )
+ this.trigger( 'draggable:dragend', event, this );
return false;
}
};
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/dataset/dataset-li-edit.js
--- a/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js
+++ b/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js
@@ -181,6 +181,8 @@
}
var $visualizations = $( this.templates.visualizations( visualizations, this ) );
+ //HACK: need to re-write those directed at galaxy_main with linkTarget
+ $visualizations.find( '[target="galaxy_main"]').attr( 'target', this.linkTarget );
// use addBack here to include the root $visualizations elem (for the case of 1 visualization)
this._addScratchBookFn( $visualizations.find( '.visualization-link' ).addBack( '.visualization-link' ) );
return $visualizations;
@@ -188,6 +190,7 @@
/** add scratchbook functionality to visualization links */
_addScratchBookFn : function( $links ){
+ var li = this;
$links.click( function( ev ){
if( Galaxy.frame && Galaxy.frame.active ){
Galaxy.frame.add({
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/dataset/dataset-li.js
--- a/client/galaxy/scripts/mvc/dataset/dataset-li.js
+++ b/client/galaxy/scripts/mvc/dataset/dataset-li.js
@@ -160,7 +160,7 @@
// add frame manager option onclick event
var self = this;
displayBtnData.onclick = function( ev ){
- if( Galaxy.frame && Galaxy.frame.active ){
+ if (Galaxy.frame && Galaxy.frame.active) {
// Add dataset to frames.
Galaxy.frame.add_dataset(self.model.get('id'));
ev.preventDefault();
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/dataset/dataset-model.js
--- a/client/galaxy/scripts/mvc/dataset/dataset-model.js
+++ b/client/galaxy/scripts/mvc/dataset/dataset-model.js
@@ -359,74 +359,11 @@
Backbone.Collection.prototype.set.call( this, models, options );
},
-// /** Convert this ad-hoc collection of hdas to a formal collection tracked
-// by the server.
-// **/
-// promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){
-////TODO: seems like this would be better in mvc/collections
-// options = options || {};
-// options.url = this.url();
-// options.type = "POST";
-// var full_collection_type = collection_type;
-// var element_identifiers = [],
-// name = null;
-//
-// // This mechanism is rough - no error handling, allows invalid selections, no way
-// // for user to pick/override element identifiers. This is only really meant
-// if( collection_type === "list" ) {
-// this.chain().each( function( hda ) {
-// // TODO: Handle duplicate names.
-// var name = hda.attributes.name;
-// var id = hda.get('id');
-// var content_type = hda.attributes.history_content_type;
-// if( content_type === "dataset" ) {
-// if( full_collection_type !== "list" ) {
-// this.log( "Invalid collection type" );
-// }
-// element_identifiers.push( { name: name, src: "hda", id: id } );
-// } else {
-// if( full_collection_type === "list" ) {
-// full_collection_type = "list:" + hda.attributes.collection_type;
-// } else {
-// if( full_collection_type !== "list:" + hda.attributes.collection_type ) {
-// this.log( "Invalid collection type" );
-// }
-// }
-// element_identifiers.push( { name: name, src: "hdca", id: id } );
-// }
-// });
-// name = "New Dataset List";
-// } else if( collection_type === "paired" ) {
-// var ids = this.ids();
-// if( ids.length !== 2 ){
-// // TODO: Do something...
-// }
-// element_identifiers.push( { name: "forward", src: "hda", id: ids[ 0 ] } );
-// element_identifiers.push( { name: "reverse", src: "hda", id: ids[ 1 ] } );
-// name = "New Dataset Pair";
-// }
-// options.data = {
-// type: "dataset_collection",
-// name: name,
-// collection_type: full_collection_type,
-// element_identifiers: JSON.stringify( element_identifiers )
-// };
-//
-// var xhr = jQuery.ajax( options );
-// xhr.done( function( message, status, responseObj ){
-// history.refresh( );
-// });
-// xhr.fail( function( xhr, status, message ){
-// if( xhr.responseJSON && xhr.responseJSON.error ){
-// error = xhr.responseJSON.error;
-// } else {
-// error = xhr.responseJSON;
-// }
-// xhr.responseText = error;
-// // Do something?
-// });
-// return xhr;
-// },
+ ///** Convert this ad-hoc collection of hdas to a formal collection tracked
+ // by the server.
+ //**/
+ //promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){
+ //},
/** String representation. */
toString : function(){
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/history/history-contents.js
--- a/client/galaxy/scripts/mvc/history/history-contents.js
+++ b/client/galaxy/scripts/mvc/history/history-contents.js
@@ -187,6 +187,7 @@
/** copy an existing, accessible hda into this collection */
copy : function( id ){
+//TODO: incorp collections
var collection = this,
xhr = jQuery.post( this.url(), {
source : 'hda',
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/history/history-model.js
--- a/client/galaxy/scripts/mvc/history/history-model.js
+++ b/client/galaxy/scripts/mvc/history/history-model.js
@@ -14,7 +14,7 @@
* @constructs
*/
var History = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
-/** @lends History.prototype */{
+ BASE_MVC.mixin( BASE_MVC.SearchableModelMixin, /** @lends History.prototype */{
/** logger used to record this.log messages, commonly set to console */
//logger : console,
@@ -117,7 +117,19 @@
return _.reduce( _.values( this.get( 'state_details' ) ), function( memo, num ){ return memo + num; }, 0 );
},
- // ........................................................................ ajax
+ // ........................................................................ search
+ /** What model fields to search with */
+ searchAttributes : [
+ 'name', 'annotation', 'tags'
+ ],
+
+ /** Adding title and singular tag */
+ searchAliases : {
+ title : 'name',
+ tag : 'tags'
+ },
+
+ // ........................................................................ updates
/** does the contents collection indicate they're still running and need to be updated later?
* delay + update if needed
* @param {Function} onReadyCallback function to run when all contents are in the ready state
@@ -187,6 +199,18 @@
return xhr;
},
+ // ........................................................................ ajax
+ /** save this history, _Mark_ing it as deleted (just a flag) */
+ _delete : function( options ){
+ if( this.get( 'deleted' ) ){ return jQuery.when(); }
+ return this.save( { deleted: true }, options );
+ },
+ /** save this history, _Mark_ing it as undeleted */
+ undelete : function( options ){
+ if( !this.get( 'deleted' ) ){ return jQuery.when(); }
+ return this.save( { deleted: false }, options );
+ },
+
/** Make a copy of this history on the server
* @param {Boolean} current if true, set the copy as the new current history (default: true)
* @param {String} name name of new history (default: none - server sets to: Copy of <current name>)
@@ -210,9 +234,28 @@
//TODO:?? all datasets?
var history = this,
- xhr = jQuery.post( this.urlRoot, postData );
- xhr.done( function( newData ){
- history.trigger( 'copied', history, newData );
+ copy = jQuery.post( this.urlRoot, postData );
+ // if current - queue to setAsCurrent before firing 'copied'
+ if( current ){
+ return copy.then( function( response ){
+ var newHistory = new History( response );
+ return newHistory.setAsCurrent()
+ .done( function(){
+ history.trigger( 'copied', history, response );
+ });
+ });
+ }
+ return copy.done( function( response ){
+ history.trigger( 'copied', history, response );
+ });
+ },
+
+ setAsCurrent : function(){
+ var history = this,
+ xhr = jQuery.getJSON( '/history/set_as_current?id=' + this.id );
+
+ xhr.done( function(){
+ history.trigger( 'set-as-current', history );
});
return xhr;
},
@@ -221,7 +264,7 @@
toString : function(){
return 'History(' + this.get( 'id' ) + ',' + this.get( 'name' ) + ')';
}
-});
+}));
//------------------------------------------------------------------------------ CLASS VARS
/** When the history has running hdas,
@@ -351,12 +394,15 @@
create : function create( data, hdas, historyOptions, xhrOptions ){
var collection = this,
- history = new History( data || {}, hdas || [], historyOptions || {} );
- return history.save( xhrOptions ).done( function( newData ){
+ xhr = jQuery.getJSON( galaxy_config.root + 'history/create_new_current' );
+ return xhr.done( function( newData ){
+ var history = new History( newData, [], historyOptions || {} );
// new histories go in the front
//TODO: (implicit ordering by update time...)
collection.unshift( history );
+ collection.trigger( 'new-current' );
});
+//TODO: move back to using history.save (via Deferred.then w/ set_as_current)
},
toString: function toString(){
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/history/history-panel-edit-current.js
--- a/client/galaxy/scripts/mvc/history/history-panel-edit-current.js
+++ b/client/galaxy/scripts/mvc/history/history-panel-edit-current.js
@@ -398,14 +398,17 @@
//TODO: move show_deleted/hidden into panel from opt menu and remove this
/** add listeners to an external options menu (templates/webapps/galaxy/root/index.mako) */
connectToOptionsMenu : function( optionsMenu ){
+ var panel = this;
if( !optionsMenu ){
- return this;
+ return panel;
}
// set a visible indication in the popupmenu for show_hidden/deleted based on the currHistoryPanel's settings
- this.on( 'new-storage', function( storage, panel ){
- if( optionsMenu && storage ){
- optionsMenu.findItemByHtml( _l( 'Include Deleted Datasets' ) ).checked = storage.get( 'show_deleted' );
- optionsMenu.findItemByHtml( _l( 'Include Hidden Datasets' ) ).checked = storage.get( 'show_hidden' );
+ this.on( 'new-storage show-deleted show-hidden', function(){
+//TODO: global
+ var menu = ( Galaxy && Galaxy.historyOptionsMenu )? Galaxy.historyOptionsMenu : undefined;
+ if( menu ){
+ menu.findItemByHtml( _l( 'Include Deleted Datasets' ) ).checked = panel.showDeleted;
+ menu.findItemByHtml( _l( 'Include Hidden Datasets' ) ).checked = panel.showHidden;
}
});
return this;
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/history/history-panel-edit.js
--- a/client/galaxy/scripts/mvc/history/history-panel-edit.js
+++ b/client/galaxy/scripts/mvc/history/history-panel-edit.js
@@ -69,6 +69,17 @@
this.multiselectActions = attributes.multiselectActions || this._getActions();
},
+ /** Override to handle history as drag-drop target */
+ _setUpListeners : function(){
+ _super.prototype._setUpListeners.call( this );
+
+ this.on( 'drop', function( ev, data ){
+ this.dataDropped( data );
+ // remove the drop target
+ this.dropTargetOff();
+ });
+ },
+
// ------------------------------------------------------------------------ listeners
/** listening for collection events */
_setUpCollectionListeners : function(){
@@ -104,6 +115,42 @@
return $newRender;
},
+ /** override to render counts when the items are rendered */
+ renderItems : function( $whereTo ){
+ var views = _super.prototype.renderItems.call( this, $whereTo );
+ this._renderCounts( $whereTo );
+ return views;
+ },
+
+ /** override to show counts, what's deleted/hidden, and links to toggle those */
+ _renderCounts : function( $whereTo ){
+//TODO: too complicated
+ function toggleLink( _class, text ){
+ return [ '<a class="', _class, '" href="javascript:void(0);">', text, '</a>' ].join( '' );
+ }
+ $whereTo = $whereTo || this.$el;
+ var deleted = this.collection.where({ deleted: true }),
+ hidden = this.collection.where({ visible: false }),
+ msgs = [];
+
+ if( this.views.length ){
+ msgs.push( [ this.views.length, _l( 'shown' ) ].join( ' ' ) );
+ }
+ if( deleted.length ){
+ msgs.push( ( !this.showDeleted )?
+ ([ deleted.length, toggleLink( 'toggle-deleted-link', _l( 'deleted' ) ) ].join( ' ' ))
+ :( toggleLink( 'toggle-deleted-link', _l( 'hide deleted' ) ) )
+ );
+ }
+ if( hidden.length ){
+ msgs.push( ( !this.showHidden )?
+ ([ hidden.length, toggleLink( 'toggle-hidden-link', _l( 'hidden' ) ) ].join( ' ' ))
+ :( toggleLink( 'toggle-hidden-link', _l( 'hide hidden' ) ) )
+ );
+ }
+ return $whereTo.find( '.subtitle' ).html( msgs.join( ', ' ) );
+ },
+
/** render the tags sub-view controller */
_renderTags : function( $where ){
var panel = this;
@@ -296,10 +343,18 @@
return options;
},
+ ///** Override to alter data in drag based on multiselection */
+ //_setUpItemViewListeners : function( view ){
+ // var panel = this;
+ // _super.prototype._setUpItemViewListeners.call( panel, view );
+ //
+ //},
+
/** If this item is deleted and we're not showing deleted items, remove the view
* @param {Model} the item model to check
*/
_handleHdaDeletionChange : function( itemModel ){
+ this._renderCounts();
if( itemModel.get( 'deleted' ) && !this.showDeleted ){
this.removeItemView( itemModel );
}
@@ -309,6 +364,7 @@
* @param {Model} the item model to check
*/
_handleHdaVisibleChange : function( itemModel ){
+ this._renderCounts();
if( itemModel.hidden() && !this.storage.showHidden ){
this.removeItemView( itemModel );
}
@@ -337,7 +393,9 @@
// ------------------------------------------------------------------------ panel events
/** event map */
events : _.extend( _.clone( _super.prototype.events ), {
- 'click .show-selectors-btn' : 'toggleSelectors'
+ 'click .show-selectors-btn' : 'toggleSelectors',
+ 'click .toggle-deleted-link' : function( ev ){ this.toggleShowDeleted(); },
+ 'click .toggle-hidden-link' : function( ev ){ this.toggleShowHidden(); }
}),
/** Update the history size display (curr. upper right of panel).
@@ -346,6 +404,132 @@
this.$el.find( '.history-size' ).text( this.model.get( 'nice_size' ) );
},
+ // ------------------------------------------------------------------------ as drop target
+ /** */
+ dropTargetOn : function(){
+ if( this.dropTarget ){ return this; }
+ this.dropTarget = true;
+
+ //TODO: to init
+ var dropHandlers = {
+ 'dragenter' : _.bind( this.dragenter, this ),
+ 'dragover' : _.bind( this.dragover, this ),
+ 'dragleave' : _.bind( this.dragleave, this ),
+ 'drop' : _.bind( this.drop, this )
+ };
+//TODO: scroll to top
+ var $dropTarget = this._renderDropTarget();
+ this.$list().before([ this._renderDropTargetHelp(), $dropTarget ]);
+ for( var evName in dropHandlers ){
+ if( dropHandlers.hasOwnProperty( evName ) ){
+ //console.debug( evName, dropHandlers[ evName ] );
+ $dropTarget.on( evName, dropHandlers[ evName ] );
+ }
+ }
+ return this;
+ },
+
+ /** */
+ _renderDropTarget : function(){
+ return $( '<div/>' ).addClass( 'history-drop-target' )
+ .css({
+ 'height': '64px',
+ 'margin': '0px 10px 10px 10px',
+ 'border': '1px dashed black',
+ 'border-radius' : '3px'
+ });
+ },
+
+ /** */
+ _renderDropTargetHelp : function(){
+ return $( '<div/>' ).addClass( 'history-drop-target-help' )
+ .css({
+ 'margin' : '10px 10px 4px 10px',
+ 'color' : 'grey',
+ 'font-size' : '80%',
+ 'font-style' : 'italic'
+ })
+ .text( _l( 'Drag datasets here to copy them to the current history' ) );
+ },
+
+ /** */
+ dropTargetOff : function(){
+ if( !this.dropTarget ){ return this; }
+ //this.log( 'dropTargetOff' );
+ this.dropTarget = false;
+ //
+ //var dropTarget = this.$( '.history-drop-target' ).get(0);
+ //for( var evName in this._dropHandlers ){
+ // if( this._dropHandlers.hasOwnProperty( evName ) ){
+ // console.debug( evName, this._dropHandlers[ evName ] );
+ // dropTarget.off( evName, this._dropHandlers[ evName ] );
+ // }
+ //}
+ this.$( '.history-drop-target' ).remove();
+ this.$( '.history-drop-target-help' ).remove();
+ return this;
+ },
+ /** */
+ dropTargetToggle : function(){
+ if( this.dropTarget ){
+ this.dropTargetOff();
+ } else {
+ this.dropTargetOn();
+ }
+ return this;
+ },
+
+ /** */
+ dragenter : function( ev ){
+ //console.debug( 'dragenter:', this, ev );
+ ev.preventDefault();
+ ev.stopPropagation();
+ this.$( '.history-drop-target' ).css( 'border', '2px solid black' );
+ },
+ /** */
+ dragover : function( ev ){
+ ev.preventDefault();
+ ev.stopPropagation();
+ },
+ /** */
+ dragleave : function( ev ){
+ //console.debug( 'dragleave:', this, ev );
+ ev.preventDefault();
+ ev.stopPropagation();
+ this.$( '.history-drop-target' ).css( 'border', '1px dashed black' );
+ },
+ /** */
+ drop : function( ev ){
+ //console.warn( 'dataTransfer:', ev.dataTransfer.getData( 'text' ) );
+ //console.warn( 'dataTransfer:', ev.originalEvent.dataTransfer.getData( 'text' ) );
+ ev.preventDefault();
+ //ev.stopPropagation();
+ ev.dataTransfer.dropEffect = 'move';
+
+ //console.debug( 'ev.dataTransfer:', ev.dataTransfer );
+
+ var panel = this,
+ data = ev.dataTransfer.getData( "text" );
+ try {
+ data = JSON.parse( data );
+
+ } catch( err ){
+ this.warn( 'error parsing JSON from drop:', data );
+ }
+ this.trigger( 'droptarget:drop', ev, data, panel );
+ return false;
+ },
+
+ /** */
+ dataDropped : function( data ){
+ var panel = this;
+ // HDA: dropping will copy it to the history
+ if( _.isObject( data ) && data.model_class === 'HistoryDatasetAssociation' && data.id ){
+ return panel.model.contents.copy( data.id );
+ }
+ return jQuery.when();
+ },
+
// ........................................................................ misc
/** Return a string rep of the history */
toString : function(){
diff -r 7666506937e21d70856474a9406f444799579349 -r 3a03061c4a858d4a1607114e77ab90793b0e5520 client/galaxy/scripts/mvc/history/history-panel.js
--- a/client/galaxy/scripts/mvc/history/history-panel.js
+++ b/client/galaxy/scripts/mvc/history/history-panel.js
@@ -395,6 +395,7 @@
if( store ){
this.storage.set( 'show_deleted', show );
}
+ this.trigger( 'show-hidden', show );
//TODO:?? to events on storage('change:show_deleted')
this.renderItems();
return this.showDeleted;
@@ -412,6 +413,7 @@
if( store ){
this.storage.set( 'show_hidden', show );
}
+ this.trigger( 'show-hidden', show );
//TODO:?? to events on storage('change:show_deleted')
this.renderItems();
return this.showHidden;
@@ -606,9 +608,7 @@
'<div class="title">',
'<div class="name"><%= history.name %></div>',
'</div>',
- '<div class="subtitle">',
- //'<%= view.collection.length %>', _l( ' items' ),
- '</div>',
+ '<div class="subtitle"></div>',
'<div class="history-size"><%= history.nice_size %></div>',
'<div class="actions"></div>',
This diff is so big that we needed to truncate the remainder.
https://bitbucket.org/galaxy/galaxy-central/commits/b8db34a82175/
Changeset: b8db34a82175
Branch: tool-autoload
User: kell...(a)gmail.com
Date: 2014-10-01 06:12:47+00:00
Summary: Reverting back to default
Affected #: 3 files
diff -r 3a03061c4a858d4a1607114e77ab90793b0e5520 -r b8db34a82175099ad7e52bde344dd356c7199bb4 config/galaxy.ini.sample
--- a/config/galaxy.ini.sample
+++ b/config/galaxy.ini.sample
@@ -120,7 +120,7 @@
# tool shed install data. There are many situtations in which it is
# valuable to seperate these - for instance bootstrapping fresh Galaxy
# instances with pretested installs. The following optin can be used to
-# separate the tool shed install database (all other options listed above
+# separate the tool shed install database (all other options listed above
# but prefixed with install_ are also available).
#install_database_connection = sqlite:///./database/universe.sqlite?isolation_level=IMMEDIATE
@@ -160,14 +160,6 @@
# Other tool config files must include the tool_path as an attribute in the <toolbox> tag.
#tool_path = tools
-# Path to autoload tools from.
-# Every directory inside the autoload directory will be scanned for *.xml files
-# and those will be loaded as tool descriptors
-#tool_autoload_dir = ./tool-autoload
-
-# Autoload Panel, for all tools that are autoloaded, they are placed in this tool section
-#tool_autoload_section = Development
-
# Path to the directory in which tool dependencies are placed. This is used by
# the tool shed to install dependencies and can also be used by administrators
# to manually install or link to dependencies. For details, see:
@@ -187,7 +179,7 @@
#watch_tools = False
# Enable automatic polling of relative tool sheds to see if any updates
-# are available for installed repositories. Ideally only one Galaxy
+# are available for installed repositories. Ideally only one Galaxy
# server process should be able to check for repository updates. The
# setting for hours_between_check should be an integer between 1 and 24.
#enable_tool_shed_check = False
@@ -252,7 +244,7 @@
#citation_cache_data_dir = database/citations/data
#citation_cache_lock_dir = database/citations/lock
-# External service types config file, defines what types of external_services configurations
+# External service types config file, defines what types of external_services configurations
# are available in Galaxy (.sample is used if default does not exist).
#external_service_type_config_file = config/external_service_types_conf.xml
@@ -361,15 +353,15 @@
# -- Account activation
-# This is user account activation feature global flag. If set to "False" the rest of the Account
+# This is user account activation feature global flag. If set to "False" the rest of the Account
# activation configuration is ignored and user activation is disabled (a.k.a. accounts are active since registration).
# Note the activation is also not working in case the smtp server is not defined.
#user_activation_on = False
-# Activation grace period. Activation is not forced (login is not disabled) until
+# Activation grace period. Activation is not forced (login is not disabled) until
# grace period has passed. Users under grace period can't run jobs (see inactivity_box_content).
-# In hours. Default is 3. Enter 0 to disable grace period.
-# Users with OpenID logins have grace period forever.
+# In hours. Default is 3. Enter 0 to disable grace period.
+# Users with OpenID logins have grace period forever.
#activation_grace_period = 0
# Used for warning box for inactive accounts (unable to run jobs).
@@ -429,7 +421,7 @@
# - $iso8601 (complete format string as specified by ISO 8601 international standard).
# pretty_datetime_format = $locale (UTC)
-# The URL of the page to display in Galaxy's middle pane when loaded. This can be
+# The URL of the page to display in Galaxy's middle pane when loaded. This can be
# an absolute or relative URL.
#welcome_url = /static/welcome.html
@@ -461,7 +453,7 @@
# The URL linked by the "Galaxy Q&A" link in the "Help" menu
# The Galaxy Q&A site is under development; when the site is done, this URL
# will be set and uncommented.
-#qa_url =
+#qa_url =
# Serve static content, which must be enabled if you're not serving it via a
# proxy server. These options should be self explanatory and so are not
@@ -614,7 +606,7 @@
# if testing shows that Galaxy is able to create files using these formats.
# Specific formats can be disabled with this option, separate more than one
# format with commas. Available formats are currently 'zip', 'gz', and 'bz2'.
-#disable_library_comptypes =
+#disable_library_comptypes =
# Some sequencer integration features in beta allow you to automatically
# transfer datasets. This is done using a lightweight transfer manager which
@@ -764,7 +756,7 @@
# File where Data Managers are configured (.sample used if default does not
# exist)
#data_manager_config_file = config/data_manager_conf.xml
-# File where Tool Shed based Data Managers are configured
+# File where Tool Shed based Data Managers are configured
#shed_data_manager_config_file = config/shed_data_manager_conf.xml
# Directory to store Data Manager based tool-data; defaults to tool_data_path
#galaxy_data_manager_data_path = tool-data
@@ -883,11 +875,11 @@
# ---- Galaxy External Message Queue -------------------------------------------------
-# Galaxy uses AMQ protocol to receive messages from external sources like
+# Galaxy uses AMQ protocol to receive messages from external sources like
# bar code scanners. Galaxy has been tested against RabbitMQ AMQP implementation.
-# For Galaxy to receive messages from a message queue the RabbitMQ server has
+# For Galaxy to receive messages from a message queue the RabbitMQ server has
# to be set up with a user account and other parameters listed below. The 'host'
-# and 'port' fields should point to where the RabbitMQ server is running.
+# and 'port' fields should point to where the RabbitMQ server is running.
[galaxy_amqp]
@@ -900,3 +892,4 @@
#exchange = galaxy_exchange
#routing_key = bar_code_scanner
#rabbitmqctl_path = /path/to/rabbitmqctl
+
diff -r 3a03061c4a858d4a1607114e77ab90793b0e5520 -r b8db34a82175099ad7e52bde344dd356c7199bb4 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -88,9 +88,6 @@
self.user_label_filters = listify( kwargs.get( "user_tool_label_filters", [] ), do_strip=True )
self.user_section_filters = listify( kwargs.get( "user_tool_section_filters", [] ), do_strip=True )
- self.tool_autoload_dir = kwargs.get( "tool_autoload_dir", None )
- self.tool_autoload_section = kwargs.get( "tool_autoload_section", None )
-
# Check for tools defined in the above non-shed tool configs (i.e., tool_conf.xml) tht have
# been migrated from the Galaxy code distribution to the Tool Shed.
self.check_migrate_tools = string_as_bool( kwargs.get( 'check_migrate_tools', True ) )
diff -r 3a03061c4a858d4a1607114e77ab90793b0e5520 -r b8db34a82175099ad7e52bde344dd356c7199bb4 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -159,23 +159,6 @@
self.init_tools( config_filename )
except:
log.exception( "Error loading tools defined in config %s", config_filename )
- if self.app.config.tool_autoload_dir is not None:
- log.info("Autoloading tool directory: %s" % (self.app.config.tool_autoload_dir))
-
- auto_load_section = ToolSection({
- 'id' : "__tool_autoload__",
- 'version' : "1.0.0",
- 'name' : self.app.config.tool_autoload_section})
-
- for tool_xml_path in glob.glob(os.path.join(self.app.config.tool_autoload_dir, "*", "*.xml")):
- log.info("AutoLoading: %s" % (tool_xml_path))
- tool = self.load_tool(tool_xml_path)
- self.tools_by_id[ tool.id ] = tool
- self.__add_tool_to_tool_panel( tool, auto_load_section, section=True )
-
- self.tool_panel[ "__tool_autoload__" ] = auto_load_section
- #self.__add_tool_to_tool_panel( auto_load_section, self.tool_panel, section=False )
-
if self.app.name == 'galaxy' and self.integrated_tool_panel_config_has_contents:
# Load self.tool_panel based on the order in self.integrated_tool_panel.
self.load_tool_panel()
@@ -880,7 +863,7 @@
if len( data_table_definitions ) > 0:
# Put the data table definition XML in a temporary file.
table_definition = '<?xml version="1.0" encoding="utf-8"?>\n<tables>\n %s</tables>'
- table_definition = table_definition % '\n'.join( data_table_definitions )
+ table_definition = table_definition % '\n'.join( data_table_definitions )
fd, table_conf = tempfile.mkstemp()
os.close( fd )
file( table_conf, 'w' ).write( table_definition )
https://bitbucket.org/galaxy/galaxy-central/commits/890d470c5a61/
Changeset: 890d470c5a61
Branch: tool-autoload
User: kell...(a)gmail.com
Date: 2014-10-01 06:57:03+00:00
Summary: Adding tool_library_dir to tool_conf parser. This will cause all the child directories of a given directory to be watched for tools.
Affected #: 1 file
diff -r b8db34a82175099ad7e52bde344dd356c7199bb4 -r 890d470c5a618cfcb6f53b2f457f8d461ef71fd5 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -236,6 +236,8 @@
self.load_label_tag_set( elem, self.tool_panel, self.integrated_tool_panel, load_panel_dict, index=index )
elif elem.tag == 'tool_dir':
self.__watch_directory( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+ elif elem.tag == 'tool_library_dir':
+ self.__watch_directory_children( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
if parsing_shed_tool_conf:
shed_tool_conf_dict = dict( config_filename=config_filename,
tool_path=tool_path,
@@ -688,6 +690,8 @@
self.load_label_tag_set( sub_elem, elems, integrated_elems, load_panel_dict, index=sub_index )
elif sub_elem.tag == 'tool_dir':
self.__watch_directory( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
+ elif sub_elem.tag == 'tool_library_dir':
+ self.__watch_directory_children( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
if load_panel_dict:
self.tool_panel[ key ] = section
# Always load sections into the integrated_tool_panel.
@@ -696,8 +700,16 @@
else:
self.integrated_tool_panel.insert( index, key, integrated_section )
- def __watch_directory( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict ):
+ def __watch_directory_children( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict ):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
+ for sub in os.listdir( directory ):
+ child = os.path.join(directory, sub)
+ if os.path.isdir(child):
+ self.__watch_directory(None, elems, tool_path, integrated_elems, load_panel_dict, child)
+
+ def __watch_directory( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict, directory=None ):
+ if directory is None:
+ directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
def quick_load( tool_file, async=True ):
try:
@@ -863,7 +875,7 @@
if len( data_table_definitions ) > 0:
# Put the data table definition XML in a temporary file.
table_definition = '<?xml version="1.0" encoding="utf-8"?>\n<tables>\n %s</tables>'
- table_definition = table_definition % '\n'.join( data_table_definitions )
+ table_definition = table_definition % '\n'.join( data_table_definitions )
fd, table_conf = tempfile.mkstemp()
os.close( fd )
file( table_conf, 'w' ).write( table_definition )
https://bitbucket.org/galaxy/galaxy-central/commits/a55060d94308/
Changeset: a55060d94308
Branch: tool-autoload
User: kellrott
Date: 2014-10-01 17:15:43+00:00
Summary: Changing tool_library_repo to work off of tool_dir with attr recursive=True
Affected #: 1 file
diff -r 890d470c5a618cfcb6f53b2f457f8d461ef71fd5 -r a55060d943081345db52ed74f8564d98af5d501a lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -235,9 +235,8 @@
elif elem.tag == 'label':
self.load_label_tag_set( elem, self.tool_panel, self.integrated_tool_panel, load_panel_dict, index=index )
elif elem.tag == 'tool_dir':
- self.__watch_directory( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
- elif elem.tag == 'tool_library_dir':
- self.__watch_directory_children( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+ self.load_tooldir_tag_set( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+
if parsing_shed_tool_conf:
shed_tool_conf_dict = dict( config_filename=config_filename,
tool_path=tool_path,
@@ -689,9 +688,7 @@
elif sub_elem.tag == 'label':
self.load_label_tag_set( sub_elem, elems, integrated_elems, load_panel_dict, index=sub_index )
elif sub_elem.tag == 'tool_dir':
- self.__watch_directory( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
- elif sub_elem.tag == 'tool_library_dir':
- self.__watch_directory_children( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
+ self.load_tooldir_tag_set( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
if load_panel_dict:
self.tool_panel[ key ] = section
# Always load sections into the integrated_tool_panel.
@@ -700,16 +697,12 @@
else:
self.integrated_tool_panel.insert( index, key, integrated_section )
- def __watch_directory_children( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict ):
+ def load_tooldir_tag_set(self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
- for sub in os.listdir( directory ):
- child = os.path.join(directory, sub)
- if os.path.isdir(child):
- self.__watch_directory(None, elems, tool_path, integrated_elems, load_panel_dict, child)
+ recursive = string_as_bool( sub_elem.attrib.get("recursive", False) )
+ self.__watch_directory( directory, elems, integrated_elems, load_panel_dict, recursive )
- def __watch_directory( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict, directory=None ):
- if directory is None:
- directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
+ def __watch_directory( self, directory, elems, integrated_elems, load_panel_dict, recursive):
def quick_load( tool_file, async=True ):
try:
@@ -729,16 +722,21 @@
# will be False when things like functional tests are the caller.
self.fix_integrated_tool_panel_dict()
self.write_integrated_tool_panel_config_file()
-
return tool.id
except Exception:
log.exception("Failed to load potential tool %s." % tool_file)
return None
+ tool_loaded = False
for name in os.listdir( directory ):
- if name.endswith( ".xml" ):
- quick_load( os.path.join( directory, name), async=False )
- self.tool_watcher.watch_directory( directory, quick_load )
+ child_path = os.path.join(directory, name)
+ if os.path.isdir(child_path) and recursive:
+ self.__watch_directory(child_path, elems, integrated_elems, load_panel_dict, recursive)
+ elif name.endswith( ".xml" ):
+ quick_load( child_path, async=False )
+ tool_loaded = True
+ if tool_loaded:
+ self.tool_watcher.watch_directory( directory, quick_load )
def load_tool( self, config_file, guid=None, repository_id=None, **kwds ):
"""Load a single tool from the file named by `config_file` and return an instance of `Tool`."""
https://bitbucket.org/galaxy/galaxy-central/commits/041438f8b528/
Changeset: 041438f8b528
Branch: tool-autoload
User: kellrott
Date: 2014-10-02 17:06:53+00:00
Summary: Changing tool_dir in tool_conf to be recursive by default
Affected #: 1 file
diff -r a55060d943081345db52ed74f8564d98af5d501a -r 041438f8b5281d2ff6618208ff72463b5eeebf52 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -699,7 +699,7 @@
def load_tooldir_tag_set(self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
- recursive = string_as_bool( sub_elem.attrib.get("recursive", False) )
+ recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
self.__watch_directory( directory, elems, integrated_elems, load_panel_dict, recursive )
def __watch_directory( self, directory, elems, integrated_elems, load_panel_dict, recursive):
https://bitbucket.org/galaxy/galaxy-central/commits/3aa7288f5a97/
Changeset: 3aa7288f5a97
User: jmchilton
Date: 2014-10-06 01:31:21+00:00
Summary: Merged in kellrott/galaxy-farm/tool-autoload (pull request #512)
Adding tool_library_dir to tool_conf parser
Affected #: 3 files
diff -r 342ee791fe55b3bca0bbbe86c2e58509a9f96df6 -r 3aa7288f5a97970df22fd38c400237028fe33e4b lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -235,7 +235,8 @@
elif elem.tag == 'label':
self.load_label_tag_set( elem, self.tool_panel, self.integrated_tool_panel, load_panel_dict, index=index )
elif elem.tag == 'tool_dir':
- self.__watch_directory( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+ self.load_tooldir_tag_set( elem, self.tool_panel, self.integrated_tool_panel, tool_path, load_panel_dict )
+
if parsing_shed_tool_conf:
shed_tool_conf_dict = dict( config_filename=config_filename,
tool_path=tool_path,
@@ -687,7 +688,7 @@
elif sub_elem.tag == 'label':
self.load_label_tag_set( sub_elem, elems, integrated_elems, load_panel_dict, index=sub_index )
elif sub_elem.tag == 'tool_dir':
- self.__watch_directory( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
+ self.load_tooldir_tag_set( sub_elem, elems, tool_path, integrated_elems, load_panel_dict )
if load_panel_dict:
self.tool_panel[ key ] = section
# Always load sections into the integrated_tool_panel.
@@ -696,8 +697,12 @@
else:
self.integrated_tool_panel.insert( index, key, integrated_section )
- def __watch_directory( self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict ):
+ def load_tooldir_tag_set(self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
+ recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
+ self.__watch_directory( directory, elems, integrated_elems, load_panel_dict, recursive )
+
+ def __watch_directory( self, directory, elems, integrated_elems, load_panel_dict, recursive):
def quick_load( tool_file, async=True ):
try:
@@ -717,16 +722,21 @@
# will be False when things like functional tests are the caller.
self.fix_integrated_tool_panel_dict()
self.write_integrated_tool_panel_config_file()
-
return tool.id
except Exception:
log.exception("Failed to load potential tool %s." % tool_file)
return None
+ tool_loaded = False
for name in os.listdir( directory ):
- if name.endswith( ".xml" ):
- quick_load( os.path.join( directory, name), async=False )
- self.tool_watcher.watch_directory( directory, quick_load )
+ child_path = os.path.join(directory, name)
+ if os.path.isdir(child_path) and recursive:
+ self.__watch_directory(child_path, elems, integrated_elems, load_panel_dict, recursive)
+ elif name.endswith( ".xml" ):
+ quick_load( child_path, async=False )
+ tool_loaded = True
+ if tool_loaded:
+ self.tool_watcher.watch_directory( directory, quick_load )
def load_tool( self, config_file, guid=None, repository_id=None, **kwds ):
"""Load a single tool from the file named by `config_file` and return an instance of `Tool`."""
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