11 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/8863e5c7e686/ Changeset: 8863e5c7e686 User: dannon Date: 2015-02-14 15:16:13+00:00 Summary: Initial update of SQLAlchemy to 0.8.7. Definitely still needs testing. Affected #: 2 files diff -r b5e29b7e30995a1f67384ce50a490383ee16083c -r 8863e5c7e686f18ddbacabbece22ed8a81c8c45c eggs.ini --- a/eggs.ini +++ b/eggs.ini @@ -26,7 +26,7 @@ pysqlite = 2.5.6 python_lzo = 1.08_2.03_static PyYAML = 3.10 -SQLAlchemy = 0.7.9 +SQLAlchemy = 0.8.7 ; msgpack_python = 0.2.4 [eggs:noplatform] @@ -62,7 +62,8 @@ Routes = 2.1 simplejson = 2.1.1 six = 1.9.0 -sqlalchemy_migrate = 0.7.2 +sqlalchemy_migrate = 0.9.4 +sqlparse = 0.1.14 ssh = 1.7.14 SVGFig = 1.1.6 Tempita = 0.5.1 diff -r b5e29b7e30995a1f67384ce50a490383ee16083c -r 8863e5c7e686f18ddbacabbece22ed8a81c8c45c lib/galaxy/model/migrate/check.py --- a/lib/galaxy/model/migrate/check.py +++ b/lib/galaxy/model/migrate/check.py @@ -4,8 +4,10 @@ from galaxy import eggs eggs.require( "SQLAlchemy" ) -eggs.require( "decorator" ) #Required by sqlalchemy-migrate -eggs.require( "Tempita " ) #Required by sqlalchemy-migrate +eggs.require( "six" ) # Required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # Required by sqlalchemy-migrate +eggs.require( "decorator" ) # Required by sqlalchemy-migrate +eggs.require( "Tempita " ) # Required by sqlalchemy-migrate eggs.require( "sqlalchemy-migrate" ) from sqlalchemy import * https://bitbucket.org/galaxy/galaxy-central/commits/d98b6a04b8b8/ Changeset: d98b6a04b8b8 User: dannon Date: 2015-02-14 15:16:44+00:00 Summary: Fix references to (long deprecated) sqlalchemy.exceptions Affected #: 2 files diff -r 8863e5c7e686f18ddbacabbece22ed8a81c8c45c -r d98b6a04b8b85dcd2e0f93876a04079576dda168 lib/galaxy/managers/users.py --- a/lib/galaxy/managers/users.py +++ b/lib/galaxy/managers/users.py @@ -54,7 +54,7 @@ try: self.app.model.context.flush() #TODO:?? flush needed for permissions below? If not, make optional - except sqlalchemy.exceptions.IntegrityError, db_err: + except sqlalchemy.exc.IntegrityError, db_err: raise exceptions.Conflict( db_err.message ) # can throw an sqlalx.IntegrityError if username not unique diff -r 8863e5c7e686f18ddbacabbece22ed8a81c8c45c -r d98b6a04b8b85dcd2e0f93876a04079576dda168 lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py +++ b/lib/galaxy/model/mapping.py @@ -1723,7 +1723,7 @@ active_folders=relation( model.LibraryFolder, primaryjoin=( ( model.LibraryFolder.table.c.parent_id == model.LibraryFolder.table.c.id ) & ( not_( model.LibraryFolder.table.c.deleted ) ) ), order_by=asc( model.LibraryFolder.table.c.name ), - lazy=True, #"""sqlalchemy.exceptions.ArgumentError: Error creating eager relationship 'active_folders' on parent class '<class 'galaxy.model.LibraryFolder'>' to child class '<class 'galaxy.model.LibraryFolder'>': Cant use eager loading on a self referential relationship.""" + lazy=True, #"""sqlalchemy.exc.ArgumentError: Error creating eager relationship 'active_folders' on parent class '<class 'galaxy.model.LibraryFolder'>' to child class '<class 'galaxy.model.LibraryFolder'>': Cant use eager loading on a self referential relationship.""" viewonly=True ), datasets=relation( model.LibraryDataset, primaryjoin=( ( model.LibraryDataset.table.c.folder_id == model.LibraryFolder.table.c.id ) ), https://bitbucket.org/galaxy/galaxy-central/commits/489925951973/ Changeset: 489925951973 User: dannon Date: 2015-02-14 15:35:42+00:00 Summary: Add all the necessary dependency requires. Note to self: fix the egg dependency resolution bug so we don't have to dot his. Affected #: 6 files diff -r d98b6a04b8b85dcd2e0f93876a04079576dda168 -r 48992595197338928f7b92f8574b192f8c54b577 lib/galaxy/model/orm/scripts.py --- a/lib/galaxy/model/orm/scripts.py +++ b/lib/galaxy/model/orm/scripts.py @@ -9,6 +9,8 @@ eggs.require( "decorator" ) eggs.require( "Tempita" ) eggs.require( "SQLAlchemy" ) +eggs.require( "six" ) # required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # required by sqlalchemy-migrate eggs.require( "sqlalchemy_migrate" ) from galaxy.util.properties import load_app_properties diff -r d98b6a04b8b85dcd2e0f93876a04079576dda168 -r 48992595197338928f7b92f8574b192f8c54b577 lib/galaxy/model/tool_shed_install/migrate/check.py --- a/lib/galaxy/model/tool_shed_install/migrate/check.py +++ b/lib/galaxy/model/tool_shed_install/migrate/check.py @@ -4,6 +4,8 @@ from galaxy import eggs eggs.require( "SQLAlchemy" ) +eggs.require( "six" ) # Required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # Required by sqlalchemy-migrate eggs.require( "decorator" ) # Required by sqlalchemy-migrate eggs.require( "Tempita " ) # Required by sqlalchemy-migrate eggs.require( "sqlalchemy-migrate" ) diff -r d98b6a04b8b85dcd2e0f93876a04079576dda168 -r 48992595197338928f7b92f8574b192f8c54b577 lib/galaxy/webapps/tool_shed/model/migrate/check.py --- a/lib/galaxy/webapps/tool_shed/model/migrate/check.py +++ b/lib/galaxy/webapps/tool_shed/model/migrate/check.py @@ -2,11 +2,12 @@ from galaxy import eggs -import pkg_resources -pkg_resources.require( "SQLAlchemy" ) -pkg_resources.require( "decorator" ) -pkg_resources.require( "sqlalchemy-migrate" ) -pkg_resources.require( "Tempita" ) +eggs.require( "SQLAlchemy" ) +eggs.require( "decorator" ) +eggs.require( "six" ) # Required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # Required by sqlalchemy-migrate +eggs.require( "sqlalchemy-migrate" ) +eggs.require( "Tempita" ) from migrate.versioning import repository, schema diff -r d98b6a04b8b85dcd2e0f93876a04079576dda168 -r 48992595197338928f7b92f8574b192f8c54b577 lib/tool_shed/galaxy_install/migrate/check.py --- a/lib/tool_shed/galaxy_install/migrate/check.py +++ b/lib/tool_shed/galaxy_install/migrate/check.py @@ -5,6 +5,8 @@ from galaxy import eggs eggs.require( "decorator" ) eggs.require( "Tempita" ) +eggs.require( "six" ) # Required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # Required by sqlalchemy-migrate eggs.require( "SQLAlchemy" ) eggs.require( "sqlalchemy_migrate" ) from migrate.versioning import repository diff -r d98b6a04b8b85dcd2e0f93876a04079576dda168 -r 48992595197338928f7b92f8574b192f8c54b577 scripts/manage_db.py --- a/scripts/manage_db.py +++ b/scripts/manage_db.py @@ -13,6 +13,8 @@ eggs.require( "decorator" ) eggs.require( "Tempita" ) eggs.require( "SQLAlchemy" ) +eggs.require( "six" ) # Required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # Required by sqlalchemy-migrate eggs.require( "sqlalchemy_migrate" ) from migrate.versioning.shell import main diff -r d98b6a04b8b85dcd2e0f93876a04079576dda168 -r 48992595197338928f7b92f8574b192f8c54b577 scripts/manage_tools.py --- a/scripts/manage_tools.py +++ b/scripts/manage_tools.py @@ -8,11 +8,12 @@ from galaxy import eggs -import pkg_resources -pkg_resources.require( "SQLAlchemy" ) -pkg_resources.require( "decorator" ) -pkg_resources.require( "Tempita " ) -pkg_resources.require( "sqlalchemy-migrate" ) +eggs.require( "SQLAlchemy" ) +eggs.require( "decorator" ) +eggs.require( "Tempita " ) +eggs.require( "six" ) # Required by sqlalchemy-migrate +eggs.require( "sqlparse" ) # Required by sqlalchemy-migrate +eggs.require( "sqlalchemy-migrate" ) from migrate.versioning.shell import main from ConfigParser import SafeConfigParser https://bitbucket.org/galaxy/galaxy-central/commits/477ebeedaf0c/ Changeset: 477ebeedaf0c User: dannon Date: 2015-02-14 15:38:09+00:00 Summary: Merge. Affected #: 1 file diff -r 48992595197338928f7b92f8574b192f8c54b577 -r 477ebeedaf0c845811602e28ea0ec3d3362d3c2a requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -14,14 +14,14 @@ # starting a Galaxy server. Use this in conjunction with the # `GALAXY_ENABLE_EGGS=False` environment variable. # -# Note that except in the case of SQLAlchemy, all dependencies will be -# installed at their newest versions. Galaxy has not been tested with these and -# you may (likely?) run into problems! The Galaxy Team does not support using -# Galaxy with dependency versions other than those in eggs.ini, however, if you -# do find an incompatibility between Galaxy and the latest version, we would -# appreciate if you would investigate and provide a code fix for the issue. We -# are trying to move away from our strict version dependency policy and this -# would greatly help in our efforts. +# Note that except in the case of SQLAlchemy and Whoosh, all dependencies will +# be installed at their newest versions. Galaxy has not been tested with these +# and you may (likely?) run into problems! The Galaxy Team does not support +# using Galaxy with dependency versions other than those in eggs.ini, however, +# if you do find an incompatibility between Galaxy and the latest version, we +# would appreciate if you would investigate and provide a code fix for the +# issue. We are trying to move away from our strict version dependency policy +# and this would greatly help in our efforts. Paste PasteDeploy https://bitbucket.org/galaxy/galaxy-central/commits/7f780e8c98aa/ Changeset: 7f780e8c98aa User: dannon Date: 2015-02-14 15:55:17+00:00 Summary: Merge. Affected #: 1 file diff -r 477ebeedaf0c845811602e28ea0ec3d3362d3c2a -r 7f780e8c98aa951432ccc89eb00a697c8d957048 lib/galaxy/util/__init__.py --- a/lib/galaxy/util/__init__.py +++ b/lib/galaxy/util/__init__.py @@ -519,7 +519,7 @@ # This can manipulate the input other than just masking password, # so the previous string replace method is preferred when the # password doesn't appear twice in the url - split._replace(netloc=split.netloc.replace("%s:%s" % (split.username, split.password), '%s:********' % split.username)) + split = split._replace(netloc=split.netloc.replace("%s:%s" % (split.username, split.password), '%s:********' % split.username)) url = urlparse.urlunsplit(split) return url https://bitbucket.org/galaxy/galaxy-central/commits/af7603a13e8d/ Changeset: af7603a13e8d User: dannon Date: 2015-02-14 16:05:54+00:00 Summary: Merge. Affected #: 1 file diff -r 7f780e8c98aa951432ccc89eb00a697c8d957048 -r af7603a13e8d5340f064312808b6ebfb56d1a959 lib/galaxy/tools/actions/__init__.py --- a/lib/galaxy/tools/actions/__init__.py +++ b/lib/galaxy/tools/actions/__init__.py @@ -548,7 +548,7 @@ pass #process change_format tags - if output.change_format: + if output.change_format is not None: new_format_set = False for change_elem in output.change_format: for when_elem in change_elem.findall( 'when' ): https://bitbucket.org/galaxy/galaxy-central/commits/4909df6a1dbd/ Changeset: 4909df6a1dbd User: dannon Date: 2015-02-16 16:17:51+00:00 Summary: Merge. Affected #: 14 files diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 client/galaxy/scripts/mvc/tools/tools-form-workflow.js --- a/client/galaxy/scripts/mvc/tools/tools-form-workflow.js +++ b/client/galaxy/scripts/mvc/tools/tools-form-workflow.js @@ -21,8 +21,8 @@ this.options = options; // set labels - this.options.text_enable = 'In Advance'; - this.options.text_disable = 'At Runtime'; + this.options.text_enable = 'Set in Advance'; + this.options.text_disable = 'Set at Runtime'; // configure workflow style this.options.is_dynamic = false; @@ -33,7 +33,7 @@ // declare fields as optional Utils.deepeach(options.inputs, function(item) { if (item.type) { - item.optional = (['data', 'data_hidden', 'hidden', 'drill_down', 'repeat', 'conditional']).indexOf(item.type) == -1; + item.optional = (['data', 'data_hidden', 'hidden', 'repeat', 'conditional']).indexOf(item.type) == -1; } }); diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 client/galaxy/scripts/mvc/tools/tools-input.js --- a/client/galaxy/scripts/mvc/tools/tools-input.js +++ b/client/galaxy/scripts/mvc/tools/tools-input.js @@ -9,52 +9,56 @@ initialize: function(app, options) { // link app this.app = app; - - // set text labels - this.text_enable = app.options.text_enable || 'Enable'; - this.text_disable = app.options.text_disable || 'Disable'; + + // set text labels and icons for optional button + this.text_enable = app.options.text_enable || 'Enable'; + this.text_disable = app.options.text_disable || 'Disable'; + this.cls_enable = app.options.cls_enable || 'fa fa-plus-square'; + this.cls_disable = app.options.cls_disable || 'fa fa-minus-square'; // link field this.field = options.field; this.default_value = options.default_value; - + // set element this.setElement(this._template(options)); - + // link elements this.$field = this.$el.find('.ui-table-form-field'); - this.$title_optional = this.$el.find('.ui-table-form-title-optional'); + this.$optional = this.$el.find('.ui-table-form-optional'); + this.$optional_icon = this.$el.find('.ui-table-form-optional').find('.icon'); this.$error_text = this.$el.find('.ui-table-form-error-text'); this.$error = this.$el.find('.ui-table-form-error'); - + // add field element this.$field.prepend(this.field.$el); - + // decide wether to expand or collapse optional fields this.field.skip = false; var v = this.field.value && this.field.value(); this.field.skip = Boolean(options.optional && - (v === null || v == this.default_value || - Number(v) == Number(this.default_value) || - JSON.stringify(v) == JSON.stringify(this.default_value))); + (v === null || v === '' || v === this.default_value || + String(v) === String(this.default_value) || + Number(v) === Number(this.default_value) || + JSON.stringify(v) === JSON.stringify(this.default_value))); // refresh view this._refresh(); - + // add optional hide/show var self = this; - this.$title_optional.on('click', function() { + this.$optional.on('click', function() { // flip flag self.field.skip = !self.field.skip; - + // refresh view self._refresh(); - + // refresh state self.app.trigger('refresh'); }); }, - + /** Set error text */ error: function(text) { @@ -62,27 +66,46 @@ this.$error.show(); this.$el.addClass('ui-error'); }, - + /** Reset this view */ reset: function() { this.$error.hide(); this.$el.removeClass('ui-error'); }, - + /** Refresh element */ _refresh: function() { + // reset optional button + this.$optional_icon.removeClass().addClass('icon'); + + // identify state if (!this.field.skip) { + // enable input field this.$field.fadeIn('fast'); - this.$title_optional.html(this.text_disable); + this._tooltip(this.text_disable, this.cls_disable); + } else { + // disable input field this.$field.hide(); - this.$title_optional.html(this.text_enable); + this._tooltip(this.text_enable, this.cls_enable); + // reset field value this.field.value && this.field.value(this.default_value); } }, - + + /** Set tooltip text + */ + _tooltip: function(title, cls) { + if (this.$optional.length) { + this.$optional_icon.addClass(cls) + .tooltip({ placement: 'bottom' }) + .attr('data-original-title', title) + .tooltip('fixTitle').tooltip('hide'); + } + }, + /** Main Template */ _template: function(options) { @@ -91,30 +114,34 @@ '<div class="ui-table-form-error ui-error">' + '<span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/>' + '</div>' + - '<div class="ui-table-form-title-strong">'; - + '<div class="ui-table-form-title">'; + // is optional if (options.optional) { - tmp += options.label + - '<span> [<span class="ui-table-form-title-optional"/>]</span>'; + tmp += '<div class="ui-table-form-optional">' + + '<i class="icon"/>' + options.label + + '</div>'; } else { - tmp += options.label; + tmp += options.label; } - + // finalize title tmp += '</div>' + '<div class="ui-table-form-field">'; + // add help + tmp += '<div class="ui-table-form-info">'; if (options.help) { - tmp += '<div class="ui-table-form-info">' + options.help + '</div>'; + tmp += options.help; } + tmp += '</div>'; // finalize tmp += '</div>' + '</div>'; - + // return input element return tmp; } }); -}); +}); \ No newline at end of file diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 client/galaxy/scripts/mvc/ui/ui-button-check.js --- a/client/galaxy/scripts/mvc/ui/ui-button-check.js +++ b/client/galaxy/scripts/mvc/ui/ui-button-check.js @@ -35,7 +35,7 @@ if (new_val !== undefined) { this.current = new_val; this.$el.removeClass() - .addClass('ui-checkbutton') + .addClass('ui-button-check') .addClass(this.options.icons[new_val]); this.options.onchange && this.options.onchange(new_val); } diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 client/galaxy/scripts/mvc/ui/ui-misc.js --- a/client/galaxy/scripts/mvc/ui/ui-misc.js +++ b/client/galaxy/scripts/mvc/ui/ui-misc.js @@ -447,7 +447,7 @@ _template: function(options) { var tmpl = '<div id="' + options.id + '" >'; if (options.info) { - tmpl += '<label>' + options.info + '</label>'; + tmpl += '<div>' + options.info + '</div>'; } tmpl += '<hidden value="' + options.value + '"/>' + '</div>'; diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/mvc/tools/tools-form-workflow.js --- a/static/scripts/mvc/tools/tools-form-workflow.js +++ b/static/scripts/mvc/tools/tools-form-workflow.js @@ -21,8 +21,8 @@ this.options = options; // set labels - this.options.text_enable = 'In Advance'; - this.options.text_disable = 'At Runtime'; + this.options.text_enable = 'Set in Advance'; + this.options.text_disable = 'Set at Runtime'; // configure workflow style this.options.is_dynamic = false; @@ -33,7 +33,7 @@ // declare fields as optional Utils.deepeach(options.inputs, function(item) { if (item.type) { - item.optional = (['data', 'data_hidden', 'hidden', 'drill_down', 'repeat', 'conditional']).indexOf(item.type) == -1; + item.optional = (['data', 'data_hidden', 'hidden', 'repeat', 'conditional']).indexOf(item.type) == -1; } }); diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/mvc/tools/tools-input.js --- a/static/scripts/mvc/tools/tools-input.js +++ b/static/scripts/mvc/tools/tools-input.js @@ -9,52 +9,56 @@ initialize: function(app, options) { // link app this.app = app; - - // set text labels - this.text_enable = app.options.text_enable || 'Enable'; - this.text_disable = app.options.text_disable || 'Disable'; + + // set text labels and icons for optional button + this.text_enable = app.options.text_enable || 'Enable'; + this.text_disable = app.options.text_disable || 'Disable'; + this.cls_enable = app.options.cls_enable || 'fa fa-plus-square'; + this.cls_disable = app.options.cls_disable || 'fa fa-minus-square'; // link field this.field = options.field; this.default_value = options.default_value; - + // set element this.setElement(this._template(options)); - + // link elements this.$field = this.$el.find('.ui-table-form-field'); - this.$title_optional = this.$el.find('.ui-table-form-title-optional'); + this.$optional = this.$el.find('.ui-table-form-optional'); + this.$optional_icon = this.$el.find('.ui-table-form-optional').find('.icon'); this.$error_text = this.$el.find('.ui-table-form-error-text'); this.$error = this.$el.find('.ui-table-form-error'); - + // add field element this.$field.prepend(this.field.$el); - + // decide wether to expand or collapse optional fields this.field.skip = false; var v = this.field.value && this.field.value(); this.field.skip = Boolean(options.optional && - (v === null || v == this.default_value || - Number(v) == Number(this.default_value) || - JSON.stringify(v) == JSON.stringify(this.default_value))); + (v === null || v === '' || v === this.default_value || + String(v) === String(this.default_value) || + Number(v) === Number(this.default_value) || + JSON.stringify(v) === JSON.stringify(this.default_value))); // refresh view this._refresh(); - + // add optional hide/show var self = this; - this.$title_optional.on('click', function() { + this.$optional.on('click', function() { // flip flag self.field.skip = !self.field.skip; - + // refresh view self._refresh(); - + // refresh state self.app.trigger('refresh'); }); }, - + /** Set error text */ error: function(text) { @@ -62,27 +66,46 @@ this.$error.show(); this.$el.addClass('ui-error'); }, - + /** Reset this view */ reset: function() { this.$error.hide(); this.$el.removeClass('ui-error'); }, - + /** Refresh element */ _refresh: function() { + // reset optional button + this.$optional_icon.removeClass().addClass('icon'); + + // identify state if (!this.field.skip) { + // enable input field this.$field.fadeIn('fast'); - this.$title_optional.html(this.text_disable); + this._tooltip(this.text_disable, this.cls_disable); + } else { + // disable input field this.$field.hide(); - this.$title_optional.html(this.text_enable); + this._tooltip(this.text_enable, this.cls_enable); + // reset field value this.field.value && this.field.value(this.default_value); } }, - + + /** Set tooltip text + */ + _tooltip: function(title, cls) { + if (this.$optional.length) { + this.$optional_icon.addClass(cls) + .tooltip({ placement: 'bottom' }) + .attr('data-original-title', title) + .tooltip('fixTitle').tooltip('hide'); + } + }, + /** Main Template */ _template: function(options) { @@ -91,30 +114,34 @@ '<div class="ui-table-form-error ui-error">' + '<span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/>' + '</div>' + - '<div class="ui-table-form-title-strong">'; - + '<div class="ui-table-form-title">'; + // is optional if (options.optional) { - tmp += options.label + - '<span> [<span class="ui-table-form-title-optional"/>]</span>'; + tmp += '<div class="ui-table-form-optional">' + + '<i class="icon"/>' + options.label + + '</div>'; } else { - tmp += options.label; + tmp += options.label; } - + // finalize title tmp += '</div>' + '<div class="ui-table-form-field">'; + // add help + tmp += '<div class="ui-table-form-info">'; if (options.help) { - tmp += '<div class="ui-table-form-info">' + options.help + '</div>'; + tmp += options.help; } + tmp += '</div>'; // finalize tmp += '</div>' + '</div>'; - + // return input element return tmp; } }); -}); +}); \ No newline at end of file diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/mvc/ui/ui-button-check.js --- a/static/scripts/mvc/ui/ui-button-check.js +++ b/static/scripts/mvc/ui/ui-button-check.js @@ -35,7 +35,7 @@ if (new_val !== undefined) { this.current = new_val; this.$el.removeClass() - .addClass('ui-checkbutton') + .addClass('ui-button-check') .addClass(this.options.icons[new_val]); this.options.onchange && this.options.onchange(new_val); } diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/mvc/ui/ui-misc.js --- a/static/scripts/mvc/ui/ui-misc.js +++ b/static/scripts/mvc/ui/ui-misc.js @@ -447,7 +447,7 @@ _template: function(options) { var tmpl = '<div id="' + options.id + '" >'; if (options.info) { - tmpl += '<label>' + options.info + '</label>'; + tmpl += '<div>' + options.info + '</div>'; } tmpl += '<hidden value="' + options.value + '"/>' + '</div>'; diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/packed/mvc/tools/tools-form-workflow.js --- a/static/scripts/packed/mvc/tools/tools-form-workflow.js +++ b/static/scripts/packed/mvc/tools/tools-form-workflow.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.post_job_actions=this.node.post_job_actions||{};this.options=e;this.options.text_enable="In Advance";this.options.text_disable="At Runtime";this.options.is_dynamic=false;this.options.narrow=true;this.options.initial_errors=true;this.options.cls_portlet="ui-portlet-narrow";b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","drill_down","repeat","conditional"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or note for this step. It will be shown with the workflow.",value:this.node.annotation};var f=this.node.output_terminals&&Object.keys(this.node.output_terminals)[0];if(f){d[b.uuid()]={name:"pja__"+f+"__EmailAction",label:"Email notification",type:"boolean",value:String(Boolean(this.post_job_actions["EmailAction"+f])),ignore:"false",help:"An email notification will be send when the job has completed.",payload:{host:window.location.host}};d[b.uuid()]={name:"pja__"+f+"__DeleteIntermediatesAction",label:"Output cleanup",type:"boolean",value:String(Boolean(this.post_job_actions["DeleteIntermediatesAction"+f])),ignore:"false",help:"Delete intermediate outputs if they are not used as input for another job."};for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:""});var f={label:"Add Actions: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"integer",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(e){var d=this;e={tool_id:this.options.id,tool_version:this.options.version,inputs:e};console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"api/workflows/build_module";b.request({type:"POST",url:f,data:e,success:function(h){d.node.update_field_data(h);d._errors(h&&h.tool_model);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}}); \ No newline at end of file +define(["utils/utils","mvc/tools/tools-form-base"],function(b,a){var c=a.extend({initialize:function(e){this.node=workflow.active_node;if(!this.node){console.debug("FAILED - tools-form-workflow:initialize() - Node not found in workflow.");return}this.post_job_actions=this.node.post_job_actions||{};this.options=e;this.options.text_enable="Set in Advance";this.options.text_disable="Set at Runtime";this.options.is_dynamic=false;this.options.narrow=true;this.options.initial_errors=true;this.options.cls_portlet="ui-portlet-narrow";b.deepeach(e.inputs,function(f){if(f.type){f.optional=(["data","data_hidden","hidden","repeat","conditional"]).indexOf(f.type)==-1}});b.deepeach(e.inputs,function(f){if(f.type){if(f.type=="conditional"){f.test_param.optional=false}}});var d=this;b.get({url:galaxy_config.root+"api/datatypes",cache:true,success:function(f){d.datatypes=f;d._makeSections(e.inputs);a.prototype.initialize.call(d,e)}})},_makeSections:function(d){d[b.uuid()]={label:"Annotation / Notes",name:"annotation",type:"text",area:true,help:"Add an annotation or note for this step. It will be shown with the workflow.",value:this.node.annotation};var f=this.node.output_terminals&&Object.keys(this.node.output_terminals)[0];if(f){d[b.uuid()]={name:"pja__"+f+"__EmailAction",label:"Email notification",type:"boolean",value:String(Boolean(this.post_job_actions["EmailAction"+f])),ignore:"false",help:"An email notification will be send when the job has completed.",payload:{host:window.location.host}};d[b.uuid()]={name:"pja__"+f+"__DeleteIntermediatesAction",label:"Output cleanup",type:"boolean",value:String(Boolean(this.post_job_actions["DeleteIntermediatesAction"+f])),ignore:"false",help:"Delete intermediate outputs if they are not used as input for another job."};for(var e in this.node.output_terminals){d[b.uuid()]=this._makeSection(e)}}},_makeSection:function(h){var g=[];for(key in this.datatypes){g.push({0:this.datatypes[key],1:this.datatypes[key]})}g.sort(function(j,i){return j.label>i.label?1:j.label<i.label?-1:0});g.unshift({0:"Sequences",1:"Sequences"});g.unshift({0:"Roadmaps",1:"Roadmaps"});g.unshift({0:"Leave unchanged",1:""});var f={label:"Add Actions: '"+h+"'",type:"section",inputs:[{action:"RenameDatasetAction",argument:"newname",label:"Rename dataset",type:"text",value:"",ignore:"",help:'This action will rename the result dataset. Click <a href="https://wiki.galaxyproject.org/Learn/AdvancedWorkflow/Variables">here</a> for more information.'},{action:"ChangeDatatypeAction",argument:"newtype",label:"Change datatype",type:"select",ignore:"",options:g,help:"This action will change the datatype of the output to the indicated value."},{action:"TagDatasetAction",argument:"tags",label:"Tags",type:"text",value:"",ignore:"",help:"This action will set tags for the dataset."},{label:"Assign columns",type:"section",inputs:[{action:"ColumnSetAction",argument:"chromCol",label:"Chrom column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"startCol",label:"Start column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"endCol",label:"End column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"strandCol",label:"Strand column",type:"integer",value:"",ignore:""},{action:"ColumnSetAction",argument:"nameCol",label:"Name column",type:"integer",value:"",ignore:""}],help:"This action will set column assignments in the output dataset. Blank fields are ignored."}]};var d=this;function e(n,o){o=o||[];o.push(n);for(var m in n.inputs){var k=n.inputs[m];if(k.action){k.name="pja__"+h+"__"+k.action;if(k.argument){k.name+="__"+k.argument}if(k.payload){for(var s in k.payload){var q=k.payload[s];k.payload[k.name+"__"+s]=q;delete q}}var r=d.post_job_actions[k.action+h];if(r){for(var l in o){o[l].expand=true}if(k.argument){k.value=r.action_arguments&&r.action_arguments[k.argument]||k.value}else{k.value="true"}}}if(k.inputs){e(k,o.slice(0))}}}e(f);return f},_buildModel:function(){Galaxy.modal.show({title:"Coming soon...",body:"This feature has not been implemented yet.",buttons:{Close:function(){Galaxy.modal.hide()}}})},_updateModel:function(e){var d=this;e={tool_id:this.options.id,tool_version:this.options.version,inputs:e};console.debug("tools-form-workflow::_refreshForm() - Refreshing states.");console.debug(e);var g=this.deferred.register();var f=galaxy_config.root+"api/workflows/build_module";b.request({type:"POST",url:f,data:e,success:function(h){d.node.update_field_data(h);d._errors(h&&h.tool_model);d.deferred.done(g);console.debug("tools-form::_refreshForm() - States refreshed.");console.debug(h)},error:function(h){d.deferred.done(g);console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(h)}})}});return{View:c}}); \ No newline at end of file diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/packed/mvc/tools/tools-input.js --- a/static/scripts/packed/mvc/tools/tools-input.js +++ b/static/scripts/packed/mvc/tools/tools-input.js @@ -1,1 +1,1 @@ -define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.text_enable=d.options.text_enable||"Enable";this.text_disable=d.options.text_disable||"Disable";this.field=c.field;this.default_value=c.default_value;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$title_optional=this.$el.find(".ui-table-form-title-optional");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&(b===null||b==this.default_value||Number(b)==Number(this.default_value)||JSON.stringify(b)==JSON.stringify(this.default_value)));this._refresh();var a=this;this.$title_optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh();a.app.trigger("refresh")})},error:function(a){this.$error_text.html(a);this.$error.show();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){if(!this.field.skip){this.$field.fadeIn("fast");this.$title_optional.html(this.text_disable)}else{this.$field.hide();this.$title_optional.html(this.text_enable);this.field.value&&this.field.value(this.default_value)}},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title-strong">';if(a.optional){b+=a.label+'<span> [<span class="ui-table-form-title-optional"/>]</span>'}else{b+=a.label}b+='</div><div class="ui-table-form-field">';if(a.help){b+='<div class="ui-table-form-info">'+a.help+"</div>"}b+="</div></div>";return b}})}); \ No newline at end of file +define([],function(){return Backbone.View.extend({initialize:function(d,c){this.app=d;this.text_enable=d.options.text_enable||"Enable";this.text_disable=d.options.text_disable||"Disable";this.cls_enable=d.options.cls_enable||"fa fa-plus-square";this.cls_disable=d.options.cls_disable||"fa fa-minus-square";this.field=c.field;this.default_value=c.default_value;this.setElement(this._template(c));this.$field=this.$el.find(".ui-table-form-field");this.$optional=this.$el.find(".ui-table-form-optional");this.$optional_icon=this.$el.find(".ui-table-form-optional").find(".icon");this.$error_text=this.$el.find(".ui-table-form-error-text");this.$error=this.$el.find(".ui-table-form-error");this.$field.prepend(this.field.$el);this.field.skip=false;var b=this.field.value&&this.field.value();this.field.skip=Boolean(c.optional&&(b===null||b===""||b===this.default_value||String(b)===String(this.default_value)||Number(b)===Number(this.default_value)||JSON.stringify(b)===JSON.stringify(this.default_value)));this._refresh();var a=this;this.$optional.on("click",function(){a.field.skip=!a.field.skip;a._refresh();a.app.trigger("refresh")})},error:function(a){this.$error_text.html(a);this.$error.show();this.$el.addClass("ui-error")},reset:function(){this.$error.hide();this.$el.removeClass("ui-error")},_refresh:function(){this.$optional_icon.removeClass().addClass("icon");if(!this.field.skip){this.$field.fadeIn("fast");this._tooltip(this.text_disable,this.cls_disable)}else{this.$field.hide();this._tooltip(this.text_enable,this.cls_enable);this.field.value&&this.field.value(this.default_value)}},_tooltip:function(b,a){if(this.$optional.length){this.$optional_icon.addClass(a).tooltip({placement:"bottom"}).attr("data-original-title",b).tooltip("fixTitle").tooltip("hide")}},_template:function(a){var b='<div class="ui-table-form-element"><div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"/></div><div class="ui-table-form-title">';if(a.optional){b+='<div class="ui-table-form-optional"><i class="icon"/>'+a.label+"</div>"}else{b+=a.label}b+='</div><div class="ui-table-form-field">';b+='<div class="ui-table-form-info">';if(a.help){b+=a.help}b+="</div>";b+="</div></div>";return b}})}); \ No newline at end of file diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/packed/mvc/ui/ui-button-check.js --- a/static/scripts/packed/mvc/ui/ui-button-check.js +++ b/static/scripts/packed/mvc/ui/ui-button-check.js @@ -1,1 +1,1 @@ -define(["utils/utils"],function(a){return Backbone.View.extend({optionsDefault:{icons:["fa fa-square-o","fa fa-minus-square-o","fa fa-check-square-o"],value:0},initialize:function(c){this.options=a.merge(c,this.optionsDefault);this.setElement($("<div/>"));this.value(this.options.value);var b=this;this.$el.on("click",function(){b.current=(!b.current&&2)||0;b.value(b.current);b.options.onclick&&b.options.onclick()})},value:function(b){if(b!==undefined){this.current=b;this.$el.removeClass().addClass("ui-checkbutton").addClass(this.options.icons[b]);this.options.onchange&&this.options.onchange(b)}return this.current}})}); \ No newline at end of file +define(["utils/utils"],function(a){return Backbone.View.extend({optionsDefault:{icons:["fa fa-square-o","fa fa-minus-square-o","fa fa-check-square-o"],value:0},initialize:function(c){this.options=a.merge(c,this.optionsDefault);this.setElement($("<div/>"));this.value(this.options.value);var b=this;this.$el.on("click",function(){b.current=(!b.current&&2)||0;b.value(b.current);b.options.onclick&&b.options.onclick()})},value:function(b){if(b!==undefined){this.current=b;this.$el.removeClass().addClass("ui-button-check").addClass(this.options.icons[b]);this.options.onchange&&this.options.onchange(b)}return this.current}})}); \ No newline at end of file diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/scripts/packed/mvc/ui/ui-misc.js --- a/static/scripts/packed/mvc/ui/ui-misc.js +++ b/static/scripts/packed/mvc/ui/ui-misc.js @@ -1,1 +1,1 @@ -define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-button-check","mvc/ui/ui-modal"],function(e,h,i,m,l,r,d,b){var q=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options))},_template:function(s){return'<img class="ui-image '+s.cls+'" src="'+s.url+'"/>'}});var j=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options))},title:function(s){this.$el.html(s)},_template:function(s){return'<label class="ui-label '+s.cls+'">'+s.title+"</label>"},value:function(){return options.title}});var c=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},_template:function(s){return'<div><span class="fa '+s.icon+'" class="ui-icon"/> '+s.title+"</div>"}});var g=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",function(){$(".tooltip").hide();if(s.onclick){s.onclick()}});$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},_template:function(s){var t='<button id="'+s.id+'" type="submit" style="float: '+s.floating+';" type="button" class="'+s.cls+'">';if(s.icon){t+='<i class="icon fa '+s.icon+'"></i> '}t+=s.title+"</button>";return t}});var o=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);this.setElement(this._template(this.options));this.$button=this.$el.find(".button");var s=this;$(this.el).on("click",function(){$(".tooltip").hide();if(t.onclick&&!s.disabled){t.onclick()}});$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled");this.disabled=true},enable:function(){this.$button.removeClass("disabled");this.disabled=false},setIcon:function(s){this.$("i").removeClass(this.options.icon).addClass(s);this.options.icon=s},_template:function(s){var t="";if(s.title){t="width: auto;"}var u='<div id="'+s.id+'" style="float: '+s.floating+"; "+t+'" class="'+s.cls+'">';if(s.title){u+='<div class="button"><i class="icon fa '+s.icon+'"/> <span class="title">'+s.title+"</span></div>"}else{u+='<i class="icon fa '+s.icon+'"/>'}u+="</div>";return u}});var p=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",s.onclick)},_template:function(s){return'<div><a href="javascript:void(0)" class="ui-anchor '+s.cls+'">'+s.title+"</a></div>"}});var a=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:false},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement("<div></div>");if(this.options.message){this.update(this.options)}},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options));this.$el.find(".alert").append(t.message);this.$el.fadeIn();if(this.timeout){window.clearTimeout(this.timeout)}if(!t.persistent){var s=this;this.timeout=window.setTimeout(function(){if(s.$el.is(":visible")){s.$el.fadeOut()}else{s.$el.hide()}},3000)}}else{this.$el.fadeOut()}},_template:function(s){return'<div class="ui-message alert alert-'+s.status+'"/>'}});var f=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault);this.setElement(this._template(this.options));var s=this;if(this.options.onclick){this.$el.on("submit",function(v){var u=s.$el.find("#search");s.options.onclick(u.val())})}},_template:function(s){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+s.searchword+'"><button type="submit" class="btn search-btn"><i class="fa fa-search"></i></button></form></div>'}});var n=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:false,visible:true,cls:"",area:false},initialize:function(t){this.options=e.merge(t,this.optionsDefault);this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}if(this.options.disabled){this.$el.prop("disabled",true)}if(!this.options.visible){this.$el.hide()}var s=this;this.$el.on("input",function(){if(s.options.onchange){s.options.onchange(s.$el.val())}})},value:function(s){if(s!==undefined){this.$el.val(s)}return this.$el.val()},_template:function(s){if(s.area){return'<textarea id="'+s.id+'" class="ui-textarea '+s.cls+'"></textarea>'}else{return'<input id="'+s.id+'" type="'+s.type+'" value="'+s.value+'" placeholder="'+s.placeholder+'" class="ui-input '+s.cls+'">'}}});var k=Backbone.View.extend({initialize:function(s){this.options=s;this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}},value:function(s){if(s!==undefined){this.$("hidden").val(s)}return this.$("hidden").val()},_template:function(t){var s='<div id="'+t.id+'" >';if(t.info){s+="<label>"+t.info+"</label>"}s+='<hidden value="'+t.value+'"/></div>';return s}});return{Anchor:p,Button:g,ButtonIcon:o,ButtonCheck:d,ButtonMenu:r,Icon:c,Image:q,Input:n,Label:j,Message:a,Modal:b,RadioButton:m.RadioButton,Checkbox:m.Checkbox,Radio:m.Radio,Searchbox:f,Select:h,Hidden:k,Slider:i,Drilldown:l}}); \ No newline at end of file +define(["utils/utils","mvc/ui/ui-select-default","mvc/ui/ui-slider","mvc/ui/ui-options","mvc/ui/ui-drilldown","mvc/ui/ui-button-menu","mvc/ui/ui-button-check","mvc/ui/ui-modal"],function(e,h,i,m,l,r,d,b){var q=Backbone.View.extend({optionsDefault:{url:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options))},_template:function(s){return'<img class="ui-image '+s.cls+'" src="'+s.url+'"/>'}});var j=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options))},title:function(s){this.$el.html(s)},_template:function(s){return'<label class="ui-label '+s.cls+'">'+s.title+"</label>"},value:function(){return options.title}});var c=Backbone.View.extend({optionsDefault:{floating:"right",icon:"",tooltip:"",placement:"bottom",title:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},_template:function(s){return'<div><span class="fa '+s.icon+'" class="ui-icon"/> '+s.title+"</div>"}});var g=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button btn btn-default",icon:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",function(){$(".tooltip").hide();if(s.onclick){s.onclick()}});$(this.el).tooltip({title:s.tooltip,placement:"bottom"})},_template:function(s){var t='<button id="'+s.id+'" type="submit" style="float: '+s.floating+';" type="button" class="'+s.cls+'">';if(s.icon){t+='<i class="icon fa '+s.icon+'"></i> '}t+=s.title+"</button>";return t}});var o=Backbone.View.extend({optionsDefault:{id:null,title:"",floating:"right",cls:"ui-button-icon",icon:"",tooltip:"",onclick:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);this.setElement(this._template(this.options));this.$button=this.$el.find(".button");var s=this;$(this.el).on("click",function(){$(".tooltip").hide();if(t.onclick&&!s.disabled){t.onclick()}});$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},disable:function(){this.$button.addClass("disabled");this.disabled=true},enable:function(){this.$button.removeClass("disabled");this.disabled=false},setIcon:function(s){this.$("i").removeClass(this.options.icon).addClass(s);this.options.icon=s},_template:function(s){var t="";if(s.title){t="width: auto;"}var u='<div id="'+s.id+'" style="float: '+s.floating+"; "+t+'" class="'+s.cls+'">';if(s.title){u+='<div class="button"><i class="icon fa '+s.icon+'"/> <span class="title">'+s.title+"</span></div>"}else{u+='<i class="icon fa '+s.icon+'"/>'}u+="</div>";return u}});var p=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement(this._template(this.options));$(this.el).on("click",s.onclick)},_template:function(s){return'<div><a href="javascript:void(0)" class="ui-anchor '+s.cls+'">'+s.title+"</a></div>"}});var a=Backbone.View.extend({optionsDefault:{message:null,status:"info",persistent:false},initialize:function(s){this.options=e.merge(s,this.optionsDefault);this.setElement("<div></div>");if(this.options.message){this.update(this.options)}},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options));this.$el.find(".alert").append(t.message);this.$el.fadeIn();if(this.timeout){window.clearTimeout(this.timeout)}if(!t.persistent){var s=this;this.timeout=window.setTimeout(function(){if(s.$el.is(":visible")){s.$el.fadeOut()}else{s.$el.hide()}},3000)}}else{this.$el.fadeOut()}},_template:function(s){return'<div class="ui-message alert alert-'+s.status+'"/>'}});var f=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault);this.setElement(this._template(this.options));var s=this;if(this.options.onclick){this.$el.on("submit",function(v){var u=s.$el.find("#search");s.options.onclick(u.val())})}},_template:function(s){return'<div class="ui-search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+s.searchword+'"><button type="submit" class="btn search-btn"><i class="fa fa-search"></i></button></form></div>'}});var n=Backbone.View.extend({optionsDefault:{type:"text",placeholder:"",disabled:false,visible:true,cls:"",area:false},initialize:function(t){this.options=e.merge(t,this.optionsDefault);this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}if(this.options.disabled){this.$el.prop("disabled",true)}if(!this.options.visible){this.$el.hide()}var s=this;this.$el.on("input",function(){if(s.options.onchange){s.options.onchange(s.$el.val())}})},value:function(s){if(s!==undefined){this.$el.val(s)}return this.$el.val()},_template:function(s){if(s.area){return'<textarea id="'+s.id+'" class="ui-textarea '+s.cls+'"></textarea>'}else{return'<input id="'+s.id+'" type="'+s.type+'" value="'+s.value+'" placeholder="'+s.placeholder+'" class="ui-input '+s.cls+'">'}}});var k=Backbone.View.extend({initialize:function(s){this.options=s;this.setElement(this._template(this.options));if(this.options.value!==undefined){this.value(this.options.value)}},value:function(s){if(s!==undefined){this.$("hidden").val(s)}return this.$("hidden").val()},_template:function(t){var s='<div id="'+t.id+'" >';if(t.info){s+="<div>"+t.info+"</div>"}s+='<hidden value="'+t.value+'"/></div>';return s}});return{Anchor:p,Button:g,ButtonIcon:o,ButtonCheck:d,ButtonMenu:r,Icon:c,Image:q,Input:n,Label:j,Message:a,Modal:b,RadioButton:m.RadioButton,Checkbox:m.Checkbox,Radio:m.Radio,Searchbox:f,Select:h,Hidden:k,Slider:i,Drilldown:l}}); \ No newline at end of file diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/style/blue/base.css --- a/static/style/blue/base.css +++ b/static/style/blue/base.css @@ -148,7 +148,7 @@ .form-control::-moz-placeholder{color:#999} .form-control:-ms-input-placeholder{color:#999} .form-control::-webkit-input-placeholder{color:#999} -.form-control,.ui-input,.ui-textarea,.ui-options .ui-options-list,.ui-form-slider .ui-form-slider-text,.ui-select-multiple{display:block;width:100%;height:27px;padding:4px 10px;font-size:12px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #aaa;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)} +.form-control{display:block;width:100%;height:27px;padding:4px 10px;font-size:12px;line-height:1.428571429;color:#555;vertical-align:middle;background-color:#fff;border:1px solid #aaa;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);-webkit-transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s;transition:border-color ease-in-out .15s, box-shadow ease-in-out .15s}.form-control:focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6)} .form-control[disabled],.form-control[readonly],fieldset[disabled] .form-control{cursor:not-allowed;background-color:#eee} textarea.form-control{height:auto} .form-group{margin-bottom:15px} @@ -1414,11 +1414,10 @@ .ui-table tbody,.ui-table-plain tbody{cursor:pointer} .ui-table-plain{table-layout:fixed}.ui-table-plain tbody{cursor:auto !important}.ui-table-plain tbody td{padding:0px !important;border:none !important} .ui-table-plain .ui-table-section{border-left:solid 3px #ebd9b2;border-radius:5px !important;margin-bottom:5px;padding-left:10px} -.ui-table-form-element{margin-top:5px;margin-bottom:5px;overflow:hidden}.ui-table-form-element .ui-table-form-title-optional{font-weight:bold;text-decoration:underline;cursor:pointer} +.ui-table-form-element{margin-top:5px;margin-bottom:5px;overflow:visible}.ui-table-form-element .ui-table-form-title{font-weight:bold}.ui-table-form-element .ui-table-form-title .ui-table-form-optional{cursor:pointer}.ui-table-form-element .ui-table-form-title .ui-table-form-optional .icon{margin-right:5px;font-size:1.2em} .ui-table-form-element .ui-table-form-field{margin-top:5px} -.ui-table-form-title-strong{font-weight:bold} +.ui-table-form-separator{font-weight:bold;font-size:0.9em} .ui-table-form-info{clear:both !important} -.ui-table-form-separator{font-weight:bold;font-size:0.9em} .ui-table-form-error{display:none}.ui-table-form-error .ui-table-form-error-text{padding-left:5px} .ui-portlet,.ui-portlet-repeat,.ui-portlet-limited,.ui-portlet-section,.ui-portlet-narrow,.ui-portlet-repeat,.ui-portlet-limited,.ui-portlet-section,.ui-portlet-narrow{border:solid #d6b161 1px;border-radius:3px;position:relative;clear:both;width:auto;height:100%}.ui-portlet .portlet-header,.ui-portlet-limited .portlet-header,.ui-portlet-narrow .portlet-header{background:#ebd9b2;border-bottom:solid #d6b161 1px;padding:2px 8px;overflow:visible;float:right;width:100%}.ui-portlet .portlet-header .portlet-title,.ui-portlet-limited .portlet-header .portlet-title,.ui-portlet-narrow .portlet-header .portlet-title{display:inline;vertical-align:middle}.ui-portlet .portlet-header .portlet-title .portlet-title-text,.ui-portlet-limited .portlet-header .portlet-title .portlet-title-text,.ui-portlet-narrow .portlet-header .portlet-title .portlet-title-text{vertical-align:middle;line-height:22px} .ui-portlet .portlet-header .portlet-title .icon,.ui-portlet-limited .portlet-header .portlet-title .icon,.ui-portlet-narrow .portlet-header .portlet-title .icon{font-size:1.2em;vertical-align:middle} @@ -1435,7 +1434,7 @@ .ui-portlet-limited,.ui-portlet-narrow,.ui-portlet-narrow{max-width:900px} .ui-popover{max-width:700px;display:none}.ui-popover .popover-close{position:absolute;right:10px;top:7px;font-size:1.2em;cursor:pointer} .ui-popover .popover-title{padding:4px 10px} -.ui-input,.ui-textarea,.ui-options .ui-options-list,.ui-form-slider .ui-form-slider-text,.ui-select-multiple,.ui-textarea,.ui-options .ui-options-list,.ui-form-slider .ui-form-slider-text,.ui-select-multiple{background:transparent} +.ui-input,.ui-textarea,.ui-options .ui-options-list,.ui-form-slider .ui-form-slider-text,.ui-select-multiple{width:100%;display:block;height:27px;padding:4px 10px;font-size:12px;line-height:1.428571429;color:#555;border:1px solid #aaa;border-radius:3px;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.ui-input[disabled],.ui-input[readonly],fieldset[disabled] .ui-input{cursor:not-allowed;background-color:#eee} .ui-textarea{height:100px !important} .ui-options .ui-options-list{height:100% !important}.ui-options .ui-options-list input[type=checkbox],.ui-options .ui-options-list input[type=radio]{display:none} .ui-options .ui-options-list label{margin:0px;cursor:pointer} @@ -1448,15 +1447,15 @@ .ui-form-slider .ui-form-slider-element{width:calc(100% - 110px);float:left;top:8px;left:10px} .ui-radiobutton{width:100%}.ui-radiobutton label{height:23px;line-height:1em} .ui-radiobutton i{padding-right:5px} -.ui-checkbutton{font-size:1.2em;width:1.2em;cursor:pointer} +.ui-button-check{font-size:1.2em;width:1.2em;cursor:pointer} .ui-select{position:relative}.ui-select .button{position:absolute;top:5px;right:5px} .ui-select .select2-container{width:100%} .ui-select select{position:relative;top:0px;height:27px;width:100%;padding-left:5px;padding-right:20px;cursor:pointer;background:transparent;-webkit-appearance:none;border:1px solid #bfbfbf;-moz-border-radius:3px;border-radius:3px} .ui-select-content .ui-options{float:left;padding-top:2px} .ui-color-picker .ui-color-picker-header{cursor:pointer} -.ui-color-picker .ui-color-picker-value{float:left;border-radius:3px;border:solid 1px #000000;width:12px;height:12px;margin-bottom:10px;margin-right:5px} +.ui-color-picker .ui-color-picker-value{float:left;border-radius:3px;border:solid 1px #000000;width:12px;height:12px;margin-right:5px} .ui-color-picker .ui-color-picker-label{float:left;line-height:1.2em} -.ui-color-picker .ui-color-picker-view{display:none;float:left;overflow:auto;height:100%}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel{width:210px}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel .ui-color-picker-content{margin-bottom:15px}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel .ui-color-picker-content .label{padding-bottom:2px} +.ui-color-picker .ui-color-picker-view{height:100%;overflow:auto;display:none;float:left;margin-top:5px}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel{width:210px}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel .ui-color-picker-content{margin-bottom:15px}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel .ui-color-picker-content .label{padding-bottom:2px} .ui-color-picker .ui-color-picker-view .ui-color-picker-panel .ui-color-picker-content .line .ui-color-picker-box{cursor:pointer;float:left;margin-right:5px;border:solid 1px #c0c0c0;width:15px;height:15px;border-radius:2px}.ui-color-picker .ui-color-picker-view .ui-color-picker-panel .ui-color-picker-content .line .ui-color-picker-box .ui-color-picker-check{color:black;font-size:1.2em;position:relative;left:1px} .libraryRow{background-color:#ebd9b2} .datasetHighlighted{background-color:#f9f9f9} diff -r af7603a13e8d5340f064312808b6ebfb56d1a959 -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 static/style/src/less/ui.less --- a/static/style/src/less/ui.less +++ b/static/style/src/less/ui.less @@ -57,7 +57,10 @@ height: auto !important; ul { i { - font-size: 1.2em; margin-right: @ui-margin-horizontal; position: relative; top: 1px; + font-size: 1.2em; + margin-right: @ui-margin-horizontal; + position: relative; + top: 1px; } } .button { @@ -142,26 +145,22 @@ // table form elements .ui-table-form-element { - .ui-table-form-title-optional { + .ui-table-form-title { font-weight: bold; - text-decoration: underline; - cursor: pointer; + .ui-table-form-optional { + cursor: pointer; + .icon { + margin-right: 5px; + font-size: 1.2em; + } + } } .ui-table-form-field { margin-top: @ui-margin-vertical; } margin-top: @ui-margin-vertical; margin-bottom: @ui-margin-vertical; - overflow: hidden; -} - -.ui-table-form-title-strong { - font-weight: bold; -} - -.ui-table-form-info { - &:extend(.toolParamHelp); - clear: both !important; + overflow: visible; } .ui-table-form-separator { @@ -169,6 +168,11 @@ font-size: 0.9em; } +.ui-table-form-info { + &:extend(.toolParamHelp); + clear: both !important; +} + .ui-table-form-error { display: none; .ui-table-form-error-text { @@ -312,8 +316,22 @@ // input elements .ui-input { - &:extend(.form-control); - background: transparent; + width: 100%; + display: block; + height: @input-height-base; + padding: @padding-base-vertical @padding-base-horizontal; + font-size: @font-size-base; + line-height: @line-height-base; + color: @input-color; + border: 1px solid @input-border; + border-radius: @input-border-radius; + .box-shadow(inset 0 1px 1px rgba(0,0,0,.075)); + &[disabled], + &[readonly], + fieldset[disabled] & { + cursor: not-allowed; + background-color: @input-bg-disabled; + } } .ui-textarea { @@ -370,7 +388,6 @@ } } - .ui-form-slider { display: inline-block; width: 100%; @@ -400,7 +417,7 @@ } } -.ui-checkbutton { +.ui-button-check { font-size: 1.2em; width: 1.2em; cursor: pointer; @@ -453,7 +470,6 @@ border: solid 1px #000000; width: 12px; height: 12px; - margin-bottom: 10px; margin-right: 5px; } .ui-color-picker-label { @@ -465,6 +481,7 @@ overflow: auto; display: none; float: left; + margin-top: 5px; .ui-color-picker-panel { width: 210px; .ui-color-picker-content { https://bitbucket.org/galaxy/galaxy-central/commits/4589eb71e192/ Changeset: 4589eb71e192 User: dannon Date: 2015-02-16 20:09:42+00:00 Summary: Bump SQLAlchemy all the way to 0.9.8 Affected #: 1 file diff -r 4909df6a1dbde9ece5f8b5dfd0bbe03597826893 -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 eggs.ini --- a/eggs.ini +++ b/eggs.ini @@ -26,7 +26,7 @@ pysqlite = 2.5.6 python_lzo = 1.08_2.03_static PyYAML = 3.10 -SQLAlchemy = 0.8.7 +SQLAlchemy = 0.9.8 ; msgpack_python = 0.2.4 [eggs:noplatform] https://bitbucket.org/galaxy/galaxy-central/commits/d004eb0d8be7/ Changeset: d004eb0d8be7 User: dannon Date: 2015-02-17 12:26:52+00:00 Summary: Merge. Affected #: 20 files diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 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 @@ -205,6 +205,11 @@ if( this.get( 'deleted' ) ){ return jQuery.when(); } return this.save( { deleted: true }, options ); }, + /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */ + purge : function( options ){ + if( this.get( 'purged' ) ){ return jQuery.when(); } + return this.save( { purged: true }, options ); + }, /** save this history, _Mark_ing it as undeleted */ undelete : function( options ){ if( !this.get( 'deleted' ) ){ return jQuery.when(); } diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 client/galaxy/scripts/mvc/history/multi-panel.js --- a/client/galaxy/scripts/mvc/history/multi-panel.js +++ b/client/galaxy/scripts/mvc/history/multi-panel.js @@ -128,12 +128,9 @@ /** set up passed-in panel (if any) and listeners */ initialize : function initialize( options ){ options = options || {}; + this.purgeAllowed = !_.isUndefined( options.purgeAllowed )? options.purgeAllowed: false; + this.panel = options.panel || this.createPanel( options ); - //this.log( this + '.init', options ); - // if model, set up model - // create panel sub-view -//TODO: use current-history-panel for current - this.panel = options.panel || this.createPanel( options ); this.setUpListeners(); }, @@ -143,6 +140,7 @@ model : this.model, //el : this.$panel(), // non-current panels should set their hdas to draggable + purgeAllowed: this.purgeAllowed, dragItems : true }, panelOptions ); //this.log( 'panelOptions:', panelOptions ); @@ -245,9 +243,9 @@ }); return $([ '<div class="panel-controls clear flex-row">', - this.controlsLeftTemplate( data ), + this.controlsLeftTemplate({ history: data, view: this }), //'<button class="btn btn-default">Herp</button>', - this.controlsRightTemplate( data ), + this.controlsRightTemplate({ history: data, view: this }), '</div>', '<div class="inner flex-row flex-column-container">', '<div id="history-', data.id, '" class="history-column history-panel flex-column"></div>', @@ -317,24 +315,24 @@ /** controls template displaying controls above the panel based on this.currentHistory */ controlsLeftTemplate : _.template([ '<div class="pull-left">', - '<% if( history.isCurrentHistory ){ %>', + '<% if( data.history.isCurrentHistory ){ %>', '<strong class="current-label">', _l( 'Current History' ), '</strong>', '<% } else { %>', '<button class="switch-to btn btn-default">', _l( 'Switch to' ), '</button>', '<% } %>', '</div>' - ].join( '' ), { variable : 'history' }), + ].join( '' ), { variable : 'data' }), /** controls template displaying controls above the panel based on this.currentHistory */ controlsRightTemplate : _.template([ '<div class="pull-right">', - '<% if( !history.purged ){ %>', + '<% if( !data.history.purged ){ %>', '<div class="panel-menu btn-group">', '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">', '<span class="caret"></span>', '</button>', '<ul class="dropdown-menu pull-right" role="menu">', - '<% if( !history.deleted ){ %>', + '<% if( !data.history.deleted ){ %>', '<li><a href="javascript:void(0);" class="copy-history">', _l( 'Copy' ), '</a></li>', @@ -349,14 +347,16 @@ _l( 'Undelete' ), '</a></li>', '<% } %>', - //'<li><a href="javascript:void(0);" class="purge-history">', - // _l( 'Purge' ), - //'</a></li>', + '<% if( data.view.purgeAllowed ){ %>', + '<li><a href="javascript:void(0);" class="purge-history">', + _l( 'Purge' ), + '</a></li>', + '<% } %>', '</ul>', '<% } %>', '</div>', '</div>' - ].join( '' ), { variable: 'history' }), + ].join( '' ), { variable: 'data' }), // ------------------------------------------------------------------------ misc /** String rep */ @@ -491,7 +491,7 @@ // handle setting a history as current, triggered by history.setAsCurrent 'set-as-current': multipanel.setCurrentHistory, // handle deleting a history (depends on whether panels is including deleted or not) - 'change:deleted': multipanel.handleDeletedHistory, + 'change:deleted change:purged': multipanel.handleDeletedHistory, 'sort' : function(){ multipanel.renderColumns( 0 ); } }); @@ -519,7 +519,7 @@ * based on collection.includeDeleted */ handleDeletedHistory : function handleDeletedHistory( history ){ - if( history.get( 'deleted' ) ){ + if( history.get( 'deleted' ) || history.get( 'purged' ) ){ this.log( 'handleDeletedHistory', this.collection.includeDeleted, history ); var multipanel = this; column = multipanel.columnMap[ history.id ]; @@ -584,7 +584,10 @@ /** create a column and its panel and set up any listeners to them */ createColumn : function createColumn( history, options ){ // options passed can be re-used, so extend them before adding the model to prevent pollution for the next - options = _.extend( {}, options, { model: history }); + options = _.extend( {}, options, { + model : history, + purgeAllowed: Galaxy.config.allow_user_dataset_purge + }); var column = new HistoryPanelColumn( options ); if( history.id === this.currentHistoryId ){ column.currentHistory = true; } this.setUpColumnListeners( column ); @@ -1047,21 +1050,19 @@ mainTemplate : _.template([ '<div class="header flex-column-container">', '<div class="control-column control-column-left flex-column">', - '<button class="create-new btn btn-default">', _l( 'Create new' ), '</button> ', + '<button class="create-new btn btn-default" tabindex="4">', _l( 'Create new' ), '</button> ', '<div id="search-histories" class="search-control"></div>', '<div id="search-datasets" class="search-control"></div>', - '<button class="open-more-options btn btn-default">', - //TODO: tip not working - '<span class="fa fa-ellipsis-h" title="More options"></span>', - '</button>', + '<a class="open-more-options btn btn-default" tabindex="3">', + '<span class="fa fa-ellipsis-h"></span>', + '</a>', '</div>', // feedback '<div class="control-column control-column-center flex-column">', - '<div class="header-info">', - '</div>', + '<div class="header-info">', '</div>', '</div>', '<div class="control-column control-column-right flex-column">', - '<button class="done btn btn-default">', _l( 'Done' ), '</button>', + '<button class="done btn btn-default" tabindex="1">', _l( 'Done' ), '</button>', '</div>', '</div>', // middle - where the columns go diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 config/plugins/visualizations/scatterplot/templates/scatterplot.mako --- a/config/plugins/visualizations/scatterplot/templates/scatterplot.mako +++ b/config/plugins/visualizations/scatterplot/templates/scatterplot.mako @@ -36,73 +36,75 @@ 'mvc/visualization/visualization-model' )} ${h.javascript_link( root + 'plugins/visualizations/scatterplot/static/scatterplot-edit.js' )} + +<script type="text/javascript"> +function getModel(){ + return new ScatterplotModel({ + id : ${h.dumps( visualization_id )} || undefined, + title : "${title}", + config : ${h.dumps( config, indent=2 )} + }); +} +function getHDAJSON(){ + return ${h.dumps( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )}; +} +</script> + </head> ## ---------------------------------------------------------------------------- <body> -%if embedded and saved_visualization: -<figcaption> - <span class="title">${title}</span> - <span class="title-info">${info}</span> -</figcaption> -<figure class="scatterplot-display"></div> + %if embedded and saved_visualization: + <figcaption> + <span class="title">${title}</span> + <span class="title-info">${info}</span> + </figcaption> + <figure class="scatterplot-display"></figure> -<script type="text/javascript"> -$(function(){ - var model = new ScatterplotModel({ - id : ${h.dumps( visualization_id )} || undefined, - title : "${title}", - config : ${h.dumps( config, indent=2 )} + <script type="text/javascript"> + $(function(){ + var display = new ScatterplotDisplay({ + el : $( '.scatterplot-display' ).attr( 'id', 'scatterplot-display-' + '${visualization_id}' ), + model : getModel(), + dataset : getHDAJSON(), + embedded: "${embedded}" + }).render(); + display.fetchData(); + //window.model = model; + //window.display = display; }); - hdaJson = ${h.dumps( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )}, - display = new ScatterplotDisplay({ - el : $( '.scatterplot-display' ).attr( 'id', 'scatterplot-display-' + '${visualization_id}' ), - model : model, - dataset : hdaJson, - embedded: "${embedded}" - }).render(); - display.fetchData(); - //window.model = model; - //window.display = display; -}); + </script> -</script> + %else: + <div class="chart-header"> + <h2>${title or default_title}</h2> + <p>${info}</p> + </div> -%else: -<div class="chart-header"> - <h2>${title or default_title}</h2> - <p>${info}</p> -</div> + <div class="scatterplot-editor"></div> + <script type="text/javascript"> + $(function(){ + var model = getModel(), + hdaJSON = getHDAJSON(), + editor = new ScatterplotConfigEditor({ + el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hdaJSON.id ), + model : getModel(), + dataset : hdaJSON + }).render(); + window.editor = editor; -<div class="scatterplot-editor"></div> -<script type="text/javascript"> -$(function(){ - var model = new ScatterplotModel({ - id : ${h.dumps( visualization_id )} || undefined, - title : "${title or default_title}", - config : ${h.dumps( config, indent=2 )} - }), - hdaJson = ${h.dumps( trans.security.encode_dict_ids( hda.to_dict() ), indent=2 )}, - editor = new ScatterplotConfigEditor({ - el : $( '.scatterplot-editor' ).attr( 'id', 'scatterplot-editor-hda-' + hdaJson.id ), - model : model, - dataset : hdaJson - }).render(); - window.editor = editor; - - $( '.chart-header h2' ).click( function(){ - var returned = prompt( 'Enter a new title:' ); - if( returned ){ - model.set( 'title', returned ); - } - }); - model.on( 'change:title', function(){ - $( '.chart-header h2' ).text( model.get( 'title' ) ); - document.title = model.get( 'title' ) + ' | ' + '${visualization_display_name}'; - }) -}); - -</script> -%endif + $( '.chart-header h2' ).click( function(){ + var returned = prompt( 'Enter a new title:' ); + if( returned ){ + model.set( 'title', returned ); + } + }); + model.on( 'change:title', function(){ + $( '.chart-header h2' ).text( model.get( 'title' ) ); + document.title = model.get( 'title' ) + ' | ' + '${visualization_display_name}'; + }) + }); + </script> + %endif </body> diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/datatypes/dataproviders/column.py --- a/lib/galaxy/datatypes/dataproviders/column.py +++ b/lib/galaxy/datatypes/dataproviders/column.py @@ -116,8 +116,8 @@ self.column_filters.append( parsed ) def parse_filter( self, filter_param_str ): - split = filter_param_str.split( '-', 3 ) - if not len( split ) == 3: + split = filter_param_str.split( '-', 2 ) + if not len( split ) >= 3: return None column, op, val = split diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/managers/deletable.py --- a/lib/galaxy/managers/deletable.py +++ b/lib/galaxy/managers/deletable.py @@ -105,7 +105,7 @@ return item.purged if new_purged: self.manager.purge( trans, item, flush=False ) - return self.purged + return item.purged class PurgableFiltersMixin( DeletableFiltersMixin ): diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/managers/histories.py --- a/lib/galaxy/managers/histories.py +++ b/lib/galaxy/managers/histories.py @@ -260,7 +260,7 @@ 'model_class', 'name', 'deleted', - #'purged', + 'purged', #'count' 'url', #TODO: why these? diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/tools/parameters/basic.py --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -965,7 +965,7 @@ # Old style dynamic options, no dependency information so there isn't # a lot we can do: if we're dealing with workflows, have to assume # late validation no matter what. - if (self.dynamic_options is not None or self.is_dynamic is not None) and ( trans is None or trans.workflow_building_mode ): + if self.dynamic_options is not None and ( trans is None or trans.workflow_building_mode ): return True # If we got this far, we can actually look at the dependencies # to see if their values will not be available until runtime. diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/webapps/galaxy/api/configuration.py --- a/lib/galaxy/webapps/galaxy/api/configuration.py +++ b/lib/galaxy/webapps/galaxy/api/configuration.py @@ -63,11 +63,11 @@ self.add_view( 'all', self.serializers.keys() ) def default_serializer( self, trans, config, key ): - return config.get( key, None ) + return getattr( config, key, None ) def add_serializers( self ): def _defaults_to( default ): - return lambda t, i, k: i.get( k, default ) + return lambda t, i, k: getattr( i, k, default ) self.serializers = { #TODO: this is available from user data, remove @@ -90,7 +90,6 @@ 'biostar_url_redirect' : lambda *a: self.url_for( controller='biostar', action='biostar_redirect', qualified=True ), - 'allow_user_creation' : _defaults_to( False ), 'use_remote_user' : _defaults_to( None ), 'remote_user_logout_href' : _defaults_to( '' ), 'enable_cloud_launch' : _defaults_to( False ), @@ -111,7 +110,7 @@ def add_serializers( self ): super( AdminConfigSerializer, self ).add_serializers() def _defaults_to( default ): - return lambda t, i, k: i.get( k, default ) + return lambda t, i, k: getattr( i, k, default ) self.serializers.update({ #TODO: this is available from user data, remove diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/webapps/galaxy/api/histories.py --- a/lib/galaxy/webapps/galaxy/api/histories.py +++ b/lib/galaxy/webapps/galaxy/api/histories.py @@ -259,23 +259,23 @@ :type id: str :param id: the encoded id of the history to delete :type kwd: dict - :param kwd: (optional) dictionary structure containing: + :param kwd: (optional) dictionary structure containing extra parameters - * payload: a dictionary itself containing: - * purge: if True, purge the history and all of its HDAs + You can purge a history, removing all it's datasets from disk (if unshared), + by passing in ``purge=True`` in the url. :param keys: same as the use of `keys` in the `index` function above :param view: same as the use of `view` in the `index` function above :rtype: dict - :returns: an error object if an error occurred or a dictionary containing: - * id: the encoded id of the history, - * deleted: if the history was marked as deleted, - * purged: if the history was purged + :returns: the deleted or purged history """ history_id = id # a request body is optional here purge = False + if 'purge' in kwd: + purge = string_as_bool( kwd.get( 'purge' ) ) + # for backwards compat, keep the payload sub-dictionary if kwd.get( 'payload', None ): purge = string_as_bool( kwd['payload'].get( 'purge', False ) ) diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/webapps/galaxy/controllers/visualization.py --- a/lib/galaxy/webapps/galaxy/controllers/visualization.py +++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py @@ -801,7 +801,6 @@ raise HTTPNotFound( 'No visualization registry (possibly disabled in galaxy.ini)' ) if visualization_name not in registry.plugins: raise HTTPNotFound( 'Unknown or invalid visualization: ' + visualization_name ) - # or redirect to list? plugin = registry.plugins[ visualization_name ] returned = None @@ -824,15 +823,21 @@ # look up template and render template_path = plugin.config[ 'template' ] returned = registry.fill_template( trans, plugin, template_path, - visualization_name=visualization_name, visualization_display_name=visualization_display_name, - title=title, saved_visualization=visualization, visualization_id=encoded_visualization_id, - embedded=embedded, query=kwargs, vars={}, config=config, **resources ) - #NOTE: passing *unparsed* kwargs as query - #NOTE: vars is a dictionary for shared data in the template - # this feels hacky to me but it's what mako recommends: - # http://docs.makotemplates.org/en/latest/runtime.html - #TODO: should vars contain all the passed in arguments? is that even necessary? - #TODO: embedded + visualization_name=visualization_name, + visualization_display_name=visualization_display_name, + title=title, + saved_visualization=visualization, + visualization_id=encoded_visualization_id, + embedded=embedded, + #NOTE: passing *unparsed* kwargs as query + query=kwargs, + #NOTE: vars is a dictionary for shared data in the template + # this feels hacky to me but it's what mako recommends: + # http://docs.makotemplates.org/en/latest/runtime.html + vars={}, + config=config, + **resources + ) except Exception, exception: log.exception( 'error rendering visualization (%s): %s', visualization_name, str( exception ) ) diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 lib/galaxy/webapps/galaxy/controllers/workflow.py --- a/lib/galaxy/webapps/galaxy/controllers/workflow.py +++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py @@ -652,9 +652,6 @@ trans.workflow_building_mode = True module = module_factory.new( trans, type, **kwargs ) tool_model = None - if type == 'tool': - tool_model = module.tool.to_json(trans, is_dynamic=False) - module.state.inputs = copy.deepcopy(tool_model['state_inputs']) return { 'type': module.type, 'name': module.get_name(), diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/scripts/mvc/history/history-model.js --- a/static/scripts/mvc/history/history-model.js +++ b/static/scripts/mvc/history/history-model.js @@ -205,6 +205,11 @@ if( this.get( 'deleted' ) ){ return jQuery.when(); } return this.save( { deleted: true }, options ); }, + /** purge this history, _Mark_ing it as purged and removing all dataset data from the server */ + purge : function( options ){ + if( this.get( 'purged' ) ){ return jQuery.when(); } + return this.save( { purged: true }, options ); + }, /** save this history, _Mark_ing it as undeleted */ undelete : function( options ){ if( !this.get( 'deleted' ) ){ return jQuery.when(); } diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/scripts/mvc/history/multi-panel.js --- a/static/scripts/mvc/history/multi-panel.js +++ b/static/scripts/mvc/history/multi-panel.js @@ -128,12 +128,9 @@ /** set up passed-in panel (if any) and listeners */ initialize : function initialize( options ){ options = options || {}; + this.purgeAllowed = !_.isUndefined( options.purgeAllowed )? options.purgeAllowed: false; + this.panel = options.panel || this.createPanel( options ); - //this.log( this + '.init', options ); - // if model, set up model - // create panel sub-view -//TODO: use current-history-panel for current - this.panel = options.panel || this.createPanel( options ); this.setUpListeners(); }, @@ -143,6 +140,7 @@ model : this.model, //el : this.$panel(), // non-current panels should set their hdas to draggable + purgeAllowed: this.purgeAllowed, dragItems : true }, panelOptions ); //this.log( 'panelOptions:', panelOptions ); @@ -245,9 +243,9 @@ }); return $([ '<div class="panel-controls clear flex-row">', - this.controlsLeftTemplate( data ), + this.controlsLeftTemplate({ history: data, view: this }), //'<button class="btn btn-default">Herp</button>', - this.controlsRightTemplate( data ), + this.controlsRightTemplate({ history: data, view: this }), '</div>', '<div class="inner flex-row flex-column-container">', '<div id="history-', data.id, '" class="history-column history-panel flex-column"></div>', @@ -317,24 +315,24 @@ /** controls template displaying controls above the panel based on this.currentHistory */ controlsLeftTemplate : _.template([ '<div class="pull-left">', - '<% if( history.isCurrentHistory ){ %>', + '<% if( data.history.isCurrentHistory ){ %>', '<strong class="current-label">', _l( 'Current History' ), '</strong>', '<% } else { %>', '<button class="switch-to btn btn-default">', _l( 'Switch to' ), '</button>', '<% } %>', '</div>' - ].join( '' ), { variable : 'history' }), + ].join( '' ), { variable : 'data' }), /** controls template displaying controls above the panel based on this.currentHistory */ controlsRightTemplate : _.template([ '<div class="pull-right">', - '<% if( !history.purged ){ %>', + '<% if( !data.history.purged ){ %>', '<div class="panel-menu btn-group">', '<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">', '<span class="caret"></span>', '</button>', '<ul class="dropdown-menu pull-right" role="menu">', - '<% if( !history.deleted ){ %>', + '<% if( !data.history.deleted ){ %>', '<li><a href="javascript:void(0);" class="copy-history">', _l( 'Copy' ), '</a></li>', @@ -349,14 +347,16 @@ _l( 'Undelete' ), '</a></li>', '<% } %>', - //'<li><a href="javascript:void(0);" class="purge-history">', - // _l( 'Purge' ), - //'</a></li>', + '<% if( data.view.purgeAllowed ){ %>', + '<li><a href="javascript:void(0);" class="purge-history">', + _l( 'Purge' ), + '</a></li>', + '<% } %>', '</ul>', '<% } %>', '</div>', '</div>' - ].join( '' ), { variable: 'history' }), + ].join( '' ), { variable: 'data' }), // ------------------------------------------------------------------------ misc /** String rep */ @@ -491,7 +491,7 @@ // handle setting a history as current, triggered by history.setAsCurrent 'set-as-current': multipanel.setCurrentHistory, // handle deleting a history (depends on whether panels is including deleted or not) - 'change:deleted': multipanel.handleDeletedHistory, + 'change:deleted change:purged': multipanel.handleDeletedHistory, 'sort' : function(){ multipanel.renderColumns( 0 ); } }); @@ -519,7 +519,7 @@ * based on collection.includeDeleted */ handleDeletedHistory : function handleDeletedHistory( history ){ - if( history.get( 'deleted' ) ){ + if( history.get( 'deleted' ) || history.get( 'purged' ) ){ this.log( 'handleDeletedHistory', this.collection.includeDeleted, history ); var multipanel = this; column = multipanel.columnMap[ history.id ]; @@ -584,7 +584,10 @@ /** create a column and its panel and set up any listeners to them */ createColumn : function createColumn( history, options ){ // options passed can be re-used, so extend them before adding the model to prevent pollution for the next - options = _.extend( {}, options, { model: history }); + options = _.extend( {}, options, { + model : history, + purgeAllowed: Galaxy.config.allow_user_dataset_purge + }); var column = new HistoryPanelColumn( options ); if( history.id === this.currentHistoryId ){ column.currentHistory = true; } this.setUpColumnListeners( column ); @@ -1047,21 +1050,19 @@ mainTemplate : _.template([ '<div class="header flex-column-container">', '<div class="control-column control-column-left flex-column">', - '<button class="create-new btn btn-default">', _l( 'Create new' ), '</button> ', + '<button class="create-new btn btn-default" tabindex="4">', _l( 'Create new' ), '</button> ', '<div id="search-histories" class="search-control"></div>', '<div id="search-datasets" class="search-control"></div>', - '<button class="open-more-options btn btn-default">', - //TODO: tip not working - '<span class="fa fa-ellipsis-h" title="More options"></span>', - '</button>', + '<a class="open-more-options btn btn-default" tabindex="3">', + '<span class="fa fa-ellipsis-h"></span>', + '</a>', '</div>', // feedback '<div class="control-column control-column-center flex-column">', - '<div class="header-info">', - '</div>', + '<div class="header-info">', '</div>', '</div>', '<div class="control-column control-column-right flex-column">', - '<button class="done btn btn-default">', _l( 'Done' ), '</button>', + '<button class="done btn btn-default" tabindex="1">', _l( 'Done' ), '</button>', '</div>', '</div>', // middle - where the columns go diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/scripts/packed/mvc/history/history-model.js --- a/static/scripts/packed/mvc/history/history-model.js +++ b/static/scripts/packed/mvc/history/history-model.js @@ -1,1 +1,1 @@ -define(["mvc/history/history-contents","mvc/base-mvc","utils/localization"],function(h,i,d){var e=Backbone.Model.extend(i.LoggableMixin).extend(i.mixin(i.SearchableModelMixin,{defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",initialize:function(k,l,j){j=j||{};this.logger=j.logger||null;this.log(this+".initialize:",k,l,j);this.log("creating history contents:",l);this.contents=new h.HistoryContents(l||[],{historyId:this.get("id")});this._setUpListeners();this.updateTimeoutId=null},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});if(this.contents){this.listenTo(this.contents,"error",function(){this.trigger.apply(this,["error:contents"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(k,j){if(this.contents){this.contents.historyId=j}},this)},errorHandler:function(k,n,j,m,l){this.clearUpdateTimeout()},ownedByCurrUser:function(){if(!Galaxy||!Galaxy.currUser){return false}if(Galaxy.currUser.isAnonymous()||Galaxy.currUser.id!==this.get("user_id")){return false}return true},contentsCount:function(){return _.reduce(_.values(this.get("state_details")),function(j,k){return j+k},0)},searchAttributes:["name","annotation","tags"],searchAliases:{title:"name",tag:"tags"},checkForUpdates:function(j){if(this.contents.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(j)){j.call(this)}}return this},setUpdateTimeout:function(j){j=j||e.UPDATE_DELAY;var k=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){k.refresh()},j);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(k,j){k=k||[];j=j||{};var l=this;j.data=j.data||{};if(k.length){j.data.details=k.join(",")}var m=this.contents.fetch(j);m.done(function(n){l.checkForUpdates(function(){this.fetch()})});return m},_delete:function(j){if(this.get("deleted")){return jQuery.when()}return this.save({deleted:true},j)},undelete:function(j){if(!this.get("deleted")){return jQuery.when()}return this.save({deleted:false},j)},copy:function(m,k){m=(m!==undefined)?(m):(true);if(!this.id){throw new Error("You must set the history ID before copying it.")}var j={history_id:this.id};if(m){j.current=true}if(k){j.name=k}var l=this,n=jQuery.post(this.urlRoot,j);if(m){return n.then(function(o){var p=new e(o);return p.setAsCurrent().done(function(){l.trigger("copied",l,o)})})}return n.done(function(o){l.trigger("copied",l,o)})},setAsCurrent:function(){var j=this,k=jQuery.getJSON("/history/set_as_current?id="+this.id);k.done(function(){j.trigger("set-as-current",j)});return k},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}}));e.UPDATE_DELAY=4000;e.getHistoryData=function c(j,v){v=v||{};var r=v.detailIdsFn||[];var m=v.hdcaDetailIds||[];var s=jQuery.Deferred(),p=null;function k(w){if(j==="current"){return jQuery.getJSON(galaxy_config.root+"history/current_history_json")}return jQuery.ajax(galaxy_config.root+"api/histories/"+j)}function o(w){return w&&w.empty}function q(x){if(o(x)){return[]}if(_.isFunction(r)){r=r(x)}if(_.isFunction(m)){m=m(x)}var w={};if(r.length){w.dataset_details=r.join(",")}if(m.length){w.dataset_collection_details=m.join(",")}return jQuery.ajax(galaxy_config.root+"api/histories/"+x.id+"/contents",{data:w})}var t=v.historyFn||k,u=v.contentsFn||q;var n=t(j);n.done(function(w){p=w;s.notify({status:"history data retrieved",historyJSON:p})});n.fail(function(y,w,x){s.reject(y,"loading the history")});var l=n.then(u);l.then(function(w){s.notify({status:"contents data retrieved",historyJSON:p,contentsJSON:w});s.resolve(p,w)});l.fail(function(y,w,x){s.reject(y,"loading the contents",{history:p})});return s};var f=Backbone.Collection.extend(i.LoggableMixin).extend({model:e,urlRoot:(window.galaxy_config?galaxy_config.root:"/")+"api/histories",initialize:function(k,j){j=j||{};this.log("HistoryCollection.initialize",arguments);this.includeDeleted=j.includeDeleted||false;this.setUpListeners()},setUpListeners:function a(){var j=this;this.on("change:deleted",function(k){this.debug("change:deleted",j.includeDeleted,k.get("deleted"));if(!j.includeDeleted&&k.get("deleted")){j.remove(k)}});this.on("copied",function(k,l){this.unshift(new e(l,[]))})},create:function g(m,k,j,l){var o=this,n=jQuery.getJSON(galaxy_config.root+"history/create_new_current");return n.done(function(p){var q=new e(p,[],j||{});o.unshift(q);o.trigger("new-current")})},toString:function b(){return"HistoryCollection("+this.length+")"}});return{History:e,HistoryCollection:f}}); \ No newline at end of file +define(["mvc/history/history-contents","mvc/base-mvc","utils/localization"],function(h,i,d){var e=Backbone.Model.extend(i.LoggableMixin).extend(i.mixin(i.SearchableModelMixin,{defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",initialize:function(k,l,j){j=j||{};this.logger=j.logger||null;this.log(this+".initialize:",k,l,j);this.log("creating history contents:",l);this.contents=new h.HistoryContents(l||[],{historyId:this.get("id")});this._setUpListeners();this.updateTimeoutId=null},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});if(this.contents){this.listenTo(this.contents,"error",function(){this.trigger.apply(this,["error:contents"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(k,j){if(this.contents){this.contents.historyId=j}},this)},errorHandler:function(k,n,j,m,l){this.clearUpdateTimeout()},ownedByCurrUser:function(){if(!Galaxy||!Galaxy.currUser){return false}if(Galaxy.currUser.isAnonymous()||Galaxy.currUser.id!==this.get("user_id")){return false}return true},contentsCount:function(){return _.reduce(_.values(this.get("state_details")),function(j,k){return j+k},0)},searchAttributes:["name","annotation","tags"],searchAliases:{title:"name",tag:"tags"},checkForUpdates:function(j){if(this.contents.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(j)){j.call(this)}}return this},setUpdateTimeout:function(j){j=j||e.UPDATE_DELAY;var k=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){k.refresh()},j);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(k,j){k=k||[];j=j||{};var l=this;j.data=j.data||{};if(k.length){j.data.details=k.join(",")}var m=this.contents.fetch(j);m.done(function(n){l.checkForUpdates(function(){this.fetch()})});return m},_delete:function(j){if(this.get("deleted")){return jQuery.when()}return this.save({deleted:true},j)},purge:function(j){if(this.get("purged")){return jQuery.when()}return this.save({purged:true},j)},undelete:function(j){if(!this.get("deleted")){return jQuery.when()}return this.save({deleted:false},j)},copy:function(m,k){m=(m!==undefined)?(m):(true);if(!this.id){throw new Error("You must set the history ID before copying it.")}var j={history_id:this.id};if(m){j.current=true}if(k){j.name=k}var l=this,n=jQuery.post(this.urlRoot,j);if(m){return n.then(function(o){var p=new e(o);return p.setAsCurrent().done(function(){l.trigger("copied",l,o)})})}return n.done(function(o){l.trigger("copied",l,o)})},setAsCurrent:function(){var j=this,k=jQuery.getJSON("/history/set_as_current?id="+this.id);k.done(function(){j.trigger("set-as-current",j)});return k},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}}));e.UPDATE_DELAY=4000;e.getHistoryData=function c(j,v){v=v||{};var r=v.detailIdsFn||[];var m=v.hdcaDetailIds||[];var s=jQuery.Deferred(),p=null;function k(w){if(j==="current"){return jQuery.getJSON(galaxy_config.root+"history/current_history_json")}return jQuery.ajax(galaxy_config.root+"api/histories/"+j)}function o(w){return w&&w.empty}function q(x){if(o(x)){return[]}if(_.isFunction(r)){r=r(x)}if(_.isFunction(m)){m=m(x)}var w={};if(r.length){w.dataset_details=r.join(",")}if(m.length){w.dataset_collection_details=m.join(",")}return jQuery.ajax(galaxy_config.root+"api/histories/"+x.id+"/contents",{data:w})}var t=v.historyFn||k,u=v.contentsFn||q;var n=t(j);n.done(function(w){p=w;s.notify({status:"history data retrieved",historyJSON:p})});n.fail(function(y,w,x){s.reject(y,"loading the history")});var l=n.then(u);l.then(function(w){s.notify({status:"contents data retrieved",historyJSON:p,contentsJSON:w});s.resolve(p,w)});l.fail(function(y,w,x){s.reject(y,"loading the contents",{history:p})});return s};var f=Backbone.Collection.extend(i.LoggableMixin).extend({model:e,urlRoot:(window.galaxy_config?galaxy_config.root:"/")+"api/histories",initialize:function(k,j){j=j||{};this.log("HistoryCollection.initialize",arguments);this.includeDeleted=j.includeDeleted||false;this.setUpListeners()},setUpListeners:function a(){var j=this;this.on("change:deleted",function(k){this.debug("change:deleted",j.includeDeleted,k.get("deleted"));if(!j.includeDeleted&&k.get("deleted")){j.remove(k)}});this.on("copied",function(k,l){this.unshift(new e(l,[]))})},create:function g(m,k,j,l){var o=this,n=jQuery.getJSON(galaxy_config.root+"history/create_new_current");return n.done(function(p){var q=new e(p,[],j||{});o.unshift(q);o.trigger("new-current")})},toString:function b(){return"HistoryCollection("+this.length+")"}});return{History:e,HistoryCollection:f}}); \ No newline at end of file diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/scripts/packed/mvc/history/multi-panel.js --- a/static/scripts/packed/mvc/history/multi-panel.js +++ b/static/scripts/packed/mvc/history/multi-panel.js @@ -1,1 +1,1 @@ -define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/base-mvc","utils/ajax-queue","ui/mode-button","ui/search-input"],function(d,l,z,a){function g(I,E){E=E||{};if(!(Galaxy&&Galaxy.modal)){return I.copy()}var F=I.get("name"),C="Copy of '"+F+"'";function D(K){if(!K){if(!Galaxy.modal.$("#invalid-title").size()){var J=$("<p/>").attr("id","invalid-title").css({color:"red","margin-top":"8px"}).addClass("bg-danger").text(_l("Please enter a valid history title"));Galaxy.modal.$(".modal-body").append(J)}return false}return K}function G(J){var K=$('<p><span class="fa fa-spinner fa-spin"></span> Copying history...</p>').css("margin-top","8px");Galaxy.modal.$(".modal-body").append(K);I.copy(true,J).fail(function(){alert(_l("History could not be copied. Please contact a Galaxy administrator"))}).always(function(){Galaxy.modal.hide()})}function H(){var J=Galaxy.modal.$("#copy-modal-title").val();if(!D(J)){return}G(J)}Galaxy.modal.show(_.extend({title:_l("Copying history")+' "'+F+'"',body:$(['<label for="copy-modal-title">',_l("Enter a title for the copied history"),":","</label><br />",'<input id="copy-modal-title" class="form-control" style="width: 100%" value="',C,'" />'].join("")),buttons:{Cancel:function(){Galaxy.modal.hide()},Copy:H}},E));$("#copy-modal-title").focus().select();$("#copy-modal-title").on("keydown",function(J){if(J.keyCode===13){H()}})}var B=Backbone.View.extend(z.LoggableMixin).extend({tagName:"div",className:"history-column flex-column flex-row-container",id:function q(){if(!this.model){return""}return"history-column-"+this.model.get("id")},initialize:function c(C){C=C||{};this.panel=C.panel||this.createPanel(C);this.setUpListeners()},createPanel:function u(D){D=_.extend({model:this.model,dragItems:true},D);var C=new l.HistoryPanelEdit(D);C._renderEmptyMessage=this.__patch_renderEmptyMessage;return C},__patch_renderEmptyMessage:function(E){var D=this,F=_.chain(this.model.get("state_ids")).values().flatten().value().length,C=D.$emptyMessage(E);if(!_.isEmpty(D.hdaViews)){C.hide()}else{if(F&&!this.model.contents.length){C.empty().append($('<span class="fa fa-spinner fa-spin"></span><i>loading datasets...</i>')).show()}else{if(D.searchFor){C.text(D.noneFoundMsg).show()}else{C.text(D.emptyMsg).show()}}}return C},setUpListeners:function f(){var C=this;this.once("rendered",function(){C.trigger("rendered:initial",C)});this.setUpPanelListeners()},setUpPanelListeners:function k(){var C=this;this.listenTo(this.panel,{rendered:function(){C.trigger("rendered",C)}},this)},inView:function(C,D){var F=this.$el.offset().left,E=F+this.$el.width();if(E<C){return false}if(F>D){return false}return true},$panel:function e(){return this.$(".history-panel")},render:function A(D){D=(D!==undefined)?(D):("fast");var C=this.model?this.model.toJSON():{};this.$el.html(this.template(C));this.renderPanel(D);this.setUpBehaviors();return this},setUpBehaviors:function v(){},template:function w(C){C=_.extend(C||{},{isCurrentHistory:this.currentHistory});return $(['<div class="panel-controls clear flex-row">',this.controlsLeftTemplate(C),this.controlsRightTemplate(C),"</div>",'<div class="inner flex-row flex-column-container">','<div id="history-',C.id,'" class="history-column history-panel flex-column"></div>',"</div>"].join(""))},renderPanel:function h(C){C=(C!==undefined)?(C):("fast");this.panel.setElement(this.$panel()).render(C);if(this.currentHistory){this.panel.$list().before(this.panel._renderDropTargetHelp())}return this},events:{"click .switch-to.btn":function(){this.model.setAsCurrent()},"click .delete-history":function(){var C=this;this.model._delete().fail(function(F,D,E){alert(_l("Could not delete the history")+":\n"+E)}).done(function(D){C.render()})},"click .undelete-history":function(){var C=this;this.model.undelete().fail(function(F,D,E){alert(_l("Could not undelete the history")+":\n"+E)}).done(function(D){C.render()})},"click .purge-history":function(){if(confirm(_l("This will permanently remove the data. Are you sure?"))){var C=this;this.model.purge().fail(function(F,D,E){alert(_l("Could not purge the history")+":\n"+E)}).done(function(D){C.render()})}},"click .copy-history":"copy"},copy:function s(){g(this.model)},controlsLeftTemplate:_.template(['<div class="pull-left">',"<% if( history.isCurrentHistory ){ %>",'<strong class="current-label">',_l("Current History"),"</strong>","<% } else { %>",'<button class="switch-to btn btn-default">',_l("Switch to"),"</button>","<% } %>","</div>"].join(""),{variable:"history"}),controlsRightTemplate:_.template(['<div class="pull-right">',"<% if( !history.purged ){ %>",'<div class="panel-menu btn-group">','<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">','<span class="caret"></span>',"</button>",'<ul class="dropdown-menu pull-right" role="menu">',"<% if( !history.deleted ){ %>",'<li><a href="javascript:void(0);" class="copy-history">',_l("Copy"),"</a></li>",'<li><a href="javascript:void(0);" class="delete-history">',_l("Delete"),"</a></li>","<% } else /* if is deleted */ { %>",'<li><a href="javascript:void(0);" class="undelete-history">',_l("Undelete"),"</a></li>","<% } %>","</ul>","<% } %>","</div>","</div>"].join(""),{variable:"history"}),toString:function(){return"HistoryPanelColumn("+(this.panel?this.panel:"")+")"}});var m=Backbone.View.extend(z.LoggableMixin).extend({className:"multi-panel-history",initialize:function c(C){C=C||{};this.log(this+".init",C);this.$el.addClass(this.className);if(!C.currentHistoryId){throw new Error(this+" requires a currentHistoryId in the options")}this.currentHistoryId=C.currentHistoryId;this.options={columnWidth:312,borderWidth:1,columnGap:8,headerHeight:29,footerHeight:0,controlsHeight:20};this.order=C.order||"update";this._initSortOrders();this.hdaQueue=new a.NamedAjaxQueue([],false);this.collection=null;this.setCollection(C.histories||[]);this.columnMap={};this.createColumns(C.columnOptions);this.setUpListeners()},_initSortOrders:function(){function C(D,E){return function F(H,G,I){if(H.id===I){return -1}if(G.id===I){return 1}H=D(H);G=D(G);return E.asc?((H===G)?(0):(H>G?1:-1)):((H===G)?(0):(H>G?-1:1))}}this.sortOrders={update:{text:_l("most recent first"),fn:C(function(D){return Date(D.get("update_time"))},{asc:false})},name:{text:_l("name, a to z"),fn:C(function(D){return D.get("name")},{asc:true})},"name-dsc":{text:_l("name, z to a"),fn:C(function(D){return D.get("name")},{asc:false})},size:{text:_l("size, large to small"),fn:C(function(D){return D.get("size")},{asc:false})},"size-dsc":{text:_l("size, small to large"),fn:C(function(D){return D.get("size")},{asc:true})}};return this.sortOrders},setUpListeners:function f(){},setCollection:function y(D){var C=this;C.stopListening(C.collection);C.collection=D;C.sortCollection(C.order,{silent:true});C.setUpCollectionListeners();C.trigger("new-collection",C);return C},setUpCollectionListeners:function(){var C=this,D=C.collection;C.listenTo(D,{add:C.addAsCurrentColumn,"set-as-current":C.setCurrentHistory,"change:deleted":C.handleDeletedHistory,sort:function(){C.renderColumns(0)}})},setCurrentHistory:function p(D){var C=this.columnMap[this.currentHistoryId];if(C){C.currentHistory=false;C.$el.height("")}this.currentHistoryId=D.id;var E=this.columnMap[this.currentHistoryId];E.currentHistory=true;this.sortCollection();multipanel._recalcFirstColumnHeight();return E},handleDeletedHistory:function b(D){if(D.get("deleted")){this.log("handleDeletedHistory",this.collection.includeDeleted,D);var C=this;column=C.columnMap[D.id];if(!column){return}if(column.model.id===this.currentHistoryId){}else{if(!C.collection.includeDeleted){C.removeColumn(column)}}}},sortCollection:function(C,D){if(!(C in this.sortOrders)){C="update"}this.order=C;var G=this.currentHistoryId,F=this.sortOrders[C];this.collection.comparator=function E(I,H){return F.fn(I,H,G)};this.$(".current-order").text(F.text);if(this.$(".more-options").is(":visible")){this.$(".open-more-options.btn").popover("show")}this.collection.sort(D);return this.collection},create:function(C){return this.collection.create({current:true})},createColumns:function r(D){D=D||{};var C=this;this.columnMap={};C.collection.each(function(E,F){var G=C.createColumn(E,D);C.columnMap[E.id]=G})},createColumn:function t(E,C){C=_.extend({},C,{model:E});var D=new B(C);if(E.id===this.currentHistoryId){D.currentHistory=true}this.setUpColumnListeners(D);return D},sortedFilteredColumns:function(C){C=C||this.filters;if(!C||!C.length){return this.sortedColumns()}var D=this;return D.sortedColumns().filter(function(G,F){var E=G.currentHistory||_.every(C.map(function(H){return H.call(G)}));return E})},sortedColumns:function(){var D=this;var C=this.collection.map(function(F,E){return D.columnMap[F.id]});return C},addColumn:function o(E,C){C=C!==undefined?C:true;var D=this.createColumn(E);this.columnMap[E.id]=D;if(C){this.renderColumns()}return D},addAsCurrentColumn:function o(E){var D=this,C=this.addColumn(E,false);this.setCurrentHistory(E);C.once("rendered",function(){D.queueHdaFetch(C)});return C},removeColumn:function x(E,D){D=D!==undefined?D:true;this.log("removeColumn",E);if(!E){return}var F=this,C=this.options.columnWidth+this.options.columnGap;E.$el.fadeOut("fast",function(){if(D){$(this).remove();F.$(".middle").width(F.$(".middle").width()-C);F.checkColumnsInView();F._recalcFirstColumnHeight()}F.stopListening(E.panel);F.stopListening(E);delete F.columnMap[E.model.id];E.remove()})},setUpColumnListeners:function n(D){var E=this,C={HistoryDatasetAssociation:"hda",HistoryDatasetCollectionAssociation:"hdca"};E.listenTo(D,{"in-view":E.queueHdaFetch});E.listenTo(D.panel,{"view:draggable:dragstart":function(I,G,F,H){E._dropData=JSON.parse(I.dataTransfer.getData("text"));E.currentColumnDropTargetOn()},"view:draggable:dragend":function(I,G,F,H){E._dropData=null;E.currentColumnDropTargetOff()},"droptarget:drop":function(H,I,G){var J=E._dropData.filter(function(K){return((_.isObject(K)&&K.id)&&(_.contains(_.keys(C),K.model_class)))});E._dropData=null;var F=new a.NamedAjaxQueue();J.forEach(function(K){var L=C[K.model_class];F.add({name:"copy-"+K.id,fn:function(){return G.model.contents.copy(K.id,L)}})});F.start();F.done(function(K){G.model.fetch()})}})},columnMapLength:function(){return Object.keys(this.columnMap).length},render:function A(D){D=D!==undefined?D:this.fxSpeed;var C=this;C.log(C+".render");C.$el.html(C.mainTemplate(C));C.renderColumns(D);C.setUpBehaviors();C.trigger("rendered",C);return C},renderColumns:function j(F){F=F!==undefined?F:this.fxSpeed;var E=this,C=E.sortedFilteredColumns();E.$(".middle").width(C.length*(this.options.columnWidth+this.options.columnGap)+this.options.columnGap+16);var D=E.$(".middle");D.empty();C.forEach(function(H,G){H.$el.appendTo(D);H.delegateEvents();E.renderColumn(H,F)});if(this.searchFor&&C.length<=1){}else{E.checkColumnsInView();this._recalcFirstColumnHeight()}return C},renderColumn:function(C,D){D=D!==undefined?D:this.fxSpeed;return C.render(D)},queueHdaFetch:function i(E){if(E.model.contents.length===0&&!E.model.get("empty")){var C={},D=_.values(E.panel.storage.get("expandedIds")).join();if(D){C.dataset_details=D}this.hdaQueue.add({name:E.model.id,fn:function(){var F=E.model.contents.fetch({data:C,silent:true});return F.done(function(G){E.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},queueHdaFetchDetails:function(C){if((C.model.contents.length===0&&!C.model.get("empty"))||(!C.model.contents.haveDetails())){this.hdaQueue.add({name:C.model.id,fn:function(){var D=C.model.contents.fetch({data:{details:"all"},silent:true});return D.done(function(E){C.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},renderInfo:function(C){return this.$(".header .header-info").text(C)},events:{"click .done.btn":"close","click .create-new.btn":"create","click #include-deleted":"_clickToggleDeletedHistories","click .order .set-order":"_chooseOrder","click #toggle-deleted":"_clickToggleDeletedDatasets","click #toggle-hidden":"_clickToggleHiddenDatasets"},close:function(D){var C="/";if(Galaxy&&Galaxy.options&&Galaxy.options.root){C=Galaxy.options.root}else{if(galaxy_config&&galaxy_config.root){C=galaxy_config.root}}window.location=C},_clickToggleDeletedHistories:function(C){return this.toggleDeletedHistories($(C.currentTarget).is(":checked"))},toggleDeletedHistories:function(C){if(C){window.location=Galaxy.options.root+"history/view_multiple?include_deleted_histories=True"}else{window.location=Galaxy.options.root+"history/view_multiple"}},_clickToggleDeletedDatasets:function(C){return this.toggleDeletedDatasets($(C.currentTarget).is(":checked"))},toggleDeletedDatasets:function(C){C=C!==undefined?C:false;var D=this;D.sortedFilteredColumns().forEach(function(F,E){_.delay(function(){F.panel.toggleShowDeleted(C,false)},E*200)})},_clickToggleHiddenDatasets:function(C){return this.toggleHiddenDatasets($(C.currentTarget).is(":checked"))},toggleHiddenDatasets:function(C){C=C!==undefined?C:false;var D=this;D.sortedFilteredColumns().forEach(function(F,E){_.delay(function(){F.panel.toggleShowHidden(C,false)},E*200)})},_chooseOrder:function(D){var C=$(D.currentTarget).data("order");this.sortCollection(C)},setUpBehaviors:function(){var D=this;D._moreOptionsPopover();D.$("#search-histories").searchInput({name:"search-histories",placeholder:_l("search histories"),onsearch:function(E){D.searchFor=E;D.filters=[function(){return this.model.matchesAll(D.searchFor)}];D.renderColumns(0)},onclear:function(E){D.searchFor=null;D.filters=[];D.renderColumns(0)}});D.$("#search-datasets").searchInput({name:"search-datasets",placeholder:_l("search all datasets"),onfirstsearch:function(E){D.hdaQueue.clear();D.$("#search-datasets").searchInput("toggle-loading");D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E);D.queueHdaFetchDetails(F)});D.hdaQueue.progress(function(F){D.renderInfo([_l("searching"),(F.curr+1),_l("of"),F.total].join(" "))});D.hdaQueue.deferred.done(function(){D.renderInfo("");D.$("#search-datasets").searchInput("toggle-loading")})},onsearch:function(E){D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E)})},onclear:function(E){D.searchFor=null;D.sortedFilteredColumns().forEach(function(F){F.panel.clearSearch()})}});$(window).resize(function(){D._recalcFirstColumnHeight()});var C=_.debounce(_.bind(this.checkColumnsInView,this),100);this.$(".middle").parent().scroll(C)},_moreOptionsPopover:function(){return this.$(".open-more-options.btn").popover({container:".header",placement:"bottom",html:true,content:$(this.optionsPopoverTemplate(this))})},_recalcFirstColumnHeight:function(){var C=this.$(".history-column").first(),E=this.$(".middle").height(),D=C.find(".panel-controls").height();C.height(E).find(".inner").height(E-D)},_viewport:function(){var C=this.$(".middle").parent().offset().left;return{left:C,right:C+this.$(".middle").parent().width()}},columnsInView:function(){var C=this._viewport();return this.sortedFilteredColumns().filter(function(D){return D.currentHistory||D.inView(C.left,C.right)})},checkColumnsInView:function(){this.columnsInView().forEach(function(C){C.trigger("in-view",C)})},currentColumnDropTargetOn:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=function(D){};C.panel.dropTargetOn()},currentColumnDropTargetOff:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=l.HistoryPanelEdit.prototype.dataDrop;C.panel.dropTarget=false;C.panel.$(".history-drop-target").remove()},toString:function(){return"MultiPanelColumns("+(this.columns?this.columns.length:0)+")"},mainTemplate:_.template(['<div class="header flex-column-container">','<div class="control-column control-column-left flex-column">','<button class="create-new btn btn-default">',_l("Create new"),"</button> ",'<div id="search-histories" class="search-control"></div>','<div id="search-datasets" class="search-control"></div>','<button class="open-more-options btn btn-default">','<span class="fa fa-ellipsis-h" title="More options"></span>',"</button>","</div>",'<div class="control-column control-column-center flex-column">','<div class="header-info">',"</div>","</div>",'<div class="control-column control-column-right flex-column">','<button class="done btn btn-default">',_l("Done"),"</button>","</div>","</div>",'<div class="outer-middle flex-row flex-row-container">','<div class="middle flex-column-container flex-row"></div>',"</div>",'<div class="footer flex-column-container">',"</div>"].join(""),{variable:"view"}),optionsPopoverTemplate:_.template(['<div class="more-options">','<div class="order btn-group">','<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',_l("Order histories by")+" ",'<span class="current-order"><%= view.sortOrders[ view.order ].text %></span> ','<span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">',"<% _.each( view.sortOrders, function( order, key ){ %>",'<li><a href="javascript:void(0);" class="set-order" data-order="<%= key %>">',"<%= order.text %>","</a></li>","<% }); %>","</ul>","</div>",'<div class="checkbox"><label><input id="include-deleted" type="checkbox"','<%= view.collection.includeDeleted? " checked" : "" %>>',_l("Include deleted histories"),"</label></div>","<hr />",'<div class="checkbox"><label><input id="toggle-deleted" type="checkbox">',_l("Include deleted datasets"),"</label></div>",'<div class="checkbox"><label><input id="toggle-hidden" type="checkbox">',_l("Include hidden datasets"),"</label></div>","</div>"].join(""),{variable:"view"})});return{MultiPanelColumns:m}}); \ No newline at end of file +define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/base-mvc","utils/ajax-queue","ui/mode-button","ui/search-input"],function(d,l,z,a){function g(I,E){E=E||{};if(!(Galaxy&&Galaxy.modal)){return I.copy()}var F=I.get("name"),C="Copy of '"+F+"'";function D(K){if(!K){if(!Galaxy.modal.$("#invalid-title").size()){var J=$("<p/>").attr("id","invalid-title").css({color:"red","margin-top":"8px"}).addClass("bg-danger").text(_l("Please enter a valid history title"));Galaxy.modal.$(".modal-body").append(J)}return false}return K}function G(J){var K=$('<p><span class="fa fa-spinner fa-spin"></span> Copying history...</p>').css("margin-top","8px");Galaxy.modal.$(".modal-body").append(K);I.copy(true,J).fail(function(){alert(_l("History could not be copied. Please contact a Galaxy administrator"))}).always(function(){Galaxy.modal.hide()})}function H(){var J=Galaxy.modal.$("#copy-modal-title").val();if(!D(J)){return}G(J)}Galaxy.modal.show(_.extend({title:_l("Copying history")+' "'+F+'"',body:$(['<label for="copy-modal-title">',_l("Enter a title for the copied history"),":","</label><br />",'<input id="copy-modal-title" class="form-control" style="width: 100%" value="',C,'" />'].join("")),buttons:{Cancel:function(){Galaxy.modal.hide()},Copy:H}},E));$("#copy-modal-title").focus().select();$("#copy-modal-title").on("keydown",function(J){if(J.keyCode===13){H()}})}var B=Backbone.View.extend(z.LoggableMixin).extend({tagName:"div",className:"history-column flex-column flex-row-container",id:function q(){if(!this.model){return""}return"history-column-"+this.model.get("id")},initialize:function c(C){C=C||{};this.purgeAllowed=!_.isUndefined(C.purgeAllowed)?C.purgeAllowed:false;this.panel=C.panel||this.createPanel(C);this.setUpListeners()},createPanel:function u(D){D=_.extend({model:this.model,purgeAllowed:this.purgeAllowed,dragItems:true},D);var C=new l.HistoryPanelEdit(D);C._renderEmptyMessage=this.__patch_renderEmptyMessage;return C},__patch_renderEmptyMessage:function(E){var D=this,F=_.chain(this.model.get("state_ids")).values().flatten().value().length,C=D.$emptyMessage(E);if(!_.isEmpty(D.hdaViews)){C.hide()}else{if(F&&!this.model.contents.length){C.empty().append($('<span class="fa fa-spinner fa-spin"></span><i>loading datasets...</i>')).show()}else{if(D.searchFor){C.text(D.noneFoundMsg).show()}else{C.text(D.emptyMsg).show()}}}return C},setUpListeners:function f(){var C=this;this.once("rendered",function(){C.trigger("rendered:initial",C)});this.setUpPanelListeners()},setUpPanelListeners:function k(){var C=this;this.listenTo(this.panel,{rendered:function(){C.trigger("rendered",C)}},this)},inView:function(C,D){var F=this.$el.offset().left,E=F+this.$el.width();if(E<C){return false}if(F>D){return false}return true},$panel:function e(){return this.$(".history-panel")},render:function A(D){D=(D!==undefined)?(D):("fast");var C=this.model?this.model.toJSON():{};this.$el.html(this.template(C));this.renderPanel(D);this.setUpBehaviors();return this},setUpBehaviors:function v(){},template:function w(C){C=_.extend(C||{},{isCurrentHistory:this.currentHistory});return $(['<div class="panel-controls clear flex-row">',this.controlsLeftTemplate({history:C,view:this}),this.controlsRightTemplate({history:C,view:this}),"</div>",'<div class="inner flex-row flex-column-container">','<div id="history-',C.id,'" class="history-column history-panel flex-column"></div>',"</div>"].join(""))},renderPanel:function h(C){C=(C!==undefined)?(C):("fast");this.panel.setElement(this.$panel()).render(C);if(this.currentHistory){this.panel.$list().before(this.panel._renderDropTargetHelp())}return this},events:{"click .switch-to.btn":function(){this.model.setAsCurrent()},"click .delete-history":function(){var C=this;this.model._delete().fail(function(F,D,E){alert(_l("Could not delete the history")+":\n"+E)}).done(function(D){C.render()})},"click .undelete-history":function(){var C=this;this.model.undelete().fail(function(F,D,E){alert(_l("Could not undelete the history")+":\n"+E)}).done(function(D){C.render()})},"click .purge-history":function(){if(confirm(_l("This will permanently remove the data. Are you sure?"))){var C=this;this.model.purge().fail(function(F,D,E){alert(_l("Could not purge the history")+":\n"+E)}).done(function(D){C.render()})}},"click .copy-history":"copy"},copy:function s(){g(this.model)},controlsLeftTemplate:_.template(['<div class="pull-left">',"<% if( data.history.isCurrentHistory ){ %>",'<strong class="current-label">',_l("Current History"),"</strong>","<% } else { %>",'<button class="switch-to btn btn-default">',_l("Switch to"),"</button>","<% } %>","</div>"].join(""),{variable:"data"}),controlsRightTemplate:_.template(['<div class="pull-right">',"<% if( !data.history.purged ){ %>",'<div class="panel-menu btn-group">','<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">','<span class="caret"></span>',"</button>",'<ul class="dropdown-menu pull-right" role="menu">',"<% if( !data.history.deleted ){ %>",'<li><a href="javascript:void(0);" class="copy-history">',_l("Copy"),"</a></li>",'<li><a href="javascript:void(0);" class="delete-history">',_l("Delete"),"</a></li>","<% } else /* if is deleted */ { %>",'<li><a href="javascript:void(0);" class="undelete-history">',_l("Undelete"),"</a></li>","<% } %>","<% if( data.view.purgeAllowed ){ %>",'<li><a href="javascript:void(0);" class="purge-history">',_l("Purge"),"</a></li>","<% } %>","</ul>","<% } %>","</div>","</div>"].join(""),{variable:"data"}),toString:function(){return"HistoryPanelColumn("+(this.panel?this.panel:"")+")"}});var m=Backbone.View.extend(z.LoggableMixin).extend({className:"multi-panel-history",initialize:function c(C){C=C||{};this.log(this+".init",C);this.$el.addClass(this.className);if(!C.currentHistoryId){throw new Error(this+" requires a currentHistoryId in the options")}this.currentHistoryId=C.currentHistoryId;this.options={columnWidth:312,borderWidth:1,columnGap:8,headerHeight:29,footerHeight:0,controlsHeight:20};this.order=C.order||"update";this._initSortOrders();this.hdaQueue=new a.NamedAjaxQueue([],false);this.collection=null;this.setCollection(C.histories||[]);this.columnMap={};this.createColumns(C.columnOptions);this.setUpListeners()},_initSortOrders:function(){function C(D,E){return function F(H,G,I){if(H.id===I){return -1}if(G.id===I){return 1}H=D(H);G=D(G);return E.asc?((H===G)?(0):(H>G?1:-1)):((H===G)?(0):(H>G?-1:1))}}this.sortOrders={update:{text:_l("most recent first"),fn:C(function(D){return Date(D.get("update_time"))},{asc:false})},name:{text:_l("name, a to z"),fn:C(function(D){return D.get("name")},{asc:true})},"name-dsc":{text:_l("name, z to a"),fn:C(function(D){return D.get("name")},{asc:false})},size:{text:_l("size, large to small"),fn:C(function(D){return D.get("size")},{asc:false})},"size-dsc":{text:_l("size, small to large"),fn:C(function(D){return D.get("size")},{asc:true})}};return this.sortOrders},setUpListeners:function f(){},setCollection:function y(D){var C=this;C.stopListening(C.collection);C.collection=D;C.sortCollection(C.order,{silent:true});C.setUpCollectionListeners();C.trigger("new-collection",C);return C},setUpCollectionListeners:function(){var C=this,D=C.collection;C.listenTo(D,{add:C.addAsCurrentColumn,"set-as-current":C.setCurrentHistory,"change:deleted change:purged":C.handleDeletedHistory,sort:function(){C.renderColumns(0)}})},setCurrentHistory:function p(D){var C=this.columnMap[this.currentHistoryId];if(C){C.currentHistory=false;C.$el.height("")}this.currentHistoryId=D.id;var E=this.columnMap[this.currentHistoryId];E.currentHistory=true;this.sortCollection();multipanel._recalcFirstColumnHeight();return E},handleDeletedHistory:function b(D){if(D.get("deleted")||D.get("purged")){this.log("handleDeletedHistory",this.collection.includeDeleted,D);var C=this;column=C.columnMap[D.id];if(!column){return}if(column.model.id===this.currentHistoryId){}else{if(!C.collection.includeDeleted){C.removeColumn(column)}}}},sortCollection:function(C,D){if(!(C in this.sortOrders)){C="update"}this.order=C;var G=this.currentHistoryId,F=this.sortOrders[C];this.collection.comparator=function E(I,H){return F.fn(I,H,G)};this.$(".current-order").text(F.text);if(this.$(".more-options").is(":visible")){this.$(".open-more-options.btn").popover("show")}this.collection.sort(D);return this.collection},create:function(C){return this.collection.create({current:true})},createColumns:function r(D){D=D||{};var C=this;this.columnMap={};C.collection.each(function(E,F){var G=C.createColumn(E,D);C.columnMap[E.id]=G})},createColumn:function t(E,C){C=_.extend({},C,{model:E,purgeAllowed:Galaxy.config.allow_user_dataset_purge});var D=new B(C);if(E.id===this.currentHistoryId){D.currentHistory=true}this.setUpColumnListeners(D);return D},sortedFilteredColumns:function(C){C=C||this.filters;if(!C||!C.length){return this.sortedColumns()}var D=this;return D.sortedColumns().filter(function(G,F){var E=G.currentHistory||_.every(C.map(function(H){return H.call(G)}));return E})},sortedColumns:function(){var D=this;var C=this.collection.map(function(F,E){return D.columnMap[F.id]});return C},addColumn:function o(E,C){C=C!==undefined?C:true;var D=this.createColumn(E);this.columnMap[E.id]=D;if(C){this.renderColumns()}return D},addAsCurrentColumn:function o(E){var D=this,C=this.addColumn(E,false);this.setCurrentHistory(E);C.once("rendered",function(){D.queueHdaFetch(C)});return C},removeColumn:function x(E,D){D=D!==undefined?D:true;this.log("removeColumn",E);if(!E){return}var F=this,C=this.options.columnWidth+this.options.columnGap;E.$el.fadeOut("fast",function(){if(D){$(this).remove();F.$(".middle").width(F.$(".middle").width()-C);F.checkColumnsInView();F._recalcFirstColumnHeight()}F.stopListening(E.panel);F.stopListening(E);delete F.columnMap[E.model.id];E.remove()})},setUpColumnListeners:function n(D){var E=this,C={HistoryDatasetAssociation:"hda",HistoryDatasetCollectionAssociation:"hdca"};E.listenTo(D,{"in-view":E.queueHdaFetch});E.listenTo(D.panel,{"view:draggable:dragstart":function(I,G,F,H){E._dropData=JSON.parse(I.dataTransfer.getData("text"));E.currentColumnDropTargetOn()},"view:draggable:dragend":function(I,G,F,H){E._dropData=null;E.currentColumnDropTargetOff()},"droptarget:drop":function(H,I,G){var J=E._dropData.filter(function(K){return((_.isObject(K)&&K.id)&&(_.contains(_.keys(C),K.model_class)))});E._dropData=null;var F=new a.NamedAjaxQueue();J.forEach(function(K){var L=C[K.model_class];F.add({name:"copy-"+K.id,fn:function(){return G.model.contents.copy(K.id,L)}})});F.start();F.done(function(K){G.model.fetch()})}})},columnMapLength:function(){return Object.keys(this.columnMap).length},render:function A(D){D=D!==undefined?D:this.fxSpeed;var C=this;C.log(C+".render");C.$el.html(C.mainTemplate(C));C.renderColumns(D);C.setUpBehaviors();C.trigger("rendered",C);return C},renderColumns:function j(F){F=F!==undefined?F:this.fxSpeed;var E=this,C=E.sortedFilteredColumns();E.$(".middle").width(C.length*(this.options.columnWidth+this.options.columnGap)+this.options.columnGap+16);var D=E.$(".middle");D.empty();C.forEach(function(H,G){H.$el.appendTo(D);H.delegateEvents();E.renderColumn(H,F)});if(this.searchFor&&C.length<=1){}else{E.checkColumnsInView();this._recalcFirstColumnHeight()}return C},renderColumn:function(C,D){D=D!==undefined?D:this.fxSpeed;return C.render(D)},queueHdaFetch:function i(E){if(E.model.contents.length===0&&!E.model.get("empty")){var C={},D=_.values(E.panel.storage.get("expandedIds")).join();if(D){C.dataset_details=D}this.hdaQueue.add({name:E.model.id,fn:function(){var F=E.model.contents.fetch({data:C,silent:true});return F.done(function(G){E.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},queueHdaFetchDetails:function(C){if((C.model.contents.length===0&&!C.model.get("empty"))||(!C.model.contents.haveDetails())){this.hdaQueue.add({name:C.model.id,fn:function(){var D=C.model.contents.fetch({data:{details:"all"},silent:true});return D.done(function(E){C.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},renderInfo:function(C){return this.$(".header .header-info").text(C)},events:{"click .done.btn":"close","click .create-new.btn":"create","click #include-deleted":"_clickToggleDeletedHistories","click .order .set-order":"_chooseOrder","click #toggle-deleted":"_clickToggleDeletedDatasets","click #toggle-hidden":"_clickToggleHiddenDatasets"},close:function(D){var C="/";if(Galaxy&&Galaxy.options&&Galaxy.options.root){C=Galaxy.options.root}else{if(galaxy_config&&galaxy_config.root){C=galaxy_config.root}}window.location=C},_clickToggleDeletedHistories:function(C){return this.toggleDeletedHistories($(C.currentTarget).is(":checked"))},toggleDeletedHistories:function(C){if(C){window.location=Galaxy.options.root+"history/view_multiple?include_deleted_histories=True"}else{window.location=Galaxy.options.root+"history/view_multiple"}},_clickToggleDeletedDatasets:function(C){return this.toggleDeletedDatasets($(C.currentTarget).is(":checked"))},toggleDeletedDatasets:function(C){C=C!==undefined?C:false;var D=this;D.sortedFilteredColumns().forEach(function(F,E){_.delay(function(){F.panel.toggleShowDeleted(C,false)},E*200)})},_clickToggleHiddenDatasets:function(C){return this.toggleHiddenDatasets($(C.currentTarget).is(":checked"))},toggleHiddenDatasets:function(C){C=C!==undefined?C:false;var D=this;D.sortedFilteredColumns().forEach(function(F,E){_.delay(function(){F.panel.toggleShowHidden(C,false)},E*200)})},_chooseOrder:function(D){var C=$(D.currentTarget).data("order");this.sortCollection(C)},setUpBehaviors:function(){var D=this;D._moreOptionsPopover();D.$("#search-histories").searchInput({name:"search-histories",placeholder:_l("search histories"),onsearch:function(E){D.searchFor=E;D.filters=[function(){return this.model.matchesAll(D.searchFor)}];D.renderColumns(0)},onclear:function(E){D.searchFor=null;D.filters=[];D.renderColumns(0)}});D.$("#search-datasets").searchInput({name:"search-datasets",placeholder:_l("search all datasets"),onfirstsearch:function(E){D.hdaQueue.clear();D.$("#search-datasets").searchInput("toggle-loading");D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E);D.queueHdaFetchDetails(F)});D.hdaQueue.progress(function(F){D.renderInfo([_l("searching"),(F.curr+1),_l("of"),F.total].join(" "))});D.hdaQueue.deferred.done(function(){D.renderInfo("");D.$("#search-datasets").searchInput("toggle-loading")})},onsearch:function(E){D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E)})},onclear:function(E){D.searchFor=null;D.sortedFilteredColumns().forEach(function(F){F.panel.clearSearch()})}});$(window).resize(function(){D._recalcFirstColumnHeight()});var C=_.debounce(_.bind(this.checkColumnsInView,this),100);this.$(".middle").parent().scroll(C)},_moreOptionsPopover:function(){return this.$(".open-more-options.btn").popover({container:".header",placement:"bottom",html:true,content:$(this.optionsPopoverTemplate(this))})},_recalcFirstColumnHeight:function(){var C=this.$(".history-column").first(),E=this.$(".middle").height(),D=C.find(".panel-controls").height();C.height(E).find(".inner").height(E-D)},_viewport:function(){var C=this.$(".middle").parent().offset().left;return{left:C,right:C+this.$(".middle").parent().width()}},columnsInView:function(){var C=this._viewport();return this.sortedFilteredColumns().filter(function(D){return D.currentHistory||D.inView(C.left,C.right)})},checkColumnsInView:function(){this.columnsInView().forEach(function(C){C.trigger("in-view",C)})},currentColumnDropTargetOn:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=function(D){};C.panel.dropTargetOn()},currentColumnDropTargetOff:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=l.HistoryPanelEdit.prototype.dataDrop;C.panel.dropTarget=false;C.panel.$(".history-drop-target").remove()},toString:function(){return"MultiPanelColumns("+(this.columns?this.columns.length:0)+")"},mainTemplate:_.template(['<div class="header flex-column-container">','<div class="control-column control-column-left flex-column">','<button class="create-new btn btn-default" tabindex="4">',_l("Create new"),"</button> ",'<div id="search-histories" class="search-control"></div>','<div id="search-datasets" class="search-control"></div>','<a class="open-more-options btn btn-default" tabindex="3">','<span class="fa fa-ellipsis-h"></span>',"</a>","</div>",'<div class="control-column control-column-center flex-column">','<div class="header-info">',"</div>","</div>",'<div class="control-column control-column-right flex-column">','<button class="done btn btn-default" tabindex="1">',_l("Done"),"</button>","</div>","</div>",'<div class="outer-middle flex-row flex-row-container">','<div class="middle flex-column-container flex-row"></div>',"</div>",'<div class="footer flex-column-container">',"</div>"].join(""),{variable:"view"}),optionsPopoverTemplate:_.template(['<div class="more-options">','<div class="order btn-group">','<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown">',_l("Order histories by")+" ",'<span class="current-order"><%= view.sortOrders[ view.order ].text %></span> ','<span class="caret"></span>',"</button>",'<ul class="dropdown-menu" role="menu">',"<% _.each( view.sortOrders, function( order, key ){ %>",'<li><a href="javascript:void(0);" class="set-order" data-order="<%= key %>">',"<%= order.text %>","</a></li>","<% }); %>","</ul>","</div>",'<div class="checkbox"><label><input id="include-deleted" type="checkbox"','<%= view.collection.includeDeleted? " checked" : "" %>>',_l("Include deleted histories"),"</label></div>","<hr />",'<div class="checkbox"><label><input id="toggle-deleted" type="checkbox">',_l("Include deleted datasets"),"</label></div>",'<div class="checkbox"><label><input id="toggle-hidden" type="checkbox">',_l("Include hidden datasets"),"</label></div>","</div>"].join(""),{variable:"view"})});return{MultiPanelColumns:m}}); \ No newline at end of file diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/style/Gruntfile.js --- a/static/style/Gruntfile.js +++ b/static/style/Gruntfile.js @@ -64,7 +64,10 @@ // remove tmp files clean: { - clean : [ fmt('%s/tmp-site-config.less', out) ] + clean : [ + fmt( '%s/tmp-site-config.less', out ), + fmt( '%s/jstree.css', out ) + ] } }); diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/style/blue/base.css --- a/static/style/blue/base.css +++ b/static/style/blue/base.css @@ -2101,14 +2101,14 @@ .multi-panel-history .flex-column-container{-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row} .multi-panel-history .flex-row,.multi-panel-history .flex-column{-webkit-flex:1 1 auto;-ms-flex:1 1 auto;flex:1 1 auto;-webkit-align-self:auto;-ms-flex-item-align:auto;align-self:auto} .multi-panel-history .header,.multi-panel-history .footer{width:100%;background-color:lightgrey}.multi-panel-history .header .btn,.multi-panel-history .footer .btn{height:21px} -.multi-panel-history .header{min-height:29px;max-height:29px} +.multi-panel-history .header{min-height:29px;max-height:29px}.multi-panel-history .header .more-options .btn{height:26px} +.multi-panel-history .header .more-options input[type=checkbox]{margin-top:1px} .multi-panel-history .footer{min-height:0;max-height:0} .multi-panel-history .smaller-btn{height:20px;line-height:normal;font-size:90%;padding-top:0px;padding-bottom:0px} .multi-panel-history .control-column{margin-top:4px}.multi-panel-history .control-column .btn{height:20px;line-height:normal;font-size:90%;padding-top:0px;padding-bottom:0px} .multi-panel-history .control-column .search-control{display:inline-block;width:40%}.multi-panel-history .control-column .search-control .search-clear,.multi-panel-history .control-column .search-control .search-loading{margin-top:-22px} .multi-panel-history .control-column input.search-query{font-size:90%;height:21px;line-height:normal;padding:2px 2px 1px 2px} .multi-panel-history .control-column .open-more-options{padding:2px 6px 2px 6px;font-size:100%} -.multi-panel-history .control-column .more-options input[type=checkbox]{margin-top:2px} .multi-panel-history .control-column .header-info{display:inline-block;padding:2px 4px 2px 4px;color:grey} .multi-panel-history .control-column.control-column-right,.multi-panel-history .control-column.control-column-left{margin-right:8px;margin-left:8px}.multi-panel-history .control-column.control-column-right>*,.multi-panel-history .control-column.control-column-left>*{margin:0px 4px 4px 0px} .multi-panel-history .control-column.control-column-center{text-align:center;max-height:22px;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;flex:0 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;max-height:22px} diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 static/style/src/less/history.less --- a/static/style/src/less/history.less +++ b/static/style/src/less/history.less @@ -650,6 +650,15 @@ .header { min-height: @mph-header_height; max-height: @mph-header_height; + // popover containing sorting and filters + .more-options { + .btn { + height: 26px; + } + input[type=checkbox] { + margin-top: 1px; + } + } } .footer { min-height: @mph-footer_height; @@ -691,9 +700,6 @@ padding: 2px 6px 2px 6px; font-size: 100%; } - .more-options input[type=checkbox] { - margin-top: 2px; - } .header-info { display: inline-block; padding: 2px 4px 2px 4px; diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 test/casperjs/api-history-tests.js --- a/test/casperjs/api-history-tests.js +++ b/test/casperjs/api-history-tests.js @@ -118,7 +118,7 @@ "Id of last history (from index) DOES appear after undeletion: " + newFirstHistory.id ); //TODO: show, deleted flag - //TODO: delete, purge flag + // ------------------------------------------------------------------------------------------- UPDATE // ........................................................................................... name @@ -294,6 +294,28 @@ //this.test.comment( 'calling show with /deleted should raise a bad request' ); /* */ + + // ------------------------------------------------------------------------------------------- PURGE + var newHistoryId = null; + spaceghost.then( function(){ + this.test.comment( 'calling purge should mark a history, its datasets, and remove the files' ); + // create new history + var newHistory = this.api.histories.create({ name: 'To Purge' }); + newHistoryId = newHistory.id; + }); + spaceghost.openHomePage().api.tools.thenUploadToCurrent({ + filepath: '../../test-data/1.sam' + }); + spaceghost.then( function(){ + var recent = this.api.histories.show( newHistoryId ); + this.debug( 'size:\n' + recent.size ); + + this.api.assertRaises( function(){ + this.api.histories.delete_( recent.id, true ); + }, 403, 'This instance does not allow user dataset purging', 'Config does not allow thrown' ); + }); + //TODO: a way to set the config to allow user purging and then being able to test this would be good. + //this.debug( this.jsonStr( historyShow ) ); }); diff -r 4589eb71e192251691fbf82aac75b9b0d6f47c18 -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 test/casperjs/modules/api.js --- a/test/casperjs/modules/api.js +++ b/test/casperjs/modules/api.js @@ -267,10 +267,12 @@ this.api.spaceghost.info( 'histories.delete: ' + [ id, (( purge )?( '(purge!)' ):( '' )) ] ); // py.payload <-> ajax.data - var payload = ( purge )?({ purge: true }):({}); - return this.api._ajax( utils.format( this.urlTpls.delete_, this.api.ensureId( id ) ), { - type : 'DELETE', - data : payload + var url = utils.format( this.urlTpls.delete_, this.api.ensureId( id ) ); + if( purge ){ + url += '?purge=True'; + } + return this.api._ajax( url, { + type : 'DELETE' }); }; https://bitbucket.org/galaxy/galaxy-central/commits/17dd62d9a0b0/ Changeset: 17dd62d9a0b0 User: dannon Date: 2015-02-17 13:37:37+00:00 Summary: Supply remote annotation for complex mappings (also squelches a warning which was causing job failures) Affected #: 1 file diff -r d004eb0d8be7f7b64974f368d16d5fd217a08bd8 -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 lib/galaxy/model/mapping.py --- a/lib/galaxy/model/mapping.py +++ b/lib/galaxy/model/mapping.py @@ -1457,7 +1457,8 @@ backref=backref( "parent", primaryjoin=( model.HistoryDatasetAssociation.table.c.parent_id == model.HistoryDatasetAssociation.table.c.id ), remote_side=[model.HistoryDatasetAssociation.table.c.id], uselist=False ) ), visible_children=relation( model.HistoryDatasetAssociation, - primaryjoin=( ( model.HistoryDatasetAssociation.table.c.parent_id == model.HistoryDatasetAssociation.table.c.id ) & ( model.HistoryDatasetAssociation.table.c.visible == True ) ) ), + primaryjoin=( ( model.HistoryDatasetAssociation.table.c.parent_id == model.HistoryDatasetAssociation.table.c.id ) & ( model.HistoryDatasetAssociation.table.c.visible == True ) ), + remote_side=[model.HistoryDatasetAssociation.table.c.id] ), tags=relation( model.HistoryDatasetAssociationTagAssociation, order_by=model.HistoryDatasetAssociationTagAssociation.table.c.id, backref='history_tag_associations' ), annotations=relation( model.HistoryDatasetAssociationAnnotationAssociation, order_by=model.HistoryDatasetAssociationAnnotationAssociation.table.c.id, backref="hdas" ), ratings=relation( model.HistoryDatasetAssociationRatingAssociation, order_by=model.HistoryDatasetAssociationRatingAssociation.table.c.id, backref="hdas" ), @@ -1784,7 +1785,8 @@ backref=backref( "parent", primaryjoin=( model.LibraryDatasetDatasetAssociation.table.c.parent_id == model.LibraryDatasetDatasetAssociation.table.c.id ), remote_side=[model.LibraryDatasetDatasetAssociation.table.c.id] ) ), visible_children=relation( model.LibraryDatasetDatasetAssociation, - primaryjoin=( ( model.LibraryDatasetDatasetAssociation.table.c.parent_id == model.LibraryDatasetDatasetAssociation.table.c.id ) & ( model.LibraryDatasetDatasetAssociation.table.c.visible == True ) ) ), + primaryjoin=( ( model.LibraryDatasetDatasetAssociation.table.c.parent_id == model.LibraryDatasetDatasetAssociation.table.c.id ) & ( model.LibraryDatasetDatasetAssociation.table.c.visible == True ) ), + remote_side=[model.LibraryDatasetDatasetAssociation.table.c.id]), extended_metadata=relation( model.ExtendedMetadata, primaryjoin=( ( model.LibraryDatasetDatasetAssociation.table.c.extended_metadata_id == model.ExtendedMetadata.table.c.id ) ) https://bitbucket.org/galaxy/galaxy-central/commits/1374a75dfeb1/ Changeset: 1374a75dfeb1 User: dannon Date: 2015-02-17 14:16:11+00:00 Summary: Merge. Affected #: 11 files diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e .hgtags --- a/.hgtags +++ b/.hgtags @@ -22,4 +22,4 @@ 2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06 782fa60fc65488aea0c618d723e9a63d42caf865 latest_2014.10.06 2e8dd2949dd3eee0f56f9a3a5ebf1b2baca24aee release_2015.01.13 -577b270034b48d90e58ffbea296e700d229545c9 latest_2015.01.13 +d677cb314dccedd8743eba26f1d446cdf97ebf16 latest_2015.01.13 diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -443,7 +443,7 @@ @web.require_admin def import_workflow( self, trans, workflow_name, repository_id, **kwd ): """Import a workflow contained in an installed tool shed repository into Galaxy.""" - message = escape( kwd.get( 'message', '' ) ) + message = str( escape( kwd.get( 'message', '' ) ) ) status = kwd.get( 'status', 'done' ) if workflow_name: workflow_name = encoding_util.tool_shed_decode( workflow_name ) @@ -480,7 +480,7 @@ tool shed repository. """ # Get the tool_shed_repository from one of the tool_dependencies. - message = escape( kwd.get( 'message', '' ) ) + message = str( escape( kwd.get( 'message', '' ) ) ) status = kwd.get( 'status', 'done' ) err_msg = '' tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/galaxy/controllers/library_admin.py --- a/lib/galaxy/webapps/galaxy/controllers/library_admin.py +++ b/lib/galaxy/webapps/galaxy/controllers/library_admin.py @@ -162,14 +162,14 @@ library.root_folder = root_folder trans.sa_session.add_all( ( library, root_folder ) ) trans.sa_session.flush() - message = "The new library named '%s' has been created" % library.name + message = "The new library named '%s' has been created" % escape( library.name ) return trans.response.send_redirect( web.url_for( controller='library_common', action='browse_library', cntrller='library_admin', id=trans.security.encode_id( library.id ), message=message, status='done' ) ) - return trans.fill_template( '/admin/library/new_library.mako', message=escape( message ), status=escape( status ) ) + return trans.fill_template( '/admin/library/new_library.mako', message=message, status=escape( status ) ) @web.expose @web.require_admin def delete_library( self, trans, id, **kwd ): @@ -222,7 +222,7 @@ trans.sa_session.add( library_folder ) trans.sa_session.flush() if not library.deleted: - message = "Library '%s' has not been marked deleted, so it cannot be purged" % ( library.name ) + message = "Library '%s' has not been marked deleted, so it cannot be purged" % escape( library.name ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_libraries', message=message, @@ -232,7 +232,7 @@ library.purged = True trans.sa_session.add( library ) trans.sa_session.flush() - message = "Library '%s' and all of its contents have been purged, datasets will be removed from disk via the cleanup_datasets script" % library.name + message = "Library '%s' and all of its contents have been purged, datasets will be removed from disk via the cleanup_datasets script" % escape( library.name ) return trans.response.send_redirect( web.url_for( controller='library_admin', action='browse_libraries', message=message, diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/galaxy/controllers/library_common.py --- a/lib/galaxy/webapps/galaxy/controllers/library_common.py +++ b/lib/galaxy/webapps/galaxy/controllers/library_common.py @@ -248,7 +248,7 @@ trans.sa_session.refresh( library ) # Copy the permissions to the root folder trans.app.security_agent.copy_library_permissions( trans, library, library.root_folder ) - message = "Permissions updated for library '%s'." % library.name + message = "Permissions updated for library '%s'." % escape( library.name ) return trans.response.send_redirect( web.url_for( controller='library_common', action='library_permissions', cntrller=cntrller, @@ -310,7 +310,7 @@ if info_association and ( not( inherited ) or info_association.inheritable ): widgets = new_folder.get_template_widgets( trans ) if info_association: - message = "The new folder named '%s' has been added to the data library. " % new_folder.name + message = "The new folder named '%s' has been added to the data library. " % escape( new_folder.name ) message += "Additional information about this folder may be added using the inherited template." return trans.fill_template( '/library/common/folder_info.mako', cntrller=cntrller, @@ -325,7 +325,7 @@ message=escape( message ), status='done' ) # If not inheritable info_association, redirect to the library. - message = "The new folder named '%s' has been added to the data library." % new_folder.name + message = "The new folder named '%s' has been added to the data library." % escape( new_folder.name ) # SM: This is the second place where the API controller would # reference the library id: return trans.response.send_redirect( web.url_for( controller='library_common', @@ -373,7 +373,7 @@ folder.description = new_description trans.sa_session.add( folder ) trans.sa_session.flush() - message = "Information updated for folder '%s'." % folder.name + message = "Information updated for folder '%s'." % escape( folder.name ) return trans.response.send_redirect( web.url_for( controller='library_common', action='folder_info', cntrller=cntrller, @@ -429,7 +429,7 @@ permissions[ trans.app.security_agent.get_action( v.action ) ] = in_roles trans.app.security_agent.set_all_library_permissions( trans, folder, permissions ) trans.sa_session.refresh( folder ) - message = "Permissions updated for folder '%s'." % folder.name + message = "Permissions updated for folder '%s'." % escape( folder.name ) return trans.response.send_redirect( web.url_for( controller='library_common', action='folder_permissions', cntrller=cntrller, @@ -498,10 +498,10 @@ if ldda.datatype.allow_datatype_change and trans.app.datatypes_registry.get_datatype_by_extension( kwd.get( 'datatype' ) ).allow_datatype_change: trans.app.datatypes_registry.change_datatype( ldda, kwd.get( 'datatype' ) ) trans.sa_session.flush() - message = "Data type changed for library dataset '%s'." % ldda.name + message = "Data type changed for library dataset '%s'." % escape( ldda.name ) status = 'done' else: - message = "You are unable to change datatypes in this manner. Changing %s to %s is not allowed." % ( ldda.extension, kwd.get( 'datatype' ) ) + message = "You are unable to change datatypes in this manner. Changing %s to %s is not allowed." % ( escape( ldda.extension ), escape( kwd.get( 'datatype' ) ) ) status = 'error' else: message = "This dataset is currently being used as input or output. You cannot change datatype until the jobs have completed or you have canceled them." @@ -532,7 +532,7 @@ setattr( ldda.metadata, name, spec.unwrap( kwd.get( name, None ) ) ) ldda.metadata.dbkey = dbkey ldda.datatype.after_setting_metadata( ldda ) - message = "Attributes updated for library dataset '%s'." % ldda.name + message = "Attributes updated for library dataset '%s'." % escape( ldda.name ) status = 'done' else: message = "Attributes updated, but metadata could not be changed because this dataset is currently being used as input or output. You must cancel or wait for these jobs to complete before changing metadata." @@ -546,7 +546,7 @@ if name not in [ 'name', 'info', 'dbkey' ]: if spec.get( 'default' ): setattr( ldda.metadata, name, spec.unwrap( spec.get( 'default' ) ) ) - message = "Attributes have been queued to be updated for library dataset '%s'." % ldda.name + message = "Attributes have been queued to be updated for library dataset '%s'." % escape( ldda.name ) status = 'done' trans.app.datatypes_registry.set_external_metadata_tool.tool_action.execute( trans.app.datatypes_registry.set_external_metadata_tool, trans, incoming = { 'input1':ldda } ) else: @@ -570,7 +570,7 @@ self.delete_extended_metadata(trans, ex_obj) ex_obj = self.create_extended_metadata(trans, payload) self.set_item_extended_metadata_obj(trans, ldda, ex_obj) - message = "Updated Extended metadata '%s'." % ldda.name + message = "Updated Extended metadata '%s'." % escape( ldda.name ) status = 'done' else: message = "LDDA not found" @@ -581,7 +581,7 @@ if ex_obj is not None: self.unset_item_extended_metadata_obj(trans, ldda) self.delete_extended_metadata(trans, ex_obj) - message = "Deleted Extended metadata '%s'." % ldda.name + message = "Deleted Extended metadata '%s'." % escape( ldda.name ) status = 'done' @@ -658,7 +658,7 @@ @web.expose def ldda_permissions( self, trans, cntrller, library_id, folder_id, id, **kwd ): - message = escape( kwd.get( 'message', '' ) ) + message = str( escape( kwd.get( 'message', '' ) ) ) status = kwd.get( 'status', 'done' ) show_deleted = util.string_as_bool( kwd.get( 'show_deleted', False ) ) use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) ) @@ -744,7 +744,7 @@ trans.app.security_agent.set_all_library_permissions( trans, ldda, permissions ) trans.sa_session.refresh( ldda ) if len( lddas ) == 1: - message = "Permissions updated for dataset '%s'." % ldda.name + message = "Permissions updated for dataset '%s'." % escape( ldda.name ) else: message = 'Permissions updated for %d datasets.' % len( lddas ) status= 'done' @@ -937,13 +937,13 @@ ldda_id_list = [ str( v.id ) for k, v in created_outputs_dict.items() ] created_ldda_ids=",".join( ldda_id_list ) if replace_dataset: - message = "Added %d dataset versions to the library dataset '%s' in the folder '%s'." % ( total_added, replace_dataset_name, folder.name ) + message = "Added %d dataset versions to the library dataset '%s' in the folder '%s'." % ( total_added, escape( replace_dataset_name ), escape( folder.name ) ) else: if not folder.parent: # Libraries have the same name as their root_folder - message = "Added %d datasets to the library '%s' (each is selected). " % ( total_added, folder.name ) + message = "Added %d datasets to the library '%s' (each is selected). " % ( total_added, escape( folder.name ) ) else: - message = "Added %d datasets to the folder '%s' (each is selected). " % ( total_added, folder.name ) + message = "Added %d datasets to the folder '%s' (each is selected). " % ( total_added, escape( folder.name ) ) if cntrller == 'library_admin': message += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." status='done' @@ -1399,13 +1399,13 @@ ldda_id_list = created_ldda_ids.split( ',' ) total_added = len( ldda_id_list ) if replace_dataset: - message = "Added %d dataset versions to the library dataset '%s' in the folder '%s'." % ( total_added, replace_dataset.name, folder.name ) + message = "Added %d dataset versions to the library dataset '%s' in the folder '%s'." % ( total_added, escape( replace_dataset.name ), escape( folder.name ) ) else: if not folder.parent: # Libraries have the same name as their root_folder - message = "Added %d datasets to the library '%s' (each is selected). " % ( total_added, folder.name ) + message = "Added %d datasets to the library '%s' (each is selected). " % ( total_added, escape( folder.name ) ) else: - message = "Added %d datasets to the folder '%s' (each is selected). " % ( total_added, folder.name ) + message = "Added %d datasets to the folder '%s' (each is selected). " % ( total_added, escape( folder.name ) ) if cntrller == 'library_admin': message += "Click the Go button at the bottom of this page to edit the permissions on these datasets if necessary." else: @@ -1591,7 +1591,7 @@ library_dataset.info = new_info trans.sa_session.add( library_dataset ) trans.sa_session.flush() - message = "Information updated for library dataset '%s'." % library_dataset.name + message = "Information updated for library dataset '%s'." % escape( library_dataset.name ) status = 'done' # See if we have any associated templates widgets = [] @@ -1648,7 +1648,7 @@ # Set the LIBRARY permissions on the LibraryDatasetDatasetAssociation trans.app.security_agent.set_all_library_permissions( trans, library_dataset.library_dataset_dataset_association, permissions ) trans.sa_session.refresh( library_dataset.library_dataset_dataset_association ) - message = "Permisisons updated for library dataset '%s'." % library_dataset.name + message = "Permisisons updated for library dataset '%s'." % escape( library_dataset.name ) status = 'done' roles = trans.app.security_agent.get_legitimate_roles( trans, library_dataset, cntrller ) return trans.fill_template( '/library/common/library_dataset_permissions.mako', @@ -1677,23 +1677,23 @@ contents = util.string_as_bool( kwd.get( 'contents', 'False' ) ) trans.app.security_agent.make_library_public( library, contents=contents ) if contents: - message = "The data library (%s) and all its contents have been made publicly accessible." % library.name + message = "The data library (%s) and all its contents have been made publicly accessible." % escape( library.name ) else: - message = "The data library (%s) has been made publicly accessible, but access to its contents has been left unchanged." % library.name + message = "The data library (%s) has been made publicly accessible, but access to its contents has been left unchanged." % escape( library.name ) elif item_type == 'folder': folder = trans.sa_session.query( trans.model.LibraryFolder ).get( trans.security.decode_id( id ) ) self._check_access( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) self._check_manage( trans, cntrller, is_admin, folder, current_user_roles, use_panels, library_id, show_deleted ) trans.app.security_agent.make_folder_public( folder ) - message = "All of the contents of folder (%s) have been made publicly accessible." % folder.name + message = "All of the contents of folder (%s) have been made publicly accessible." % escape( folder.name ) elif item_type == 'ldda': ldda = trans.sa_session.query( trans.model.LibraryDatasetDatasetAssociation ).get( trans.security.decode_id( id ) ) self._check_access( trans, cntrller, is_admin, ldda.library_dataset, current_user_roles, use_panels, library_id, show_deleted ) self._check_manage( trans, cntrller, is_admin, ldda.library_dataset, current_user_roles, use_panels, library_id, show_deleted ) trans.app.security_agent.make_dataset_public( ldda.dataset ) - message = "The libary dataset (%s) has been made publicly accessible." % ldda.name + message = "The libary dataset (%s) has been made publicly accessible." % escape( ldda.name ) else: - message = "Invalid item_type (%s) received." % str( item_type ) + message = "Invalid item_type (%s) received." % escape( str( item_type ) ) status = 'error' return trans.response.send_redirect( web.url_for( controller='library_common', action='browse_library', @@ -1803,7 +1803,7 @@ if invalid_lddas: message += "You are not authorized to manage permissions on %s: " % inflector.cond_plural( len( invalid_lddas ), "dataset" ) for ldda in invalid_lddas: - message += '(%s)' % ldda.name + message += '(%s)' % escape( ldda.name ) message += '. ' if valid_ldda_ids: encoded_ldda_ids = [ trans.security.encode_id( ldda_id ) for ldda_id in valid_ldda_ids ] @@ -1967,7 +1967,7 @@ return archive.stream else: status = 'error' - message = 'Invalid action (%s) specified.' % str( action ) + message = 'Invalid action (%s) specified.' % escape( str( action ) ) if library_id: # If we have a library_id, browse the associated library return trans.response.send_redirect( web.url_for( controller='library_common', @@ -2053,11 +2053,11 @@ status = 'error' invalid_datasets += 1 elif ldda.dataset.state not in [ trans.model.Dataset.states.OK, trans.model.Dataset.states.ERROR ]: - message += "You cannot import dataset '%s' since its state is '%s'. " % ( ldda.name, ldda.dataset.state ) + message += "You cannot import dataset '%s' since its state is '%s'. " % ( escape( ldda.name ), ldda.dataset.state ) status = 'error' invalid_datasets += 1 elif not ldda.has_data(): - message += "You cannot import empty dataset '%s'. " % ldda.name + message += "You cannot import empty dataset '%s'. " % escape( ldda.name ) status = 'error' invalid_datasets += 1 else: @@ -2140,7 +2140,7 @@ except ValueError: return None if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, item ) ): - message = "You are not authorized to modify %s '%s'." % ( item_desc, item.name ) + message = "You are not authorized to modify %s '%s'." % ( escape( item_desc ), escape( item.name ) ) return trans.response.send_redirect( web.url_for( controller='library_common', action='browse_library', cntrller=cntrller, @@ -2151,9 +2151,9 @@ info_association, inherited = item.get_info_association( restrict=True ) if info_association: if info_association.inheritable: - message = "The template for this %s will no longer be inherited to contained folders and datasets." % item_desc + message = "The template for this %s will no longer be inherited to contained folders and datasets." % escape( item_desc ) else: - message = "The template for this %s will now be inherited to contained folders and datasets." % item_desc + message = "The template for this %s will now be inherited to contained folders and datasets." % escape( item_desc ) info_association.inheritable = not( info_association.inheritable ) trans.sa_session.add( info_association ) trans.sa_session.flush() @@ -2260,7 +2260,7 @@ elif invalid_lddas: message += "You are not authorized to move %s: " % inflector.cond_plural( len( invalid_lddas ), "dataset" ) for ldda in invalid_lddas: - message += '(%s)' % ldda.name + message += '(%s)' % escape( ldda.name ) message += '. ' num_source = len( move_ldda_ids ) - invalid_items message = "%i %s moved to folder (%s) within data library (%s)" % ( num_source, @@ -2278,9 +2278,9 @@ move_folder.parent = target_folder trans.sa_session.add( move_folder ) flush_required = True - message = "Moved folder (%s) to folder (%s) within data library (%s) " % ( move_folder.name, - target_folder.name, - target_library.name ) + message = "Moved folder (%s) to folder (%s) within data library (%s) " % ( escape( move_folder.name ), + escape( target_folder.name ), + escape( target_library.name ) ) if flush_required: trans.sa_session.flush() if target_library: @@ -2400,7 +2400,7 @@ is_admin = ( trans.user_is_admin() and cntrller == 'library_admin' ) current_user_roles = trans.get_current_user_roles() if item_type not in item_types: - message = 'Bad item_type specified: %s' % str( item_type ) + message = 'Bad item_type specified: %s' % escape( str( item_type ) ) status = 'error' else: if item_type == 'library_dataset': @@ -2430,12 +2430,12 @@ if flush_needed: trans.sa_session.flush() if valid_items: - message += "%d %s marked deleted. " % ( valid_items, inflector.cond_plural( valid_items, item_desc ) ) + message += "%d %s marked deleted. " % ( valid_items, escape( inflector.cond_plural( valid_items, item_desc ) ) ) if invalid_items: - message += '%d invalid %s specifield. ' % ( invalid_items, inflector.cond_plural( invalid_items, item_desc ) ) + message += '%d invalid %s specifield. ' % ( invalid_items, escape( inflector.cond_plural( invalid_items, item_desc ) ) ) status = 'error' if not_authorized_items: - message += 'You are not authorized to delete %d %s. ' % ( not_authorized_items, inflector.cond_plural( not_authorized_items, item_desc ) ) + message += 'You are not authorized to delete %d %s. ' % ( not_authorized_items, escape( inflector.cond_plural( not_authorized_items, item_desc ) ) ) status = 'error' if item_type == 'library': return trans.response.send_redirect( web.url_for( controller=cntrller, @@ -2462,7 +2462,7 @@ is_admin = ( trans.user_is_admin() and cntrller == 'library_admin' ) current_user_roles = trans.get_current_user_roles() if item_type not in item_types: - message = 'Bad item_type specified: %s' % str( item_type ) + message = 'Bad item_type specified: %s' % escape( str( item_type ) ) status = 'error' else: if item_type == 'library_dataset': @@ -2496,15 +2496,15 @@ if flush_needed: trans.sa_session.flush() if valid_items: - message += "%d %s marked undeleted. " % ( valid_items, inflector.cond_plural( valid_items, item_desc ) ) + message += "%d %s marked undeleted. " % ( valid_items, escape( inflector.cond_plural( valid_items, item_desc ) ) ) if invalid_items: - message += '%d invalid %s specifield. ' % ( invalid_items, inflector.cond_plural( invalid_items, item_desc ) ) + message += '%d invalid %s specifield. ' % ( invalid_items, escape( inflector.cond_plural( invalid_items, item_desc ) ) ) status = 'error' if not_authorized_items: - message += 'You are not authorized to undelete %d %s. ' % ( not_authorized_items, inflector.cond_plural( not_authorized_items, item_desc ) ) + message += 'You are not authorized to undelete %d %s. ' % ( not_authorized_items, escape( inflector.cond_plural( not_authorized_items, item_desc ) ) ) status = 'error' if purged_items: - message += '%d %s marked purged, so cannot be undeleted. ' % ( purged_items, inflector.cond_plural( purged_items, item_desc ) ) + message += '%d %s marked purged, so cannot be undeleted. ' % ( purged_items, escape( inflector.cond_plural( purged_items, item_desc ) ) ) status = 'error' if item_type == 'library': return trans.response.send_redirect( web.url_for( controller=cntrller, @@ -2525,7 +2525,7 @@ if isinstance( item, trans.model.HistoryDatasetAssociation ): # Make sure the user has the DATASET_ACCESS permission on the history_dataset_association. if not item: - message = "Invalid history dataset (%s) specified." % str( item ) + message = "Invalid history dataset (%s) specified." % escape( str( item ) ) can_access = False elif not trans.app.security_agent.can_access_dataset( current_user_roles, item.dataset ) and item.history.user==trans.user: message = "You do not have permission to access the history dataset with id (%s)." % str( item.id ) @@ -2533,7 +2533,7 @@ else: # Make sure the user has the LIBRARY_ACCESS permission on the library item. if not item: - message = "Invalid library item (%s) specified." % str( item ) + message = "Invalid library item (%s) specified." % escape( str( item ) ) can_access = False elif not ( is_admin or trans.app.security_agent.can_access_library_item( current_user_roles, item, trans.user ) ): if isinstance( item, trans.model.Library ): @@ -2542,7 +2542,7 @@ item_type = 'folder' else: item_type = '(unknown item type)' - message = "You do not have permission to access the %s with id (%s)." % ( item_type, str( item.id ) ) + message = "You do not have permission to access the %s with id (%s)." % ( escape( item_type ), str( item.id ) ) can_access = False if not can_access: if cntrller == 'api': @@ -2566,7 +2566,7 @@ def _check_add( self, trans, cntrller, is_admin, item, current_user_roles, use_panels, library_id, show_deleted ): # Deny access if the user is not an admin and does not have the LIBRARY_ADD permission. if not ( is_admin or trans.app.security_agent.can_add_library_item( current_user_roles, item ) ): - message = "You are not authorized to add an item to (%s)." % item.name + message = "You are not authorized to add an item to (%s)." % escape( item.name ) # Redirect to the real parent library since we know we have access to it. if cntrller == 'api': return 403, message @@ -2585,7 +2585,7 @@ if not ( is_admin or \ ( trans.app.security_agent.can_manage_library_item( current_user_roles, item ) and trans.app.security_agent.can_manage_dataset( current_user_roles, library_dataset.library_dataset_dataset_association.dataset ) ) ): - message = "You are not authorized to manage permissions on library dataset (%s)." % library_dataset.name + message = "You are not authorized to manage permissions on library dataset (%s)." % escape( library_dataset.name ) if cntrller == 'api': return 403, message return trans.response.send_redirect( web.url_for( controller='library_common', @@ -2597,7 +2597,7 @@ status='error' ) ) # Deny access if the user is not an admin and does not have the LIBRARY_MANAGE permission. if not ( is_admin or trans.app.security_agent.can_manage_library_item( current_user_roles, item ) ): - message = "You are not authorized to manage permissions on (%s)." % item.name + message = "You are not authorized to manage permissions on (%s)." % escape( item.name ) if cntrller == 'api': return 403, message return trans.response.send_redirect( web.url_for( controller='library_common', @@ -2611,7 +2611,7 @@ def _check_modify( self, trans, cntrller, is_admin, item, current_user_roles, use_panels, library_id, show_deleted ): # Deny modification if the user is not an admin and does not have the LIBRARY_MODIFY permission. if not ( is_admin or trans.app.security_agent.can_modify_library_item( current_user_roles, item ) ): - message = "You are not authorized to modify (%s)." % item.name + message = "You are not authorized to modify (%s)." % escape( item.name ) if cntrller == 'api': return 403, message return trans.response.send_redirect( web.url_for( controller='library_common', diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/galaxy/controllers/user.py --- a/lib/galaxy/webapps/galaxy/controllers/user.py +++ b/lib/galaxy/webapps/galaxy/controllers/user.py @@ -574,7 +574,7 @@ username = trans.user.username is_activation_sent = self.send_verification_email( trans, email, username ) if is_activation_sent: - message = 'This account has not been activated yet. The activation link has been sent again. Please check your email address <b>%s</b> including the spam/trash folder.<br><a target="_top" href="%s">Return to the home page</a>.' % ( email, url_for( '/' ) ) + message = 'This account has not been activated yet. The activation link has been sent again. Please check your email address <b>%s</b> including the spam/trash folder.<br><a target="_top" href="%s">Return to the home page</a>.' % ( escape( email ), url_for( '/' ) ) status = 'error' else: message = 'This account has not been activated yet but we are unable to send the activation link. Please contact your local Galaxy administrator.<br><a target="_top" href="%s">Return to the home page</a>.' % url_for( '/' ) @@ -678,7 +678,7 @@ trans.log_event( "User created a new account" ) trans.log_event( "User logged in" ) if success and is_admin: - message = 'Created new user account (%s)' % user.email + message = 'Created new user account (%s)' % escape( user.email ) trans.response.send_redirect( web.url_for( controller='admin', action='users', cntrller=cntrller, @@ -775,7 +775,7 @@ if trans.webapp.name == 'galaxy' and trans.app.config.user_activation_on: is_activation_sent = self.send_verification_email( trans, email, username ) if is_activation_sent: - message = 'Now logged in as %s.<br>Verification email has been sent to your email address. Please verify it by clicking the activation link in the email.<br>Please check your spam/trash folder in case you cannot find the message.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) ) + message = 'Now logged in as %s.<br>Verification email has been sent to your email address. Please verify it by clicking the activation link in the email.<br>Please check your spam/trash folder in case you cannot find the message.<br><a target="_top" href="%s">Return to the home page.</a>' % ( escape( user.email ), url_for( '/' ) ) success = True else: message = 'Unable to send activation email, please contact your local Galaxy administrator.' @@ -783,7 +783,7 @@ message += ' Contact: %s' % trans.app.config.error_email_to success = False else: # User activation is OFF, proceed without sending the activation email. - message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( user.email, url_for( '/' ) ) + message = 'Now logged in as %s.<br><a target="_top" href="%s">Return to the home page.</a>' % ( escape( user.email ), url_for( '/' ) ) success = True return ( message, status, user, success ) @@ -793,7 +793,7 @@ """ if username is None: username = trans.user.username - activation_link = self.prepare_activation_link( trans, email ) + activation_link = self.prepare_activation_link( trans, escape( email ) ) body = ("Hello %s,\n\n" "In order to complete the activation process for %s begun on %s at %s, please click on the following link to verify your account:\n\n" @@ -801,7 +801,7 @@ "By clicking on the above link and opening a Galaxy account you are also confirming that you have read and agreed to Galaxy's Terms and Conditions for use of this service (%s). This includes a quota limit of one account per user. Attempts to subvert this limit by creating multiple accounts or through any other method may result in termination of all associated accounts and data.\n\n" "Please contact us if you need help with your account at: %s. You can also browse resources available at: %s. \n\n" "More about the Galaxy Project can be found at galaxyproject.org\n\n" - "Your Galaxy Team" % (username, email, + "Your Galaxy Team" % (escape( username ), escape( email ), datetime.utcnow().strftime( "%D"), trans.request.host, activation_link, trans.app.config.terms_url, @@ -1178,7 +1178,7 @@ if not username: return "A public user name is required in the tool shed." if username in [ 'repos' ]: - return "The term <b>%s</b> is a reserved word in the tool shed, so it cannot be used as a public user name." % username + return "The term <b>%s</b> is a reserved word in the tool shed, so it cannot be used as a public user name." % escape( username ) message = "\n".join( [ validate_email( trans, email ), validate_password( trans, password, confirm ), validate_publicname( trans, username ) ] ).rstrip() diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/galaxy/controllers/workflow.py --- a/lib/galaxy/webapps/galaxy/controllers/workflow.py +++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py @@ -826,7 +826,7 @@ """ url = kwd.get( 'url', '' ) workflow_text = kwd.get( 'workflow_text', '' ) - message = escape( kwd.get( 'message', '' ) ) + message = str( escape( kwd.get( 'message', '' ) ) ) status = kwd.get( 'status', 'done' ) import_button = kwd.get( 'import_button', False ) # The special Galaxy integration landing page's URL on myExperiment diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/tool_shed/controllers/admin.py --- a/lib/galaxy/webapps/tool_shed/controllers/admin.py +++ b/lib/galaxy/webapps/tool_shed/controllers/admin.py @@ -140,7 +140,7 @@ trans.sa_session.flush() # Update the Tool Shed's repository registry. trans.app.repository_registry.add_category_entry( category ) - message = "Category '%s' has been created" % category.name + message = "Category '%s' has been created" % escape( category.name ) status = 'done' trans.response.send_redirect( web.url_for( controller='admin', action='manage_categories', @@ -184,7 +184,7 @@ count += 1 deleted_repositories += " %s " % repository.name if count: - message = "Deleted %d %s: %s" % ( count, inflector.cond_plural( len( ids ), "repository" ), deleted_repositories ) + message = "Deleted %d %s: %s" % ( count, inflector.cond_plural( len( ids ), "repository" ), escape( deleted_repositories ) ) else: message = "All selected repositories were already marked deleted." else: @@ -258,7 +258,7 @@ if original_category_name != new_name: # Update the Tool Shed's repository registry. trans.app.repository_registry.edit_category_entry( original_category_name, new_name ) - message = "The information has been saved for category '%s'" % ( category.name ) + message = "The information has been saved for category '%s'" % escape( category.name ) status = 'done' return trans.response.send_redirect( web.url_for( controller='admin', action='manage_categories', @@ -431,7 +431,7 @@ trans.sa_session.flush() # Update the Tool Shed's repository registry. trans.app.repository_registry.remove_category_entry( category ) - message += " %s " % category.name + message += " %s " % escape( category.name ) else: message = "No category ids received for deleting." status = 'error' @@ -462,7 +462,7 @@ trans.sa_session.delete( rca ) trans.sa_session.flush() purged_categories += " %s " % category.name - message = "Purged %d categories: %s" % ( count, purged_categories ) + message = "Purged %d categories: %s" % ( count, escape( purged_categories ) ) else: message = "No category ids received for purging." status = 'error' @@ -491,7 +491,7 @@ trans.app.repository_registry.add_category_entry( category ) count += 1 undeleted_categories += " %s" % category.name - message = "Undeleted %d categories: %s" % ( count, undeleted_categories ) + message = "Undeleted %d categories: %s" % ( count, escape( undeleted_categories ) ) else: message = "No category ids received for undeleting." status = 'error' diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/tool_shed/controllers/repository.py --- a/lib/galaxy/webapps/tool_shed/controllers/repository.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py @@ -1126,11 +1126,11 @@ if mark_deprecated: # Update the repository registry. trans.app.repository_registry.remove_entry( repository ) - message = 'The repository <b>%s</b> has been marked as deprecated.' % repository.name + message = 'The repository <b>%s</b> has been marked as deprecated.' % escape( repository.name ) else: # Update the repository registry. trans.app.repository_registry.add_entry( repository ) - message = 'The repository <b>%s</b> has been marked as not deprecated.' % repository.name + message = 'The repository <b>%s</b> has been marked as not deprecated.' % escape( repository.name ) trans.response.send_redirect( web.url_for( controller='repository', action='browse_repositories', operation='repositories_i_own', @@ -1388,8 +1388,8 @@ else: kwd[ 'message' ] = "tool id: <b>%s</b><br/>tool name: <b>%s</b><br/>tool version: <b>%s</b><br/>exact matches only: <b>%s</b>" % \ ( basic_util.stringify( tool_ids ), - basic_util.stringify( tool_names ), - basic_util.stringify( tool_versions ), + escape( basic_util.stringify( tool_names ) ), + escape( basic_util.stringify( tool_versions ) ), str( exact_matches_checked ) ) self.matched_repository_grid.title = "Repositories with matching tools" return self.matched_repository_grid( trans, **kwd ) @@ -1479,7 +1479,7 @@ return self.install_matched_repository_grid( trans, **kwd ) else: kwd[ 'message' ] = "workflow name: <b>%s</b><br/>exact matches only: <b>%s</b>" % \ - ( basic_util.stringify( workflow_names ), str( exact_matches_checked ) ) + ( escape( basic_util.stringify( workflow_names ) ), str( exact_matches_checked ) ) self.matched_repository_grid.title = "Repositories with matching workflows" return self.matched_repository_grid( trans, **kwd ) else: @@ -3076,7 +3076,7 @@ changeset_revision=changeset_revision ) ) else: message = "The change log for the repository named <b>%s</b> owned by <b>%s</b> does not include revision <b>%s</b>." % \ - ( str( name ), str( owner ), str( changeset_revision ) ) + ( escape( str( name ) ), escape( str( owner ) ), escape( str( changeset_revision ) ) ) return trans.response.send_redirect( web.url_for( controller='repository', action='index', repository_id=repository_id, diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/tool_shed/controllers/repository_review.py --- a/lib/galaxy/webapps/tool_shed/controllers/repository_review.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository_review.py @@ -51,7 +51,7 @@ review.approved = approved_select_field_value trans.sa_session.add( review ) trans.sa_session.flush() - message = 'Approved value <b>%s</b> saved for this revision.' % approved_select_field_value + message = 'Approved value <b>%s</b> saved for this revision.' % escape( approved_select_field_value ) repository_id = trans.security.encode_id( review.repository_id ) changeset_revision = review.changeset_revision return trans.response.send_redirect( web.url_for( controller='repository_review', @@ -121,7 +121,7 @@ component = trans.app.model.Component( name=name, description=description ) trans.sa_session.add( component ) trans.sa_session.flush() - message = "Component '%s' has been created" % component.name + message = "Component '%s' has been created" % escape( component.name ) status = 'done' trans.response.send_redirect( web.url_for( controller='repository_review', action='manage_components', @@ -151,7 +151,7 @@ repository_id=repository_id, changeset_revision=changeset_revision, user_id=trans.security.encode_id( trans.user.id ) ): - message = "You have already created a review for revision <b>%s</b> of repository <b>%s</b>." % ( changeset_revision, repository.name ) + message = "You have already created a review for revision <b>%s</b> of repository <b>%s</b>." % ( changeset_revision, escape( repository.name ) ) status = "error" else: # See if there are any reviews for previous changeset revisions that the user can copy. @@ -188,7 +188,7 @@ status=status ) ) else: message = "A new review cannot be created for revision <b>%s</b> of repository <b>%s</b>. Select a valid revision and try again." \ - % ( changeset_revision, repository.name ) + % ( changeset_revision, escape( repository.name ) ) kwd[ 'message' ] = message kwd[ 'status' ] = 'error' else: @@ -218,7 +218,7 @@ component.description = new_description trans.sa_session.add( component ) trans.sa_session.flush() - message = "The information has been saved for the component named <b>%s</b>" % ( component.name ) + message = "The information has been saved for the component named <b>%s</b>" % escape( component.name ) status = 'done' return trans.response.send_redirect( web.url_for( controller='repository_review', action='manage_components', diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/galaxy/webapps/tool_shed/controllers/upload.py --- a/lib/galaxy/webapps/tool_shed/controllers/upload.py +++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py @@ -256,7 +256,7 @@ source_type = "file" source = uploaded_file_filename message = "The %s <b>%s</b> has been successfully%suploaded to the repository. " % \ - ( source_type, source, uncompress_str ) + ( source_type, escape( source ), uncompress_str ) if istar and ( undesirable_dirs_removed or undesirable_files_removed ): items_removed = undesirable_dirs_removed + undesirable_files_removed message += " %d undesirable items (.hg .svn .git directories, .DS_Store, hgrc files, etc) " % items_removed diff -r 17dd62d9a0b0614f5b7fd1fbf360450855c7ab18 -r 1374a75dfeb17af8913e4fffa8b6f11bdf6f668e lib/tool_shed/util/repository_util.py --- a/lib/tool_shed/util/repository_util.py +++ b/lib/tool_shed/util/repository_util.py @@ -167,7 +167,7 @@ sa_session.flush() # Update the repository registry. app.repository_registry.add_entry( repository ) - message = "Repository <b>%s</b> has been created." % str( repository.name ) + message = "Repository <b>%s</b> has been created." % escape( str( repository.name ) ) return repository, message def create_repository_admin_role( app, repository ): @@ -285,7 +285,7 @@ repositories=in_repositories ) sa_session.refresh( role ) message += "Role <b>%s</b> has been associated with %d users, %d groups and %d repositories. " % \ - ( str( role.name ), len( in_users ), len( in_groups ), len( in_repositories ) ) + ( escape( str( role.name ) ), len( in_users ), len( in_groups ), len( in_repositories ) ) in_users = [] out_users = [] in_groups = [] 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.