galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
December 2013
- 1 participants
- 207 discussions
commit/galaxy-central: guerler: Grids: Fix for toolshed grids
by commits-noreply@bitbucket.org 11 Dec '13
by commits-noreply@bitbucket.org 11 Dec '13
11 Dec '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/392469f092a6/
Changeset: 392469f092a6
User: guerler
Date: 2013-12-11 20:58:35
Summary: Grids: Fix for toolshed grids
Affected #: 2 files
diff -r 87101044e7d4bc1d7495c0dfdaf3663339618047 -r 392469f092a67318ed25a4c675e72850e0a8f4b4 templates/webapps/tool_shed/category/grid.mako
--- a/templates/webapps/tool_shed/category/grid.mako
+++ b/templates/webapps/tool_shed/category/grid.mako
@@ -1,3 +1,4 @@
+<%inherit file="/base.mako"/><%namespace name="grid_base" file="/grid_base.mako" import="*" /><%namespace name="grid_common" file="../common/grid_common.mako" import="*" />
@@ -9,5 +10,4 @@
%></%def>
-<!DOCTYPE HTML>
${grid_base.load(False, capture(self.insert))}
\ No newline at end of file
diff -r 87101044e7d4bc1d7495c0dfdaf3663339618047 -r 392469f092a67318ed25a4c675e72850e0a8f4b4 templates/webapps/tool_shed/category/valid_grid.mako
--- a/templates/webapps/tool_shed/category/valid_grid.mako
+++ b/templates/webapps/tool_shed/category/valid_grid.mako
@@ -1,3 +1,4 @@
+<%inherit file="/base.mako"/><%namespace name="grid_base" file="/grid_base.mako" import="*" /><%namespace name="grid_common" file="../common/grid_common.mako" import="*" />
@@ -9,5 +10,4 @@
%></%def>
-<!DOCTYPE HTML>
${grid_base.load(False, capture(self.insert))}
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jgoecks: Remove duplicate JS scripts from grids.
by commits-noreply@bitbucket.org 11 Dec '13
by commits-noreply@bitbucket.org 11 Dec '13
11 Dec '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/87101044e7d4/
Changeset: 87101044e7d4
User: jgoecks
Date: 2013-12-11 20:23:57
Summary: Remove duplicate JS scripts from grids.
Affected #: 1 file
diff -r 42a88bd063ee84f0d1ddb38ddcff564421ed8140 -r 87101044e7d4bc1d7495c0dfdaf3663339618047 templates/grid_base.mako
--- a/templates/grid_base.mako
+++ b/templates/grid_base.mako
@@ -21,7 +21,6 @@
<%
self.init(insert)
self.stylesheets()
- self.javascripts()
self.grid_javascripts()
if embedded:
self.render_grid_header( grid, False )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: inithello: When creating a repository, make sure there are no repositories with the same name, deleted or active.
by commits-noreply@bitbucket.org 11 Dec '13
by commits-noreply@bitbucket.org 11 Dec '13
11 Dec '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/77b5d4888d6d/
Changeset: 77b5d4888d6d
Branch: stable
User: inithello
Date: 2013-12-11 18:43:36
Summary: When creating a repository, make sure there are no repositories with the same name, deleted or active.
Affected #: 2 files
diff -r 9d4cbf2a1c13dd481c10d28a28afb41d23553d18 -r 77b5d4888d6d957d24caccdcd5154bb8cb7574e4 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
@@ -933,7 +933,7 @@
repository_type = kwd.get( 'repository_type', rt_util.UNRESTRICTED )
if kwd.get( 'create_repository_button', False ):
error = False
- message = repository_maintenance_util.validate_repository_name( name, trans.user )
+ message = repository_maintenance_util.validate_repository_name( trans.app, name, trans.user )
if message:
error = True
if not description:
@@ -2070,7 +2070,7 @@
repository.long_description = long_description
flush_needed = True
if repository.times_downloaded == 0 and repo_name != repository.name:
- message = repository_maintenance_util.validate_repository_name( repo_name, user )
+ message = repository_maintenance_util.validate_repository_name( trans.app, repo_name, user )
if message:
error = True
else:
diff -r 9d4cbf2a1c13dd481c10d28a28afb41d23553d18 -r 77b5d4888d6d957d24caccdcd5154bb8cb7574e4 lib/tool_shed/util/repository_maintenance_util.py
--- a/lib/tool_shed/util/repository_maintenance_util.py
+++ b/lib/tool_shed/util/repository_maintenance_util.py
@@ -56,15 +56,18 @@
fp.write( 'hgext.purge=' )
fp.close()
-def validate_repository_name( name, user ):
+def validate_repository_name( app, name, user ):
# Repository names must be unique for each user, must be at least four characters
# in length and must contain only lower-case letters, numbers, and the '_' character.
if name in [ 'None', None, '' ]:
return 'Enter the required repository name.'
if name in [ 'repos' ]:
return "The term <b>%s</b> is a reserved word in the tool shed, so it cannot be used as a repository name." % name
- for repository in user.active_repositories:
- if repository.name == name:
+ check_existing = suc.get_repository_by_name_and_owner( app, name, user.username )
+ if check_existing is not None:
+ if check_existing.deleted:
+ return 'You have a deleted repository named <b>%s</b>, so choose a different name.' % name
+ else:
return "You already have a repository named <b>%s</b>, so choose a different name." % name
if len( name ) < 4:
return "Repository names must be at least 4 characters in length."
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9c5a2c5f560d/
Changeset: 9c5a2c5f560d
User: inithello
Date: 2013-12-11 18:43:36
Summary: When creating a repository, make sure there are no repositories with the same name, deleted or active.
Affected #: 2 files
diff -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 -r 9c5a2c5f560dbd769b44d684f657625563d52022 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
@@ -932,7 +932,7 @@
repository_type = kwd.get( 'repository_type', rt_util.UNRESTRICTED )
if kwd.get( 'create_repository_button', False ):
error = False
- message = repository_maintenance_util.validate_repository_name( name, trans.user )
+ message = repository_maintenance_util.validate_repository_name( trans.app, name, trans.user )
if message:
error = True
if not description:
@@ -2085,7 +2085,7 @@
repository.long_description = long_description
flush_needed = True
if repository.times_downloaded == 0 and repo_name != repository.name:
- message = repository_maintenance_util.validate_repository_name( repo_name, user )
+ message = repository_maintenance_util.validate_repository_name( trans.app, repo_name, user )
if message:
error = True
else:
diff -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 -r 9c5a2c5f560dbd769b44d684f657625563d52022 lib/tool_shed/util/repository_maintenance_util.py
--- a/lib/tool_shed/util/repository_maintenance_util.py
+++ b/lib/tool_shed/util/repository_maintenance_util.py
@@ -137,7 +137,7 @@
results_message += 'This Tool Shed does not have the category <b>%s</b> so it will not be associated with this repository.' % \
str( category_name )
else:
- category_ids.append( trans.security.encode_id( category.id ) )
+ category_ids.append( trans.security.encode_id( category.id ) )
# Create the repository record in the database.
repository, create_message = create_repository( trans,
name,
@@ -157,15 +157,18 @@
import_results_tups.append( ( ( str( name ), str( username ) ), results_message ) )
return import_results_tups
-def validate_repository_name( name, user ):
+def validate_repository_name( app, name, user ):
# Repository names must be unique for each user, must be at least four characters
# in length and must contain only lower-case letters, numbers, and the '_' character.
if name in [ 'None', None, '' ]:
return 'Enter the required repository name.'
if name in [ 'repos' ]:
return "The term <b>%s</b> is a reserved word in the tool shed, so it cannot be used as a repository name." % name
- for repository in user.active_repositories:
- if repository.name == name:
+ check_existing = suc.get_repository_by_name_and_owner( app, name, user.username )
+ if check_existing is not None:
+ if check_existing.deleted:
+ return 'You have a deleted repository named <b>%s</b>, so choose a different name.' % name
+ else:
return "You already have a repository named <b>%s</b>, so choose a different name." % name
if len( name ) < 4:
return "Repository names must be at least 4 characters in length."
https://bitbucket.org/galaxy/galaxy-central/commits/b128bbaf91fc/
Changeset: b128bbaf91fc
Branch: search
User: inithello
Date: 2013-12-11 19:11:43
Summary: Close branch search
Affected #: 0 files
https://bitbucket.org/galaxy/galaxy-central/commits/42a88bd063ee/
Changeset: 42a88bd063ee
User: inithello
Date: 2013-12-11 19:15:36
Summary: Merge in 11692:9c5a2c5f560d
Affected #: 2 files
diff -r 9c5a2c5f560dbd769b44d684f657625563d52022 -r 42a88bd063ee84f0d1ddb38ddcff564421ed8140 lib/galaxy/tools/deps/__init__.py
--- a/lib/galaxy/tools/deps/__init__.py
+++ b/lib/galaxy/tools/deps/__init__.py
@@ -76,6 +76,7 @@
return [
ToolShedPackageDependencyResolver(self),
GalaxyPackageDependencyResolver(self),
+ GalaxyPackageDependencyResolver(self, versionless=True),
]
def __parse_resolver_conf_xml(self, root):
diff -r 9c5a2c5f560dbd769b44d684f657625563d52022 -r 42a88bd063ee84f0d1ddb38ddcff564421ed8140 test/unit/test_tool_deps.py
--- a/test/unit/test_tool_deps.py
+++ b/test/unit/test_tool_deps.py
@@ -42,9 +42,10 @@
dependency = dm.find_dep( "dep1", None )
assert dependency.version == "2.0"
- ## Test default will not be fallen back upon by default
+ ## Test default resolve will be fall back on default package dependency
+ ## when using the default resolver.
dependency = dm.find_dep( "dep1", "2.1" )
- assert dependency == INDETERMINATE_DEPENDENCY
+ assert dependency.version == "2.0" # 2.0 is defined as default_version
TEST_REPO_USER = "devteam"
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/98a91b2610ab/
Changeset: 98a91b2610ab
User: jmchilton
Date: 2013-12-10 16:43:07
Summary: Resolve default package definitions if extact version is unavailable.
Old behavior can be reverted by setting up a dependency_resolvers_conf.xml with the following contents
```
<dependency_resolvers><tool_shed_packages /><galaxy_packages /></dependency_resolvers>
```
The new behavior corresponds to the following dependency_resolvers_conf.xml contents:
```
<dependency_resolvers><tool_shed_packages /><galaxy_packages /><galaxy_packages versionless="true" /></dependency_resolvers>
```
Still think galaxy_packages should come before tool_shed_packages in resolution order so that deployers can fix broken tool shed installs with manual installs or deploy optimized versions of packages without having to mess with a dependency_resolvers_conf.xml file.
Affected #: 2 files
diff -r 3bf805dfa14eb150e90c1aab565eb22b8ab3d9b8 -r 98a91b2610abbffd0a299c6ae9bae075ca5561f4 lib/galaxy/tools/deps/__init__.py
--- a/lib/galaxy/tools/deps/__init__.py
+++ b/lib/galaxy/tools/deps/__init__.py
@@ -76,6 +76,7 @@
return [
ToolShedPackageDependencyResolver(self),
GalaxyPackageDependencyResolver(self),
+ GalaxyPackageDependencyResolver(self, versionless=True),
]
def __parse_resolver_conf_xml(self, tree):
diff -r 3bf805dfa14eb150e90c1aab565eb22b8ab3d9b8 -r 98a91b2610abbffd0a299c6ae9bae075ca5561f4 test/unit/test_tool_deps.py
--- a/test/unit/test_tool_deps.py
+++ b/test/unit/test_tool_deps.py
@@ -42,9 +42,10 @@
dependency = dm.find_dep( "dep1", None )
assert dependency.version == "2.0"
- ## Test default will not be fallen back upon by default
+ ## Test default resolve will be fall back on default package dependency
+ ## when using the default resolver.
dependency = dm.find_dep( "dep1", "2.1" )
- assert dependency == INDETERMINATE_DEPENDENCY
+ assert dependency.version == "2.0" # 2.0 is defined as default_version
TEST_REPO_USER = "devteam"
https://bitbucket.org/galaxy/galaxy-central/commits/7200976bcad7/
Changeset: 7200976bcad7
User: dannon
Date: 2013-12-11 19:11:06
Summary: Merged in jmchilton/galaxy-central-fork-1 (pull request #272)
Resolve default package definitions if exact version is unavailable.
Affected #: 2 files
diff -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 -r 7200976bcad7741fe663f86492824dc5b3e24f50 lib/galaxy/tools/deps/__init__.py
--- a/lib/galaxy/tools/deps/__init__.py
+++ b/lib/galaxy/tools/deps/__init__.py
@@ -76,6 +76,7 @@
return [
ToolShedPackageDependencyResolver(self),
GalaxyPackageDependencyResolver(self),
+ GalaxyPackageDependencyResolver(self, versionless=True),
]
def __parse_resolver_conf_xml(self, root):
diff -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 -r 7200976bcad7741fe663f86492824dc5b3e24f50 test/unit/test_tool_deps.py
--- a/test/unit/test_tool_deps.py
+++ b/test/unit/test_tool_deps.py
@@ -42,9 +42,10 @@
dependency = dm.find_dep( "dep1", None )
assert dependency.version == "2.0"
- ## Test default will not be fallen back upon by default
+ ## Test default resolve will be fall back on default package dependency
+ ## when using the default resolver.
dependency = dm.find_dep( "dep1", "2.1" )
- assert dependency == INDETERMINATE_DEPENDENCY
+ assert dependency.version == "2.0" # 2.0 is defined as default_version
TEST_REPO_USER = "devteam"
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: History panel: small improvements
by commits-noreply@bitbucket.org 11 Dec '13
by commits-noreply@bitbucket.org 11 Dec '13
11 Dec '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7e45d419c54d/
Changeset: 7e45d419c54d
User: carlfeberhard
Date: 2013-12-11 18:59:40
Summary: History panel: small improvements
Affected #: 17 files
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/mvc/dataset/hda-model.js
--- a/static/scripts/mvc/dataset/hda-model.js
+++ b/static/scripts/mvc/dataset/hda-model.js
@@ -503,6 +503,11 @@
return filteredHdas;
},
+ /** return true if any hdas don't have details */
+ haveDetails : function(){
+ return this.all( function( hda ){ return hda.hasDetails(); });
+ },
+
// ........................................................................ ajax
/** fetch detailed model data for all HDAs in this collection */
fetchAllDetails : function( options ){
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/mvc/history/history-model.js
--- a/static/scripts/mvc/history/history-model.js
+++ b/static/scripts/mvc/history/history-model.js
@@ -121,6 +121,10 @@
return !!( user && user.id );
},
+ hdaCount : function(){
+ return _.reduce( _.values( this.get( 'state_details' ) ), function( memo, num ){ return memo + num; }, 0 );
+ },
+
// ........................................................................ ajax
/** does the HDA collection indicate they're still running and need to be updated later? delay + update if needed
* @param {Function} onReadyCallback function to run when all HDAs are in the ready state
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -79,8 +79,8 @@
//logger : console,
/** which class to use for constructing the HDA views */
- //HDAView : hdaBase.HDABaseView,
- HDAView : hdaEdit.HDAEditView,
+ //defaultHDAViewClass : hdaBase.HDABaseView,
+ defaultHDAViewClass : hdaEdit.HDAEditView,
tagName : 'div',
className : 'history-panel',
@@ -107,15 +107,12 @@
this.logger = attributes.logger;
}
this.log( this + '.initialize:', attributes );
-//TODO: pass show_del'd/hidden through
+ // ---- set up instance vars
+ this.HDAViewClass = attributes.HDAViewClass || this.defaultHDAViewClass;
/** where should pages from links be displayed? (default to new tab/window) */
this.linkTarget = attributes.linkTarget || '_blank';
- // set up (non-model related) event handlers
- this._setUpListeners();
-
- // ---- set up instance vars
/** map of hda model ids to hda views */
this.hdaViews = {};
/** loading indicator */
@@ -130,6 +127,8 @@
/** is the panel currently showing the dataset selection controls? */
this.selecting = attributes.selecting || false;
+ this._setUpListeners();
+
// ---- handle models passed on init
if( this.model ){
this._setUpWebStorage( attributes.initiallyExpanded, attributes.show_deleted, attributes.show_hidden );
@@ -559,8 +558,10 @@
} else {
$newRender.append( HistoryPanel.templates.historyPanel( this.model.toJSON() ) );
- this._renderTags( $newRender );
- this._renderAnnotation( $newRender );
+ if( Galaxy.currUser.id && Galaxy.currUser.id === this.model.get( 'user_id' ) ){
+ this._renderTags( $newRender );
+ this._renderAnnotation( $newRender );
+ }
}
// search and select available to both anon/logged-in users
//$newRender.find( '.history-secondary-actions' ).prepend( this._renderSelectButton() );
@@ -622,18 +623,24 @@
$where.find( '[title]' ).tooltip({ placement: 'bottom' });
// anon users shouldn't have access to any of the following
- if( !this.model || !Galaxy.currUser || Galaxy.currUser.isAnonymous() ){ return; }
+ if( ( !this.model )
+ || ( !Galaxy.currUser || Galaxy.currUser.isAnonymous() )
+ || ( Galaxy.currUser.id !== this.model.get( 'user_id' ) ) ){
+ return;
+ }
- var panel = this;//,
- $where.find( '.history-name' ).make_text_editable({
- on_finish: function( newName ){
- $where.find( '.history-name' ).text( newName );
- panel.model.save({ name: newName })
- .fail( function(){
- $where.find( '.history-name' ).text( panel.model.previous( 'name' ) );
- });
- }
- });
+ var panel = this;
+ $where.find( '.history-name' )
+ .attr( 'title', _l( 'Click to rename history' ) ).tooltip({ placement: 'bottom' })
+ .make_text_editable({
+ on_finish: function( newName ){
+ $where.find( '.history-name' ).text( newName );
+ panel.model.save({ name: newName })
+ .fail( function(){
+ $where.find( '.history-name' ).text( panel.model.previous( 'name' ) );
+ });
+ }
+ });
this._setUpDatasetActionsPopup( $where );
},
@@ -721,10 +728,11 @@
createHdaView : function( hda ){
var hdaId = hda.get( 'id' ),
expanded = this.storage.get( 'expandedHdas' )[ hdaId ],
- hdaView = new this.HDAView({
+ hdaView = new this.HDAViewClass({
model : hda,
linkTarget : this.linkTarget,
expanded : expanded,
+ //draggable : true,
selectable : this.selecting,
hasUser : this.model.hasUser(),
logger : this.logger
@@ -830,8 +838,9 @@
// allow (error) messages to be clicked away
//TODO: switch to common close (X) idiom
'click .message-container' : 'clearMessages',
+
'click .history-search-btn' : 'toggleSearchControls',
- 'click .history-select-btn' : function( e ){ this.toggleSelect( this.fxSpeed ); },
+ 'click .history-select-btn' : function( e ){ this.toggleSelectors( this.fxSpeed ); },
'click .history-select-all-datasets-btn' : 'selectAllDatasets'
},
@@ -892,6 +901,10 @@
}
function onFirstSearch( searchFor ){
//console.debug( 'onSearch', searchFor, panel );
+ if( panel.model.hdas.haveDetails() ){
+ onSearch( searchFor );
+ return;
+ }
panel.$el.find( '.history-search-controls' ).searchInput( 'toggle-loading' );
panel.model.hdas.fetchAllDetails({ silent: true })
.always( function(){
@@ -952,7 +965,7 @@
});
},
- toggleSelect : function( speed ){
+ toggleSelectors : function( speed ){
if( !this.selecting ){
this.showSelectors( speed );
} else {
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/packed/mvc/dataset/hda-model.js
--- a/static/scripts/packed/mvc/dataset/hda-model.js
+++ b/static/scripts/packed/mvc/dataset/hda-model.js
@@ -1,1 +1,1 @@
-define([],function(){var d=Backbone.Model.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"(unnamed dataset)",state:"new",deleted:false,visible:true,accessible:true,purged:false,data_type:null,file_size:0,file_ext:"",meta_files:[],misc_blurb:"",misc_info:"",tags:null},urlRoot:galaxy_config.root+"api/histories/",url:function(){return this.urlRoot+this.get("history_id")+"/contents/"+this.get("id")},urls:function(){var i=this.get("id");if(!i){return{}}var h={purge:galaxy_config.root+"datasets/"+i+"/purge_async",display:galaxy_config.root+"datasets/"+i+"/display/?preview=True",edit:galaxy_config.root+"datasets/"+i+"/edit",download:galaxy_config.root+"datasets/"+i+"/display?to_ext="+this.get("file_ext"),report_error:galaxy_config.root+"dataset/errors?id="+i,rerun:galaxy_config.root+"tool_runner/rerun?id="+i,show_params:galaxy_config.root+"datasets/"+i+"/show_params",visualization:galaxy_config.root+"visualization",annotation:{get:galaxy_config.root+"dataset/get_annotation_async?id="+i,set:galaxy_config.root+"dataset/annotate_async?id="+i},meta_download:galaxy_config.root+"dataset/get_metadata_file?hda_id="+i+"&metadata_name="};return h},initialize:function(h){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",d.STATES.NOT_VIEWABLE)}this._setUpListeners()},_setUpListeners:function(){this.on("change:state",function(i,h){this.log(this+" has changed state:",i,h);if(this.inReadyState()){this.trigger("state:ready",i,h,this.previous("state"))}})},toJSON:function(){var h=Backbone.Model.prototype.toJSON.call(this);h.misc_info=jQuery.trim(h.misc_info);return h},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isVisible:function(i,j){var h=true;if((!i)&&(this.get("deleted")||this.get("purged"))){h=false}if((!j)&&(!this.get("visible"))){h=false}return h},hidden:function(){return !this.get("visible")},inReadyState:function(){var h=_.contains(d.READY_STATES,this.get("state"));return(this.isDeletedOrPurged()||h)},hasDetails:function(){return _.has(this.attributes,"genome_build")},hasData:function(){return(this.get("file_size")>0)},"delete":function c(h){if(this.get("deleted")){return jQuery.when()}return this.save({deleted:true},h)},undelete:function a(h){if(!this.get("deleted")||this.get("purged")){return jQuery.when()}return this.save({deleted:false},h)},hide:function b(h){if(!this.get("visible")){return jQuery.when()}return this.save({visible:false},h)},unhide:function g(h){if(this.get("visible")){return jQuery.when()}return this.save({visible:true},h)},purge:function f(h){if(this.get("purged")){return jQuery.when()}h=h||{};h.url=galaxy_config.root+"datasets/"+this.get("id")+"/purge_async";var i=this,j=jQuery.ajax(h);j.done(function(m,k,l){i.set({deleted:true,purged:true})});j.fail(function(o,k,n){var l=_l("Unable to purge dataset");var m=("Removal of datasets by users is not allowed in this Galaxy instance");if(o.responseJSON&&o.responseJSON.error){l=o.responseJSON.error}else{if(o.responseText.indexOf(m)!==-1){l=m}}o.responseText=l;i.trigger("error",i,o,h,_l(l),{error:l})});return j},searchAttributes:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],searchAliases:{title:"name",format:"file_ext",database:"genome_build",blurb:"misc_blurb",description:"misc_blurb",info:"misc_info",tag:"tags"},searchAttribute:function(j,h){var i=this.get(j);if(!h||(i===undefined||i===null)){return false}if(_.isArray(i)){return this._searchArrayAttribute(i,h)}return(i.toString().toLowerCase().indexOf(h.toLowerCase())!==-1)},_searchArrayAttribute:function(i,h){h=h.toLowerCase();return _.any(i,function(j){return(j.toString().toLowerCase().indexOf(h.toLowerCase())!==-1)})},search:function(h){var i=this;return _.filter(this.searchAttributes,function(j){return i.searchAttribute(j,h)})},matches:function(i){var k="=",h=i.split(k);if(h.length>=2){var j=h[0];j=this.searchAliases[j]||j;return this.searchAttribute(j,h[1])}return !!this.search(i).length},matchesAll:function(i){var h=this;i=i.match(/(".*"|\w*=".*"|\S*)/g).filter(function(j){return !!j});return _.all(i,function(j){j=j.replace(/"/g,"");return h.matches(j)})},toString:function(){var h=this.get("id")||"";if(this.get("name")){h=this.get("hid")+' :"'+this.get("name")+'",'+h}return"HDA("+h+")"}});d.STATES={UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",PAUSED:"paused",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};d.READY_STATES=[d.STATES.NEW,d.STATES.OK,d.STATES.EMPTY,d.STATES.PAUSED,d.STATES.FAILED_METADATA,d.STATES.NOT_VIEWABLE,d.STATES.DISCARDED,d.STATES.ERROR];d.NOT_READY_STATES=[d.STATES.UPLOAD,d.STATES.QUEUED,d.STATES.RUNNING,d.STATES.SETTING_METADATA];var e=Backbone.Collection.extend(LoggableMixin).extend({model:d,urlRoot:galaxy_config.root+"api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},initialize:function(i,h){h=h||{};this.historyId=h.historyId},ids:function(){return this.map(function(h){return h.id})},notReady:function(){return this.filter(function(h){return !h.inReadyState()})},running:function(){var h=[];this.each(function(i){if(!i.inReadyState()){h.push(i.get("id"))}});return h},getByHid:function(h){return _.first(this.filter(function(i){return i.get("hid")===h}))},getVisible:function(h,k,j){j=j||[];var i=new e(this.filter(function(l){return l.isVisible(h,k)}));_.each(j,function(l){if(!_.isFunction(l)){return}i=new e(i.filter(l))});return i},fetchAllDetails:function(i){i=i||{};var h={details:"all"};i.data=(i.data)?(_.extend(i.data,h)):(h);return this.fetch(i)},ajaxQueue:function(k,j){var i=jQuery.Deferred(),h=this.length,m=[];if(!h){i.resolve([]);return i}var l=this.chain().reverse().map(function(o,n){return function(){var p=k.call(o,j);p.done(function(q){i.notify({curr:n,total:h,response:q,model:o})});p.always(function(q){m.push(q);if(l.length){l.shift()()}else{i.resolve(m)}})}}).value();l.shift()();return i},matches:function(h){return this.filter(function(i){return i.matches(h)})},set:function(j,h){var i=this;j=_.map(j,function(l){var m=i.get(l.id);if(!m){return l}var k=m.toJSON();_.extend(k,l);return k});Backbone.Collection.prototype.set.call(this,j,h)},toString:function(){return(["HDACollection(",[this.historyId,this.length].join(),")"].join(""))}});return{HistoryDatasetAssociation:d,HDACollection:e}});
\ No newline at end of file
+define([],function(){var d=Backbone.Model.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"(unnamed dataset)",state:"new",deleted:false,visible:true,accessible:true,purged:false,data_type:null,file_size:0,file_ext:"",meta_files:[],misc_blurb:"",misc_info:"",tags:null},urlRoot:galaxy_config.root+"api/histories/",url:function(){return this.urlRoot+this.get("history_id")+"/contents/"+this.get("id")},urls:function(){var i=this.get("id");if(!i){return{}}var h={purge:galaxy_config.root+"datasets/"+i+"/purge_async",display:galaxy_config.root+"datasets/"+i+"/display/?preview=True",edit:galaxy_config.root+"datasets/"+i+"/edit",download:galaxy_config.root+"datasets/"+i+"/display?to_ext="+this.get("file_ext"),report_error:galaxy_config.root+"dataset/errors?id="+i,rerun:galaxy_config.root+"tool_runner/rerun?id="+i,show_params:galaxy_config.root+"datasets/"+i+"/show_params",visualization:galaxy_config.root+"visualization",annotation:{get:galaxy_config.root+"dataset/get_annotation_async?id="+i,set:galaxy_config.root+"dataset/annotate_async?id="+i},meta_download:galaxy_config.root+"dataset/get_metadata_file?hda_id="+i+"&metadata_name="};return h},initialize:function(h){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",d.STATES.NOT_VIEWABLE)}this._setUpListeners()},_setUpListeners:function(){this.on("change:state",function(i,h){this.log(this+" has changed state:",i,h);if(this.inReadyState()){this.trigger("state:ready",i,h,this.previous("state"))}})},toJSON:function(){var h=Backbone.Model.prototype.toJSON.call(this);h.misc_info=jQuery.trim(h.misc_info);return h},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isVisible:function(i,j){var h=true;if((!i)&&(this.get("deleted")||this.get("purged"))){h=false}if((!j)&&(!this.get("visible"))){h=false}return h},hidden:function(){return !this.get("visible")},inReadyState:function(){var h=_.contains(d.READY_STATES,this.get("state"));return(this.isDeletedOrPurged()||h)},hasDetails:function(){return _.has(this.attributes,"genome_build")},hasData:function(){return(this.get("file_size")>0)},"delete":function c(h){if(this.get("deleted")){return jQuery.when()}return this.save({deleted:true},h)},undelete:function a(h){if(!this.get("deleted")||this.get("purged")){return jQuery.when()}return this.save({deleted:false},h)},hide:function b(h){if(!this.get("visible")){return jQuery.when()}return this.save({visible:false},h)},unhide:function g(h){if(this.get("visible")){return jQuery.when()}return this.save({visible:true},h)},purge:function f(h){if(this.get("purged")){return jQuery.when()}h=h||{};h.url=galaxy_config.root+"datasets/"+this.get("id")+"/purge_async";var i=this,j=jQuery.ajax(h);j.done(function(m,k,l){i.set({deleted:true,purged:true})});j.fail(function(o,k,n){var l=_l("Unable to purge dataset");var m=("Removal of datasets by users is not allowed in this Galaxy instance");if(o.responseJSON&&o.responseJSON.error){l=o.responseJSON.error}else{if(o.responseText.indexOf(m)!==-1){l=m}}o.responseText=l;i.trigger("error",i,o,h,_l(l),{error:l})});return j},searchAttributes:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],searchAliases:{title:"name",format:"file_ext",database:"genome_build",blurb:"misc_blurb",description:"misc_blurb",info:"misc_info",tag:"tags"},searchAttribute:function(j,h){var i=this.get(j);if(!h||(i===undefined||i===null)){return false}if(_.isArray(i)){return this._searchArrayAttribute(i,h)}return(i.toString().toLowerCase().indexOf(h.toLowerCase())!==-1)},_searchArrayAttribute:function(i,h){h=h.toLowerCase();return _.any(i,function(j){return(j.toString().toLowerCase().indexOf(h.toLowerCase())!==-1)})},search:function(h){var i=this;return _.filter(this.searchAttributes,function(j){return i.searchAttribute(j,h)})},matches:function(i){var k="=",h=i.split(k);if(h.length>=2){var j=h[0];j=this.searchAliases[j]||j;return this.searchAttribute(j,h[1])}return !!this.search(i).length},matchesAll:function(i){var h=this;i=i.match(/(".*"|\w*=".*"|\S*)/g).filter(function(j){return !!j});return _.all(i,function(j){j=j.replace(/"/g,"");return h.matches(j)})},toString:function(){var h=this.get("id")||"";if(this.get("name")){h=this.get("hid")+' :"'+this.get("name")+'",'+h}return"HDA("+h+")"}});d.STATES={UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",PAUSED:"paused",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};d.READY_STATES=[d.STATES.NEW,d.STATES.OK,d.STATES.EMPTY,d.STATES.PAUSED,d.STATES.FAILED_METADATA,d.STATES.NOT_VIEWABLE,d.STATES.DISCARDED,d.STATES.ERROR];d.NOT_READY_STATES=[d.STATES.UPLOAD,d.STATES.QUEUED,d.STATES.RUNNING,d.STATES.SETTING_METADATA];var e=Backbone.Collection.extend(LoggableMixin).extend({model:d,urlRoot:galaxy_config.root+"api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},initialize:function(i,h){h=h||{};this.historyId=h.historyId},ids:function(){return this.map(function(h){return h.id})},notReady:function(){return this.filter(function(h){return !h.inReadyState()})},running:function(){var h=[];this.each(function(i){if(!i.inReadyState()){h.push(i.get("id"))}});return h},getByHid:function(h){return _.first(this.filter(function(i){return i.get("hid")===h}))},getVisible:function(h,k,j){j=j||[];var i=new e(this.filter(function(l){return l.isVisible(h,k)}));_.each(j,function(l){if(!_.isFunction(l)){return}i=new e(i.filter(l))});return i},haveDetails:function(){return this.all(function(h){return h.hasDetails()})},fetchAllDetails:function(i){i=i||{};var h={details:"all"};i.data=(i.data)?(_.extend(i.data,h)):(h);return this.fetch(i)},ajaxQueue:function(k,j){var i=jQuery.Deferred(),h=this.length,m=[];if(!h){i.resolve([]);return i}var l=this.chain().reverse().map(function(o,n){return function(){var p=k.call(o,j);p.done(function(q){i.notify({curr:n,total:h,response:q,model:o})});p.always(function(q){m.push(q);if(l.length){l.shift()()}else{i.resolve(m)}})}}).value();l.shift()();return i},matches:function(h){return this.filter(function(i){return i.matches(h)})},set:function(j,h){var i=this;j=_.map(j,function(l){var m=i.get(l.id);if(!m){return l}var k=m.toJSON();_.extend(k,l);return k});Backbone.Collection.prototype.set.call(this,j,h)},toString:function(){return(["HDACollection(",[this.historyId,this.length].join(),")"].join(""))}});return{HistoryDatasetAssociation:d,HDACollection:e}});
\ No newline at end of file
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 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/dataset/hda-model"],function(a){var c=Backbone.Model.extend(LoggableMixin).extend({defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",renameUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"history/rename_async?id="+this.get("id")},annotateUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"history/annotate_async?id="+this.get("id")},tagUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"tag/get_tagging_elt_async?item_id="+this.get("id")+"&item_class=History"},initialize:function(f,g,e){e=e||{};this.logger=e.logger||null;this.log(this+".initialize:",f,g,e);this.hdas=new a.HDACollection(g||[],{historyId:this.get("id")});if(g&&_.isArray(g)){this.hdas.reset(g)}this._setUpListeners();this.updateTimeoutId=null;this.checkForUpdates()},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});if(this.hdas){this.listenTo(this.hdas,"error",function(){this.trigger.apply(this,["error:hdas"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(f,e){if(this.hdas){this.hdas.historyId=e}},this)},errorHandler:function(f,i,e,h,g){this.clearUpdateTimeout()},hasUser:function(){var e=this.get("user");return !!(e&&e.id)},checkForUpdates:function(e){if(this.hdas.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(e)){e.call(this)}}return this},setUpdateTimeout:function(e){e=e||c.UPDATE_DELAY;var f=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){f.refresh()},e);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(f,e){f=f||[];e=e||{};var g=this;e.data=e.data||{};if(f.length){e.data.details=f.join(",")}var h=this.hdas.fetch(e);h.done(function(i){g.checkForUpdates(function(){this.fetch()})});return h},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}});c.UPDATE_DELAY=4000;c.getHistoryData=function d(f,p){p=p||{};var j=p.hdaDetailIds||[];var l=jQuery.Deferred(),k=null;function g(q){return jQuery.ajax(galaxy_config.root+"api/histories/"+f)}function e(q){if(!q||!q.state_ids){return 0}return _.reduce(q.state_ids,function(r,t,s){return r+t.length},0)}function o(r){if(!e(r)){return[]}if(_.isFunction(j)){j=j(r)}var q=(j.length)?({details:j.join(",")}):({});return jQuery.ajax(galaxy_config.root+"api/histories/"+r.id+"/contents",{data:q})}var n=p.historyFn||g,m=p.hdaFn||o;var i=n(f);i.done(function(q){k=q;l.notify({status:"history data retrieved",historyJSON:k})});i.fail(function(s,q,r){l.reject(s,"loading the history")});var h=i.then(m);h.then(function(q){l.notify({status:"dataset data retrieved",historyJSON:k,hdaJSON:q});l.resolve(k,q)});h.fail(function(s,q,r){l.reject(s,"loading the datasets",{history:k})});return l};var b=Backbone.Collection.extend(LoggableMixin).extend({model:c,urlRoot:galaxy_config.root+"api/histories"});return{History:c,HistoryCollection:b}});
\ No newline at end of file
+define(["mvc/dataset/hda-model"],function(a){var c=Backbone.Model.extend(LoggableMixin).extend({defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",renameUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"history/rename_async?id="+this.get("id")},annotateUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"history/annotate_async?id="+this.get("id")},tagUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"tag/get_tagging_elt_async?item_id="+this.get("id")+"&item_class=History"},initialize:function(f,g,e){e=e||{};this.logger=e.logger||null;this.log(this+".initialize:",f,g,e);this.hdas=new a.HDACollection(g||[],{historyId:this.get("id")});if(g&&_.isArray(g)){this.hdas.reset(g)}this._setUpListeners();this.updateTimeoutId=null;this.checkForUpdates()},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});if(this.hdas){this.listenTo(this.hdas,"error",function(){this.trigger.apply(this,["error:hdas"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(f,e){if(this.hdas){this.hdas.historyId=e}},this)},errorHandler:function(f,i,e,h,g){this.clearUpdateTimeout()},hasUser:function(){var e=this.get("user");return !!(e&&e.id)},hdaCount:function(){return _.reduce(_.values(this.get("state_details")),function(e,f){return e+f},0)},checkForUpdates:function(e){if(this.hdas.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(e)){e.call(this)}}return this},setUpdateTimeout:function(e){e=e||c.UPDATE_DELAY;var f=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){f.refresh()},e);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(f,e){f=f||[];e=e||{};var g=this;e.data=e.data||{};if(f.length){e.data.details=f.join(",")}var h=this.hdas.fetch(e);h.done(function(i){g.checkForUpdates(function(){this.fetch()})});return h},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}});c.UPDATE_DELAY=4000;c.getHistoryData=function d(f,p){p=p||{};var j=p.hdaDetailIds||[];var l=jQuery.Deferred(),k=null;function g(q){return jQuery.ajax(galaxy_config.root+"api/histories/"+f)}function e(q){if(!q||!q.state_ids){return 0}return _.reduce(q.state_ids,function(r,t,s){return r+t.length},0)}function o(r){if(!e(r)){return[]}if(_.isFunction(j)){j=j(r)}var q=(j.length)?({details:j.join(",")}):({});return jQuery.ajax(galaxy_config.root+"api/histories/"+r.id+"/contents",{data:q})}var n=p.historyFn||g,m=p.hdaFn||o;var i=n(f);i.done(function(q){k=q;l.notify({status:"history data retrieved",historyJSON:k})});i.fail(function(s,q,r){l.reject(s,"loading the history")});var h=i.then(m);h.then(function(q){l.notify({status:"dataset data retrieved",historyJSON:k,hdaJSON:q});l.resolve(k,q)});h.fail(function(s,q,r){l.reject(s,"loading the datasets",{history:k})});return l};var b=Backbone.Collection.extend(LoggableMixin).extend({model:c,urlRoot:galaxy_config.root+"api/histories"});return{History:c,HistoryCollection:b}});
\ No newline at end of file
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/packed/mvc/history/history-panel.js
--- a/static/scripts/packed/mvc/history/history-panel.js
+++ b/static/scripts/packed/mvc/history/history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(g,d,b,a){var c=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(h){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([h],[true])))},removeExpandedHda:function(h){this.save("expandedHdas",_.omit(this.get("expandedHdas"),h))},toString:function(){return"HistoryPanelPrefs("+this.id+")"}});c.historyStorageKey=function f(h){if(!h){throw new Error("HistoryPanelPrefs.historyStorageKey needs valid id: "+h)}return("history:"+h)};var e=Backbone.View.extend(LoggableMixin).extend({HDAView:a.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",emptyMsgSelector:".empty-history-message",msgsSelector:".message-container",initialize:function(h){h=h||{};if(h.logger){this.logger=h.logger}this.log(this+".initialize:",h);this.linkTarget=h.linkTarget||"_blank";this._setUpListeners();this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searching=h.searching||false;this.selecting=h.selecting||false;if(this.model){this._setUpWebStorage(h.initiallyExpanded,h.show_deleted,h.show_hidden);this._setUpModelEventHandlers()}if(h.onready){h.onready.call(this)}},_setUpListeners:function(){this.on("error",function(i,l,h,k,j){this.errorHandler(i,l,h,k,j)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...")});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(h){this.log(this+"",arguments)},this)}},errorHandler:function(j,m,i,l,k){var h=this._parseErrorMessage(j,m,i,l,k);if(m&&m.status===0&&m.readyState===0){}else{if(m&&m.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",h.message,h.details)})}else{this.displayMessage("error",h.message,h.details)}}}},_parseErrorMessage:function(k,o,j,n,m){var i=Galaxy.currUser,h={message:this._bePolite(n),details:{user:(i instanceof User)?(i.toJSON()):(i+""),source:(k instanceof Backbone.Model)?(k.toJSON()):(k+""),xhr:o,options:(o)?(_.omit(j,"xhr")):(j)}};_.extend(h.details,m||{});if(o&&_.isFunction(o.getAllResponseHeaders)){var l=o.getAllResponseHeaders();l=_.compact(l.split("\n"));l=_.map(l,function(p){return p.split(": ")});h.details.xhr.responseHeaders=_.object(l)}return h},_bePolite:function(h){h=h||_l("An error occurred while getting updates from the server");return h+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(i){var h=this;return this.loadHistoryWithHDADetails("current",i).then(function(k,j){h.trigger("current-history",h)})},switchToHistory:function(k,j){var h=this,i=function(){return jQuery.post(galaxy_config.root+"api/histories/"+k+"/set_as_current")};return this.loadHistoryWithHDADetails(k,j,i).then(function(m,l){h.trigger("switched-history",h)})},createNewHistory:function(j){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var h=this,i=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,j,i).then(function(l,k){h.trigger("new-history",h)})},loadHistoryWithHDADetails:function(k,j,i,m){var h=this,l=function(n){return h.getExpandedHdaIds(n.id)};return this.loadHistory(k,j,i,m,l)},loadHistory:function(k,j,i,n,l){this.trigger("loading-history",this);j=j||{};var h=this;var m=g.History.getHistoryData(k,{historyFn:i,hdaFn:n,hdaDetailIds:j.initiallyExpanded||l});return this._loadHistoryFromXHR(m,j).fail(function(q,o,p){h.trigger("error",h,q,j,_l("An error was encountered while "+o),{historyId:k,history:p||{}})}).always(function(){h.trigger("loading-done",h)})},_loadHistoryFromXHR:function(j,i){var h=this;j.then(function(k,l){h.setModel(k,l,i)});j.fail(function(l,k){h.render()});return j},setModel:function(j,h,i){i=i||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){j.user=Galaxy.currUser.toJSON()}this.model=new g.History(j,h,i);this._setUpWebStorage(i.initiallyExpanded,i.show_deleted,i.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(i,h,j){this.storage=new c({id:c.historyStorageKey(this.model.get("id"))});if(_.isObject(i)){this.storage.set("exandedHdas",i)}if(_.isBoolean(h)){this.storage.set("show_deleted",h)}if(_.isBoolean(j)){this.storage.set("show_hidden",j)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var h in sessionStorage){if(h.indexOf("history:")===0){sessionStorage.removeItem(h)}}},getStoredOptions:function(i){if(!i||i==="current"){return(this.storage)?(this.storage.get()):({})}var h=sessionStorage.getItem(c.historyStorageKey(i));return(h===null)?({}):(JSON.parse(h))},getExpandedHdaIds:function(h){var i=this.getStoredOptions(h).expandedHdas;return((_.isEmpty(i))?([]):(_.keys(i)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(i,k,h,j){this.errorHandler(i,k,h,j)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(h){this.model.fetch()},this);this.model.hdas.on("state:ready",function(i,j,h){if((!i.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[i.id])}},this)},render:function(j,k){j=(j===undefined)?(this.fxSpeed):(j);var h=this,i;if(this.model){i=this.renderModel()}else{i=this.renderWithoutModel()}$(h).queue("fx",[function(l){if(j&&h.$el.is(":visible")){h.$el.fadeOut(j,l)}else{l()}},function(l){h.$el.empty();if(i){h.$el.append(i.children())}l()},function(l){if(j&&!h.$el.is(":visible")){h.$el.fadeIn(j,l)}else{l()}},function(l){if(k){k.call(this)}h.trigger("rendered",this);l()}]);return this},renderWithoutModel:function(){var h=$("<div/>"),i=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return h.append(i)},renderModel:function(){var h=$("<div/>");if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){h.append(e.templates.anonHistoryPanel(this.model.toJSON()))}else{h.append(e.templates.historyPanel(this.model.toJSON()));this._renderTags(h);this._renderAnnotation(h)}h.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(h);this.renderHdas(h);return h},_renderTags:function(h){this.tagsEditor=new TagsEditor({model:this.model,el:h.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(h.find(".history-secondary-actions"))})},_renderAnnotation:function(h){this.annotationEditor=new AnnotationEditor({model:this.model,el:h.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(h.find(".history-secondary-actions"))})},_renderSearchButton:function(h){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_renderSelectButton:function(h){return faIconButton({title:_l("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(h){h=h||this.$el;h.find("[title]").tooltip({placement:"bottom"});if(!this.model||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){return}var i=this;h.find(".history-name").make_text_editable({on_finish:function(j){h.find(".history-name").text(j);i.model.save({name:j}).fail(function(){h.find(".history-name").text(i.model.previous("name"))})}});this._setUpDatasetActionsPopup(h)},_setUpDatasetActionsPopup:function(h){var i=this;(new PopupMenu(h.find(".history-dataset-action-popup-btn"),[{html:_l("Hide datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype.hide;i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Unhide datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype.unhide;i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Delete datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype["delete"];i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Undelete datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype.undelete;i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Permanently delete datasets"),func:function(){if(confirm(_l("This will permanently remove the data in your datasets. Are you sure?"))){var j=d.HistoryDatasetAssociation.prototype.purge;i.getSelectedHdaCollection().ajaxQueue(j)}}}]))},refreshHdas:function(i,h){if(this.model){return this.model.refresh(i,h)}return $.when()},addHdaView:function(k){this.log("add."+this,k);var i=this;if(!k.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function j(m){var l=i.$el.find(i.emptyMsgSelector);if(l.is(":visible")){l.fadeOut(i.fxSpeed,m)}else{m()}},function h(m){i.scrollToTop();var l=i.$el.find(i.datasetsSelector);i.createHdaView(k).$el.hide().prependTo(l).slideDown(i.fxSpeed)}])},createHdaView:function(j){var i=j.get("id"),h=this.storage.get("expandedHdas")[i],k=new this.HDAView({model:j,linkTarget:this.linkTarget,expanded:h,selectable:this.selecting,hasUser:this.model.hasUser(),logger:this.logger});this._setUpHdaListeners(k);this.hdaViews[i]=k;return k.render()},_setUpHdaListeners:function(i){var h=this;i.on("body-expanded",function(j){h.storage.addExpandedHda(j)});i.on("body-collapsed",function(j){h.storage.removeExpandedHda(j)});i.on("error",function(k,m,j,l){h.errorHandler(k,m,j,l)})},handleHdaDeletionChange:function(h){if(h.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[h.id])}},handleHdaVisibleChange:function(h){if(h.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[h.id])}},removeHdaView:function(i){if(!i){return}var h=this;i.$el.fadeOut(h.fxSpeed,function(){i.off();i.remove();delete h.hdaViews[i.model.id];if(_.isEmpty(h.hdaViews)){h.$el.find(h.emptyMsgSelector).fadeIn(h.fxSpeed,function(){h.trigger("empty-history",h)})}})},renderHdas:function(j){j=j||this.$el;this.hdaViews={};var i=this,h=j.find(this.datasetsSelector),k=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);h.empty();if(k.length){k.each(function(l){h.prepend(i.createHdaView(l).$el)});j.find(this.emptyMsgSelector).hide()}else{j.find(this.emptyMsgSelector).show()}return this.hdaViews},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls","click .history-select-btn":function(h){this.toggleSelect(this.fxSpeed)},"click .history-select-all-datasets-btn":"selectAllDatasets"},updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(h){h.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},renderSearchControls:function(i){var j=this;function l(m){j.searchFor=m;j.filters=[function(n){return n.matchesAll(j.searchFor)}];j.trigger("search:searching",m,j);j.renderHdas()}function h(m){j.$el.find(".history-search-controls").searchInput("toggle-loading");j.model.hdas.fetchAllDetails({silent:true}).always(function(){j.$el.find(".history-search-controls").searchInput("toggle-loading")}).done(function(){l(m)})}function k(){j.searchFor="";j.filters=[];j.trigger("search:clear",j);j.renderHdas()}return i.searchInput({initialVal:j.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:h,onsearch:l,onclear:k})},toggleSearchControls:function(){var h=this.$el.find(".history-search-controls");if(!h.children().size()){h=this.renderSearchControls(h).hide()}h.slideToggle(this.fxSpeed,function(){if($(this).is(":visible")){this.searching=true;$(this).find("input").focus()}else{this.searching=false}})},showSelectors:function(h){this.selecting=true;this.$el.find(".history-dataset-actions").slideDown(h);_.each(this.hdaViews,function(i){i.showSelector(h)})},hideSelectors:function(h){this.selecting=false;this.$el.find(".history-dataset-actions").slideUp(h);_.each(this.hdaViews,function(i){i.hideSelector(h)})},toggleSelect:function(h){if(!this.selecting){this.showSelectors(h)}else{this.hideSelectors(h)}},selectAllDatasets:function(i){var h=this.$el.find(".history-select-all-datasets-btn");currMode=h.data("mode");if(currMode==="select"){_.each(this.hdaViews,function(j){j.select(i)});h.data("mode","deselect");h.text(_l("De-select all"))}else{if(currMode==="deselect"){_.each(this.hdaViews,function(j){j.deselect(i)});h.data("mode","select");h.text(_l("Select all"))}}},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(h){return h.selected})},getSelectedHdaCollection:function(){return new d.HDACollection(_.map(this.getSelectedHdaViews(),function(h){return h.model}),{historyId:this.model.id})},showLoadingIndicator:function(i,h,j){h=(h!==undefined)?(h):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,j)}else{this.$el.fadeOut(h);this.indicator.show(i,h,j)}},hideLoadingIndicator:function(h,i){h=(h!==undefined)?(h):(this.fxSpeed);if(this.indicator){this.indicator.hide(h,i)}},displayMessage:function(m,n,l){var j=this;this.scrollToTop();var k=this.$el.find(this.msgsSelector),h=$("<div/>").addClass(m+"message").html(n);if(!_.isEmpty(l)){var i=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(j.messageToModalOptions(m,n,l));return false});h.append(" ",i)}return k.html(h)},messageToModalOptions:function(l,n,k){var h=this,m=$("<div/>"),j={title:"Details"};function i(o){o=_.omit(o,_.functions(o));return["<table>",_.map(o,function(q,p){q=(_.isObject(q))?(i(q)):(q);return'<tr><td style="vertical-align: top; color: grey">'+p+'</td><td style="padding-left: 8px">'+q+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(k)){j.body=m.append(i(k))}else{j.body=m.html(k)}j.buttons={Ok:function(){Galaxy.modal.hide();h.clearMessages()}};return j},clearMessages:function(){var h=this.$el.find(this.msgsSelector);h.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(h){this.$el.parent().scrollTop(h)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(i,j){if(!j){this.$el.parent().parent().scrollTop(i);return this}var h=window,k=this.$el.parent().parent(),m=$(h).innerHeight(),l=(m/2)-(j/2);$(k).scrollTop(i-l);return this},scrollToId:function(i){if((!i)||(!this.hdaViews[i])){return this}var h=this.hdaViews[i].$el;this.scrollIntoView(h.offset().top,h.outerHeight());return this},scrollToHid:function(h){var i=this.model.hdas.getByHid(h);if(!i){return this}return this.scrollToId(i.id)},connectToQuotaMeter:function(h){if(!h){return this}this.listenTo(h,"quota:over",this.showQuotaMessage);this.listenTo(h,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(h&&h.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var h=this.$el.find(".quota-message");if(h.is(":hidden")){h.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var h=this.$el.find(".quota-message");if(!h.is(":hidden")){h.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(h){if(!h){return this}this.on("new-storage",function(j,i){if(h&&j){h.findItemByHtml(_l("Include Deleted Datasets")).checked=j.get("show_deleted");h.findItemByHtml(_l("Include Hidden Datasets")).checked=j.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});e.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:e}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(g,d,b,a){var c=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(h){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([h],[true])))},removeExpandedHda:function(h){this.save("expandedHdas",_.omit(this.get("expandedHdas"),h))},toString:function(){return"HistoryPanelPrefs("+this.id+")"}});c.historyStorageKey=function f(h){if(!h){throw new Error("HistoryPanelPrefs.historyStorageKey needs valid id: "+h)}return("history:"+h)};var e=Backbone.View.extend(LoggableMixin).extend({defaultHDAViewClass:a.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",emptyMsgSelector:".empty-history-message",msgsSelector:".message-container",initialize:function(h){h=h||{};if(h.logger){this.logger=h.logger}this.log(this+".initialize:",h);this.HDAViewClass=h.HDAViewClass||this.defaultHDAViewClass;this.linkTarget=h.linkTarget||"_blank";this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searching=h.searching||false;this.selecting=h.selecting||false;this._setUpListeners();if(this.model){this._setUpWebStorage(h.initiallyExpanded,h.show_deleted,h.show_hidden);this._setUpModelEventHandlers()}if(h.onready){h.onready.call(this)}},_setUpListeners:function(){this.on("error",function(i,l,h,k,j){this.errorHandler(i,l,h,k,j)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...")});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(h){this.log(this+"",arguments)},this)}},errorHandler:function(j,m,i,l,k){var h=this._parseErrorMessage(j,m,i,l,k);if(m&&m.status===0&&m.readyState===0){}else{if(m&&m.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",h.message,h.details)})}else{this.displayMessage("error",h.message,h.details)}}}},_parseErrorMessage:function(k,o,j,n,m){var i=Galaxy.currUser,h={message:this._bePolite(n),details:{user:(i instanceof User)?(i.toJSON()):(i+""),source:(k instanceof Backbone.Model)?(k.toJSON()):(k+""),xhr:o,options:(o)?(_.omit(j,"xhr")):(j)}};_.extend(h.details,m||{});if(o&&_.isFunction(o.getAllResponseHeaders)){var l=o.getAllResponseHeaders();l=_.compact(l.split("\n"));l=_.map(l,function(p){return p.split(": ")});h.details.xhr.responseHeaders=_.object(l)}return h},_bePolite:function(h){h=h||_l("An error occurred while getting updates from the server");return h+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(i){var h=this;return this.loadHistoryWithHDADetails("current",i).then(function(k,j){h.trigger("current-history",h)})},switchToHistory:function(k,j){var h=this,i=function(){return jQuery.post(galaxy_config.root+"api/histories/"+k+"/set_as_current")};return this.loadHistoryWithHDADetails(k,j,i).then(function(m,l){h.trigger("switched-history",h)})},createNewHistory:function(j){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var h=this,i=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,j,i).then(function(l,k){h.trigger("new-history",h)})},loadHistoryWithHDADetails:function(k,j,i,m){var h=this,l=function(n){return h.getExpandedHdaIds(n.id)};return this.loadHistory(k,j,i,m,l)},loadHistory:function(k,j,i,n,l){this.trigger("loading-history",this);j=j||{};var h=this;var m=g.History.getHistoryData(k,{historyFn:i,hdaFn:n,hdaDetailIds:j.initiallyExpanded||l});return this._loadHistoryFromXHR(m,j).fail(function(q,o,p){h.trigger("error",h,q,j,_l("An error was encountered while "+o),{historyId:k,history:p||{}})}).always(function(){h.trigger("loading-done",h)})},_loadHistoryFromXHR:function(j,i){var h=this;j.then(function(k,l){h.setModel(k,l,i)});j.fail(function(l,k){h.render()});return j},setModel:function(j,h,i){i=i||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){j.user=Galaxy.currUser.toJSON()}this.model=new g.History(j,h,i);this._setUpWebStorage(i.initiallyExpanded,i.show_deleted,i.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(i,h,j){this.storage=new c({id:c.historyStorageKey(this.model.get("id"))});if(_.isObject(i)){this.storage.set("exandedHdas",i)}if(_.isBoolean(h)){this.storage.set("show_deleted",h)}if(_.isBoolean(j)){this.storage.set("show_hidden",j)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var h in sessionStorage){if(h.indexOf("history:")===0){sessionStorage.removeItem(h)}}},getStoredOptions:function(i){if(!i||i==="current"){return(this.storage)?(this.storage.get()):({})}var h=sessionStorage.getItem(c.historyStorageKey(i));return(h===null)?({}):(JSON.parse(h))},getExpandedHdaIds:function(h){var i=this.getStoredOptions(h).expandedHdas;return((_.isEmpty(i))?([]):(_.keys(i)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(i,k,h,j){this.errorHandler(i,k,h,j)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(h){this.model.fetch()},this);this.model.hdas.on("state:ready",function(i,j,h){if((!i.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[i.id])}},this)},render:function(j,k){j=(j===undefined)?(this.fxSpeed):(j);var h=this,i;if(this.model){i=this.renderModel()}else{i=this.renderWithoutModel()}$(h).queue("fx",[function(l){if(j&&h.$el.is(":visible")){h.$el.fadeOut(j,l)}else{l()}},function(l){h.$el.empty();if(i){h.$el.append(i.children())}l()},function(l){if(j&&!h.$el.is(":visible")){h.$el.fadeIn(j,l)}else{l()}},function(l){if(k){k.call(this)}h.trigger("rendered",this);l()}]);return this},renderWithoutModel:function(){var h=$("<div/>"),i=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return h.append(i)},renderModel:function(){var h=$("<div/>");if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){h.append(e.templates.anonHistoryPanel(this.model.toJSON()))}else{h.append(e.templates.historyPanel(this.model.toJSON()));if(Galaxy.currUser.id&&Galaxy.currUser.id===this.model.get("user_id")){this._renderTags(h);this._renderAnnotation(h)}}h.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(h);this.renderHdas(h);return h},_renderTags:function(h){this.tagsEditor=new TagsEditor({model:this.model,el:h.find(".history-controls .tags-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-tag-btn",faIcon:"fa-tags"}).appendTo(h.find(".history-secondary-actions"))})},_renderAnnotation:function(h){this.annotationEditor=new AnnotationEditor({model:this.model,el:h.find(".history-controls .annotation-display"),onshowFirstTime:function(){this.render()},$activator:faIconButton({title:_l("Edit history tags"),classes:"history-annotate-btn",faIcon:"fa-comment"}).appendTo(h.find(".history-secondary-actions"))})},_renderSearchButton:function(h){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_renderSelectButton:function(h){return faIconButton({title:_l("Operations on multiple datasets"),classes:"history-select-btn",faIcon:"fa-check-square-o"})},_setUpBehaviours:function(h){h=h||this.$el;h.find("[title]").tooltip({placement:"bottom"});if((!this.model)||(!Galaxy.currUser||Galaxy.currUser.isAnonymous())||(Galaxy.currUser.id!==this.model.get("user_id"))){return}var i=this;h.find(".history-name").attr("title",_l("Click to rename history")).tooltip({placement:"bottom"}).make_text_editable({on_finish:function(j){h.find(".history-name").text(j);i.model.save({name:j}).fail(function(){h.find(".history-name").text(i.model.previous("name"))})}});this._setUpDatasetActionsPopup(h)},_setUpDatasetActionsPopup:function(h){var i=this;(new PopupMenu(h.find(".history-dataset-action-popup-btn"),[{html:_l("Hide datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype.hide;i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Unhide datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype.unhide;i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Delete datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype["delete"];i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Undelete datasets"),func:function(){var j=d.HistoryDatasetAssociation.prototype.undelete;i.getSelectedHdaCollection().ajaxQueue(j)}},{html:_l("Permanently delete datasets"),func:function(){if(confirm(_l("This will permanently remove the data in your datasets. Are you sure?"))){var j=d.HistoryDatasetAssociation.prototype.purge;i.getSelectedHdaCollection().ajaxQueue(j)}}}]))},refreshHdas:function(i,h){if(this.model){return this.model.refresh(i,h)}return $.when()},addHdaView:function(k){this.log("add."+this,k);var i=this;if(!k.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function j(m){var l=i.$el.find(i.emptyMsgSelector);if(l.is(":visible")){l.fadeOut(i.fxSpeed,m)}else{m()}},function h(m){i.scrollToTop();var l=i.$el.find(i.datasetsSelector);i.createHdaView(k).$el.hide().prependTo(l).slideDown(i.fxSpeed)}])},createHdaView:function(j){var i=j.get("id"),h=this.storage.get("expandedHdas")[i],k=new this.HDAViewClass({model:j,linkTarget:this.linkTarget,expanded:h,selectable:this.selecting,hasUser:this.model.hasUser(),logger:this.logger});this._setUpHdaListeners(k);this.hdaViews[i]=k;return k.render()},_setUpHdaListeners:function(i){var h=this;i.on("body-expanded",function(j){h.storage.addExpandedHda(j)});i.on("body-collapsed",function(j){h.storage.removeExpandedHda(j)});i.on("error",function(k,m,j,l){h.errorHandler(k,m,j,l)})},handleHdaDeletionChange:function(h){if(h.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[h.id])}},handleHdaVisibleChange:function(h){if(h.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[h.id])}},removeHdaView:function(i){if(!i){return}var h=this;i.$el.fadeOut(h.fxSpeed,function(){i.off();i.remove();delete h.hdaViews[i.model.id];if(_.isEmpty(h.hdaViews)){h.$el.find(h.emptyMsgSelector).fadeIn(h.fxSpeed,function(){h.trigger("empty-history",h)})}})},renderHdas:function(j){j=j||this.$el;this.hdaViews={};var i=this,h=j.find(this.datasetsSelector),k=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);h.empty();if(k.length){k.each(function(l){h.prepend(i.createHdaView(l).$el)});j.find(this.emptyMsgSelector).hide()}else{j.find(this.emptyMsgSelector).show()}return this.hdaViews},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls","click .history-select-btn":function(h){this.toggleSelectors(this.fxSpeed)},"click .history-select-all-datasets-btn":"selectAllDatasets"},updateHistoryDiskSize:function(){this.$el.find(".history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(h){h.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},renderSearchControls:function(i){var j=this;function l(m){j.searchFor=m;j.filters=[function(n){return n.matchesAll(j.searchFor)}];j.trigger("search:searching",m,j);j.renderHdas()}function h(m){if(j.model.hdas.haveDetails()){l(m);return}j.$el.find(".history-search-controls").searchInput("toggle-loading");j.model.hdas.fetchAllDetails({silent:true}).always(function(){j.$el.find(".history-search-controls").searchInput("toggle-loading")}).done(function(){l(m)})}function k(){j.searchFor="";j.filters=[];j.trigger("search:clear",j);j.renderHdas()}return i.searchInput({initialVal:j.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:h,onsearch:l,onclear:k})},toggleSearchControls:function(){var h=this.$el.find(".history-search-controls");if(!h.children().size()){h=this.renderSearchControls(h).hide()}h.slideToggle(this.fxSpeed,function(){if($(this).is(":visible")){this.searching=true;$(this).find("input").focus()}else{this.searching=false}})},showSelectors:function(h){this.selecting=true;this.$el.find(".history-dataset-actions").slideDown(h);_.each(this.hdaViews,function(i){i.showSelector(h)})},hideSelectors:function(h){this.selecting=false;this.$el.find(".history-dataset-actions").slideUp(h);_.each(this.hdaViews,function(i){i.hideSelector(h)})},toggleSelectors:function(h){if(!this.selecting){this.showSelectors(h)}else{this.hideSelectors(h)}},selectAllDatasets:function(i){var h=this.$el.find(".history-select-all-datasets-btn");currMode=h.data("mode");if(currMode==="select"){_.each(this.hdaViews,function(j){j.select(i)});h.data("mode","deselect");h.text(_l("De-select all"))}else{if(currMode==="deselect"){_.each(this.hdaViews,function(j){j.deselect(i)});h.data("mode","select");h.text(_l("Select all"))}}},getSelectedHdaViews:function(){return _.filter(this.hdaViews,function(h){return h.selected})},getSelectedHdaCollection:function(){return new d.HDACollection(_.map(this.getSelectedHdaViews(),function(h){return h.model}),{historyId:this.model.id})},showLoadingIndicator:function(i,h,j){h=(h!==undefined)?(h):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,j)}else{this.$el.fadeOut(h);this.indicator.show(i,h,j)}},hideLoadingIndicator:function(h,i){h=(h!==undefined)?(h):(this.fxSpeed);if(this.indicator){this.indicator.hide(h,i)}},displayMessage:function(m,n,l){var j=this;this.scrollToTop();var k=this.$el.find(this.msgsSelector),h=$("<div/>").addClass(m+"message").html(n);if(!_.isEmpty(l)){var i=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(j.messageToModalOptions(m,n,l));return false});h.append(" ",i)}return k.html(h)},messageToModalOptions:function(l,n,k){var h=this,m=$("<div/>"),j={title:"Details"};function i(o){o=_.omit(o,_.functions(o));return["<table>",_.map(o,function(q,p){q=(_.isObject(q))?(i(q)):(q);return'<tr><td style="vertical-align: top; color: grey">'+p+'</td><td style="padding-left: 8px">'+q+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(k)){j.body=m.append(i(k))}else{j.body=m.html(k)}j.buttons={Ok:function(){Galaxy.modal.hide();h.clearMessages()}};return j},clearMessages:function(){var h=this.$el.find(this.msgsSelector);h.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(h){this.$el.parent().scrollTop(h)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(i,j){if(!j){this.$el.parent().parent().scrollTop(i);return this}var h=window,k=this.$el.parent().parent(),m=$(h).innerHeight(),l=(m/2)-(j/2);$(k).scrollTop(i-l);return this},scrollToId:function(i){if((!i)||(!this.hdaViews[i])){return this}var h=this.hdaViews[i].$el;this.scrollIntoView(h.offset().top,h.outerHeight());return this},scrollToHid:function(h){var i=this.model.hdas.getByHid(h);if(!i){return this}return this.scrollToId(i.id)},connectToQuotaMeter:function(h){if(!h){return this}this.listenTo(h,"quota:over",this.showQuotaMessage);this.listenTo(h,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(h&&h.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var h=this.$el.find(".quota-message");if(h.is(":hidden")){h.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var h=this.$el.find(".quota-message");if(!h.is(":hidden")){h.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(h){if(!h){return this}this.on("new-storage",function(j,i){if(h&&j){h.findItemByHtml(_l("Include Deleted Datasets")).checked=j.get("show_deleted");h.findItemByHtml(_l("Include Hidden Datasets")).checked=j.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});e.templates={historyPanel:Handlebars.templates["template-history-historyPanel"],anonHistoryPanel:Handlebars.templates["template-history-historyPanel-anon"]};return{HistoryPanel:e}});
\ No newline at end of file
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/packed/templates/compiled/history-templates.js
--- a/static/scripts/packed/templates/compiled/history-templates.js
+++ b/static/scripts/packed/templates/compiled/history-templates.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-body"]=b(function(g,r,p,k,z){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);z=z||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';if(B=p.body){B=B.call(D,{hash:{},data:C})}else{B=D.body;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+='\n </div>\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';return A}function m(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';B=p["if"].call(D,D.misc_blurb,{hash:{},inverse:o.noop,fn:o.program(4,l,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.data_type,{hash:{},inverse:o.noop,fn:o.program(6,j,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.metadata_dbkey,{hash:{},inverse:o.noop,fn:o.program(9,f,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.misc_info,{hash:{},inverse:o.noop,fn:o.program(12,x,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';B=p.unless.call(D,D.deleted,{hash:{},inverse:o.noop,fn:o.program(14,w,C),data:C});if(B||B===0){A+=B}A+="\n\n ";return A}function l(D,C){var A="",B;A+='\n <div class="dataset-blurb">\n <span class="value">';if(B=p.misc_blurb){B=B.call(D,{hash:{},data:C})}else{B=D.misc_blurb;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function j(E,D){var A="",C,B;A+='\n <div class="dataset-datatype">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(7,i,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">';if(C=p.data_type){C=C.call(E,{hash:{},data:D})}else{C=E.data_type;C=typeof C===e?C.apply(E):C}A+=d(C)+"</span>\n </div>\n ";return A}function i(B,A){return"format"}function f(E,D){var A="",C,B;A+='\n <div class="dataset-dbkey">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(10,y,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">\n ';if(C=p.metadata_dbkey){C=C.call(E,{hash:{},data:D})}else{C=E.metadata_dbkey;C=typeof C===e?C.apply(E):C}A+=d(C)+"\n </span>\n </div>\n ";return A}function y(B,A){return"database"}function x(D,C){var A="",B;A+='\n <div class="dataset-info">\n <span class="value">';if(B=p.misc_info){B=B.call(D,{hash:{},data:C})}else{B=D.misc_info;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function w(D,C){var A="",B;A+='\n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="dataset-display-applications">\n ';B=p.each.call(D,D.display_apps,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p.each.call(D,D.display_types,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-peek">\n ';B=p["if"].call(D,D.peek,{hash:{},inverse:o.noop,fn:o.program(19,s,C),data:C});if(B||B===0){A+=B}A+="\n </div>\n\n ";return A}function v(D,C){var A="",B;A+='\n <div class="display-application">\n <span class="display-application-location">';if(B=p.label){B=B.call(D,{hash:{},data:C})}else{B=D.label;B=typeof B===e?B.apply(D):B}A+=d(B)+'</span>\n <span class="display-application-links">\n ';B=p.each.call(D,D.links,{hash:{},inverse:o.noop,fn:o.program(16,u,C),data:C});if(B||B===0){A+=B}A+="\n </span>\n </div>\n ";return A}function u(E,D){var A="",C,B;A+='\n <a target="';if(C=p.target){C=C.call(E,{hash:{},data:D})}else{C=E.target;C=typeof C===e?C.apply(E):C}A+=d(C)+'" href="';if(C=p.href){C=C.call(E,{hash:{},data:D})}else{C=E.href;C=typeof C===e?C.apply(E):C}A+=d(C)+'">';B={hash:{},inverse:o.noop,fn:o.program(17,t,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+="</a>\n ";return A}function t(C,B){var A;if(A=p.text){A=A.call(C,{hash:{},data:B})}else{A=C.text;A=typeof A===e?A.apply(C):A}return d(A)}function s(D,C){var A="",B;A+='\n <pre class="peek">';if(B=p.peek){B=B.call(D,{hash:{},data:C})}else{B=D.peek;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+="</pre>\n ";return A}q+='<div class="dataset-body">\n ';h=p["if"].call(r,r.body,{hash:{},inverse:o.program(3,m,z),fn:o.program(1,n,z),data:z});if(h||h===0){q+=h}q+="\n</div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-skeleton"]=b(function(f,r,p,k,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,f.helpers);w=w||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var x="",z,y;x+='\n <div class="errormessagesmall">\n ';y={hash:{},inverse:o.noop,fn:o.program(2,m,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+=":\n ";y={hash:{},inverse:o.noop,fn:o.program(4,l,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </div>\n ";return x}function m(y,x){return"There was an error getting the data for this dataset"}function l(z,y){var x;if(x=p.error){x=x.call(z,{hash:{},data:y})}else{x=z.error;x=typeof x===e?x.apply(z):x}return d(x)}function j(A,z){var x="",y;x+="\n ";y=p["if"].call(A,A.purged,{hash:{},inverse:o.program(10,v,z),fn:o.program(7,i,z),data:z});if(y||y===0){x+=y}x+="\n ";return x}function i(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(8,g,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n\n ";return x}function g(y,x){return"This dataset has been deleted and removed from disk."}function v(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(11,u,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+='\n \n \n Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it\n or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk\n </strong></div>\n ';return x}function u(y,x){return"This dataset has been deleted."}function t(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(14,s,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+='\n \n Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it\n </strong></div>\n ';return x}function s(y,x){return"This dataset has been hidden."}q+='<div class="dataset hda">\n <div class="dataset-warnings">\n ';h=p["if"].call(r,r.error,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(6,j,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p.unless.call(r,r.visible,{hash:{},inverse:o.noop,fn:o.program(13,t,w),data:w});if(h||h===0){q+=h}q+='\n </div>\n\n <div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>\n <div class="dataset-primary-actions"></div>\n \n <div class="dataset-title-bar clear" tabindex="0">\n <span class="dataset-state-icon state-icon"></span>\n <div class="dataset-title">\n <span class="hda-hid">';if(h=p.hid){h=h.call(r,{hash:{},data:w})}else{h=r.hid;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n <span class="dataset-name">';if(h=p.name){h=h.call(r,{hash:{},data:w})}else{h=r.name;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n </div>\n </div>\n\n <div class="dataset-body"></div>\n</div>';return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(g,r,p,k,u){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);u=u||{};var q="",i,f,o=this,e="function",c=p.blockHelperMissing,d=this.escapeExpression;function n(z,y){var v="",x,w;v+='\n <div class="history-name" title="';w={hash:{},inverse:o.noop,fn:o.program(2,m,y),data:y};if(x=p.local){x=x.call(z,w)}else{x=z.local;x=typeof x===e?x.apply(z):x}if(!p.local){x=c.call(z,x,w)}if(x||x===0){v+=x}v+='">\n ';if(x=p.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===e?x.apply(z):x}v+=d(x)+"\n </div>\n ";return v}function m(w,v){return"You must be logged in to edit your history name"}function l(y,x){var v="",w;v+='\n <div class="history-size">';if(w=p.nice_size){w=w.call(y,{hash:{},data:x})}else{w=y.nice_size;w=typeof w===e?w.apply(y):w}v+=d(w)+"</div>\n ";return v}function j(y,x){var v="",w;v+='\n \n <div class="';if(w=p.status){w=w.call(y,{hash:{},data:x})}else{w=y.status;w=typeof w===e?w.apply(y):w}v+=d(w)+'message">';if(w=p.message){w=w.call(y,{hash:{},data:x})}else{w=y.message;w=typeof w===e?w.apply(y):w}v+=d(w)+"</div>\n ";return v}function h(w,v){return"You are over your disk quota"}function t(w,v){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(w,v){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,u),data:u});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(4,l,u),data:u});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(6,j,u),data:u});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(8,h,u),data:u};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(10,t,u),data:u};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(12,s,u),data:u};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(h,s,q,l,y){this.compilerInfo=[4,">= 1.0.0"];q=this.merge(q,h.helpers);y=y||{};var r="",i,f,p=this,e="function",c=q.blockHelperMissing,d=this.escapeExpression;function o(D,C){var z="",B,A;z+='\n <div class="history-name" title="';A={hash:{},inverse:p.noop,fn:p.program(2,n,C),data:C};if(B=q.local){B=B.call(D,A)}else{B=D.local;B=typeof B===e?B.apply(D):B}if(!q.local){B=c.call(D,B,A)}if(B||B===0){z+=B}z+='">\n ';if(B=q.name){B=B.call(D,{hash:{},data:C})}else{B=D.name;B=typeof B===e?B.apply(D):B}z+=d(B)+"\n </div>\n ";return z}function n(A,z){return"Click to rename history"}function m(C,B){var z="",A;z+='\n <div class="history-size">';if(A=q.nice_size){A=A.call(C,{hash:{},data:B})}else{A=C.nice_size;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function k(D,C){var z="",B,A;z+='\n <div class="warningmessagesmall"><strong>\n ';A={hash:{},inverse:p.noop,fn:p.program(7,j,C),data:C};if(B=q.local){B=B.call(D,A)}else{B=D.local;B=typeof B===e?B.apply(D):B}if(!q.local){B=c.call(D,B,A)}if(B||B===0){z+=B}z+="\n </strong></div>\n ";return z}function j(A,z){return"You are currently viewing a deleted history!"}function g(C,B){var z="",A;z+='\n \n <div class="';if(A=q.status){A=A.call(C,{hash:{},data:B})}else{A=C.status;A=typeof A===e?A.apply(C):A}z+=d(A)+'message">';if(A=q.message){A=A.call(C,{hash:{},data:B})}else{A=C.message;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function x(A,z){return"You are over your disk quota"}function w(A,z){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function v(A,z){return"Select all"}function u(A,z){return"For all selected"}function t(A,z){return"Your history is empty. Click 'Get Data' on the left pane to start"}r+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n ';i=q["if"].call(s,s.name,{hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=q["if"].call(s,s.nice_size,{hash:{},inverse:p.noop,fn:p.program(4,m,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=q["if"].call(s,s.deleted,{hash:{},inverse:p.noop,fn:p.program(6,k,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="message-container">\n ';i=q["if"].call(s,s.message,{hash:{},inverse:p.noop,fn:p.program(9,g,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:p.noop,fn:p.program(11,x,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+=".\n ";f={hash:{},inverse:p.noop,fn:p.program(13,w,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:p.noop,fn:p.program(15,v,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:p.noop,fn:p.program(17,u,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:p.noop,fn:p.program(19,t,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n </div>";return r})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-body"]=b(function(g,r,p,k,z){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);z=z||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';if(B=p.body){B=B.call(D,{hash:{},data:C})}else{B=D.body;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+='\n </div>\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';return A}function m(D,C){var A="",B;A+='\n <div class="dataset-summary">\n ';B=p["if"].call(D,D.misc_blurb,{hash:{},inverse:o.noop,fn:o.program(4,l,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.data_type,{hash:{},inverse:o.noop,fn:o.program(6,j,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.metadata_dbkey,{hash:{},inverse:o.noop,fn:o.program(9,f,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p["if"].call(D,D.misc_info,{hash:{},inverse:o.noop,fn:o.program(12,x,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-actions clear">\n <div class="left"></div>\n <div class="right"></div>\n </div>\n\n ';B=p.unless.call(D,D.deleted,{hash:{},inverse:o.noop,fn:o.program(14,w,C),data:C});if(B||B===0){A+=B}A+="\n\n ";return A}function l(D,C){var A="",B;A+='\n <div class="dataset-blurb">\n <span class="value">';if(B=p.misc_blurb){B=B.call(D,{hash:{},data:C})}else{B=D.misc_blurb;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function j(E,D){var A="",C,B;A+='\n <div class="dataset-datatype">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(7,i,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">';if(C=p.data_type){C=C.call(E,{hash:{},data:D})}else{C=E.data_type;C=typeof C===e?C.apply(E):C}A+=d(C)+"</span>\n </div>\n ";return A}function i(B,A){return"format"}function f(E,D){var A="",C,B;A+='\n <div class="dataset-dbkey">\n <label class="prompt">';B={hash:{},inverse:o.noop,fn:o.program(10,y,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+='</label>\n <span class="value">\n ';if(C=p.metadata_dbkey){C=C.call(E,{hash:{},data:D})}else{C=E.metadata_dbkey;C=typeof C===e?C.apply(E):C}A+=d(C)+"\n </span>\n </div>\n ";return A}function y(B,A){return"database"}function x(D,C){var A="",B;A+='\n <div class="dataset-info">\n <span class="value">';if(B=p.misc_info){B=B.call(D,{hash:{},data:C})}else{B=D.misc_info;B=typeof B===e?B.apply(D):B}A+=d(B)+"</span>\n </div>\n ";return A}function w(D,C){var A="",B;A+='\n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="dataset-display-applications">\n ';B=p.each.call(D,D.display_apps,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+="\n\n ";B=p.each.call(D,D.display_types,{hash:{},inverse:o.noop,fn:o.program(15,v,C),data:C});if(B||B===0){A+=B}A+='\n </div>\n\n <div class="dataset-peek">\n ';B=p["if"].call(D,D.peek,{hash:{},inverse:o.noop,fn:o.program(19,s,C),data:C});if(B||B===0){A+=B}A+="\n </div>\n\n ";return A}function v(D,C){var A="",B;A+='\n <div class="display-application">\n <span class="display-application-location">';if(B=p.label){B=B.call(D,{hash:{},data:C})}else{B=D.label;B=typeof B===e?B.apply(D):B}A+=d(B)+'</span>\n <span class="display-application-links">\n ';B=p.each.call(D,D.links,{hash:{},inverse:o.noop,fn:o.program(16,u,C),data:C});if(B||B===0){A+=B}A+="\n </span>\n </div>\n ";return A}function u(E,D){var A="",C,B;A+='\n <a target="';if(C=p.target){C=C.call(E,{hash:{},data:D})}else{C=E.target;C=typeof C===e?C.apply(E):C}A+=d(C)+'" href="';if(C=p.href){C=C.call(E,{hash:{},data:D})}else{C=E.href;C=typeof C===e?C.apply(E):C}A+=d(C)+'">';B={hash:{},inverse:o.noop,fn:o.program(17,t,D),data:D};if(C=p.local){C=C.call(E,B)}else{C=E.local;C=typeof C===e?C.apply(E):C}if(!p.local){C=c.call(E,C,B)}if(C||C===0){A+=C}A+="</a>\n ";return A}function t(C,B){var A;if(A=p.text){A=A.call(C,{hash:{},data:B})}else{A=C.text;A=typeof A===e?A.apply(C):A}return d(A)}function s(D,C){var A="",B;A+='\n <pre class="peek">';if(B=p.peek){B=B.call(D,{hash:{},data:C})}else{B=D.peek;B=typeof B===e?B.apply(D):B}if(B||B===0){A+=B}A+="</pre>\n ";return A}q+='<div class="dataset-body">\n ';h=p["if"].call(r,r.body,{hash:{},inverse:o.program(3,m,z),fn:o.program(1,n,z),data:z});if(h||h===0){q+=h}q+="\n</div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-skeleton"]=b(function(f,r,p,k,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,f.helpers);w=w||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var x="",z,y;x+='\n <div class="errormessagesmall">\n ';y={hash:{},inverse:o.noop,fn:o.program(2,m,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+=":\n ";y={hash:{},inverse:o.noop,fn:o.program(4,l,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </div>\n ";return x}function m(y,x){return"There was an error getting the data for this dataset"}function l(z,y){var x;if(x=p.error){x=x.call(z,{hash:{},data:y})}else{x=z.error;x=typeof x===e?x.apply(z):x}return d(x)}function j(A,z){var x="",y;x+="\n ";y=p["if"].call(A,A.purged,{hash:{},inverse:o.program(10,v,z),fn:o.program(7,i,z),data:z});if(y||y===0){x+=y}x+="\n ";return x}function i(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(8,g,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n\n ";return x}function g(y,x){return"This dataset has been deleted and removed from disk."}function v(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(11,u,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+='\n \n \n Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it\n or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk\n </strong></div>\n ';return x}function u(y,x){return"This dataset has been deleted."}function t(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(14,s,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+='\n \n Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it\n </strong></div>\n ';return x}function s(y,x){return"This dataset has been hidden."}q+='<div class="dataset hda">\n <div class="dataset-warnings">\n ';h=p["if"].call(r,r.error,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(6,j,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p.unless.call(r,r.visible,{hash:{},inverse:o.noop,fn:o.program(13,t,w),data:w});if(h||h===0){q+=h}q+='\n </div>\n\n <div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>\n <div class="dataset-primary-actions"></div>\n \n <div class="dataset-title-bar clear" tabindex="0">\n <span class="dataset-state-icon state-icon"></span>\n <div class="dataset-title">\n <span class="hda-hid">';if(h=p.hid){h=h.call(r,{hash:{},data:w})}else{h=r.hid;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n <span class="dataset-name">';if(h=p.name){h=h.call(r,{hash:{},data:w})}else{h=r.name;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n </div>\n </div>\n\n <div class="dataset-body"></div>\n</div>';return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-hda-skeleton"]=b(function(f,r,p,k,w){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,f.helpers);w=w||{};var q="",h,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var x="",z,y;x+='\n <div class="errormessagesmall">\n ';y={hash:{},inverse:o.noop,fn:o.program(2,m,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+=":\n ";y={hash:{},inverse:o.noop,fn:o.program(4,l,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </div>\n ";return x}function m(y,x){return"There was an error getting the data for this dataset"}function l(z,y){var x;if(x=p.error){x=x.call(z,{hash:{},data:y})}else{x=z.error;x=typeof x===e?x.apply(z):x}return d(x)}function j(A,z){var x="",y;x+="\n ";y=p["if"].call(A,A.purged,{hash:{},inverse:o.program(10,v,z),fn:o.program(7,i,z),data:z});if(y||y===0){x+=y}x+="\n ";return x}function i(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(8,g,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+="\n </strong></div>\n\n ";return x}function g(y,x){return"This dataset has been deleted and removed from disk."}function v(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(11,u,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+='\n \n \n Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it\n or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk\n </strong></div>\n ';return x}function u(y,x){return"This dataset has been deleted."}function t(B,A){var x="",z,y;x+='\n <div class="warningmessagesmall"><strong>\n ';y={hash:{},inverse:o.noop,fn:o.program(14,s,A),data:A};if(z=p.local){z=z.call(B,y)}else{z=B.local;z=typeof z===e?z.apply(B):z}if(!p.local){z=c.call(B,z,y)}if(z||z===0){x+=z}x+='\n \n Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it\n </strong></div>\n ';return x}function s(y,x){return"This dataset has been hidden."}q+='<div class="dataset hda">\n <div class="dataset-warnings">\n ';h=p["if"].call(r,r.error,{hash:{},inverse:o.noop,fn:o.program(1,n,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(6,j,w),data:w});if(h||h===0){q+=h}q+="\n\n ";h=p.unless.call(r,r.visible,{hash:{},inverse:o.noop,fn:o.program(13,t,w),data:w});if(h||h===0){q+=h}q+='\n </div>\n\n <div class="dataset-selector"><span class="fa fa-2x fa-square-o"></span></div>\n <div class="dataset-primary-actions"></div>\n <div class="dataset-title-bar clear" tabindex="0">\n <span class="dataset-state-icon state-icon"></span>\n <div class="dataset-title">\n <span class="hda-hid">';if(h=p.hid){h=h.call(r,{hash:{},data:w})}else{h=r.hid;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n <span class="dataset-name">';if(h=p.name){h=h.call(r,{hash:{},data:w})}else{h=r.name;h=typeof h===e?h.apply(r):h}q+=d(h)+'</span>\n </div>\n </div>\n\n <div class="dataset-body"></div>\n</div>';return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,t){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);t=t||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(x,w){var u="",v;u+='\n <div class="history-name">\n ';if(v=p.name){v=v.call(x,{hash:{},data:w})}else{v=x.name;v=typeof v===e?v.apply(x):v}u+=d(v)+"\n </div>\n ";return u}function m(x,w){var u="",v;u+='\n <div class="history-size">';if(v=p.nice_size){v=v.call(x,{hash:{},data:w})}else{v=x.nice_size;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function k(x,w){var u="",v;u+='\n \n <div class="';if(v=p.status){v=v.call(x,{hash:{},data:w})}else{v=x.status;v=typeof v===e?v.apply(x):v}u+=d(v)+'message">';if(v=p.message){v=v.call(x,{hash:{},data:w})}else{v=x.message;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function j(v,u){return"You are over your disk quota"}function g(v,u){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(v,u){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,t),data:t});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(11,s,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(g,r,p,l,x){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);x=x||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var y="",z;y+='\n <div class="history-name">\n ';if(z=p.name){z=z.call(B,{hash:{},data:A})}else{z=B.name;z=typeof z===e?z.apply(B):z}y+=d(z)+"\n </div>\n ";return y}function m(B,A){var y="",z;y+='\n <div class="history-size">';if(z=p.nice_size){z=z.call(B,{hash:{},data:A})}else{z=B.nice_size;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function k(C,B){var y="",A,z;y+='\n <div class="warningmessagesmall"><strong>\n ';z={hash:{},inverse:o.noop,fn:o.program(6,j,B),data:B};if(A=p.local){A=A.call(C,z)}else{A=C.local;A=typeof A===e?A.apply(C):A}if(!p.local){A=c.call(C,A,z)}if(A||A===0){y+=A}y+="\n </strong></div>\n ";return y}function j(z,y){return"You are currently viewing a deleted history!"}function h(B,A){var y="",z;y+='\n \n <div class="';if(z=p.status){z=z.call(B,{hash:{},data:A})}else{z=B.status;z=typeof z===e?z.apply(B):z}y+=d(z)+'message">';if(z=p.message){z=z.call(B,{hash:{},data:A})}else{z=B.message;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function w(z,y){return"You are over your disk quota"}function v(z,y){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function u(z,y){return"Select all"}function t(z,y){return"For all selected"}function s(z,y){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(5,k,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(8,h,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(10,w,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(12,v,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(14,u,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(16,t,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(18,s,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/packed/templates/compiled/template-history-historyPanel-anon.js
--- a/static/scripts/packed/templates/compiled/template-history-historyPanel-anon.js
+++ b/static/scripts/packed/templates/compiled/template-history-historyPanel-anon.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(g,r,p,k,u){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);u=u||{};var q="",i,f,o=this,e="function",c=p.blockHelperMissing,d=this.escapeExpression;function n(z,y){var v="",x,w;v+='\n <div class="history-name" title="';w={hash:{},inverse:o.noop,fn:o.program(2,m,y),data:y};if(x=p.local){x=x.call(z,w)}else{x=z.local;x=typeof x===e?x.apply(z):x}if(!p.local){x=c.call(z,x,w)}if(x||x===0){v+=x}v+='">\n ';if(x=p.name){x=x.call(z,{hash:{},data:y})}else{x=z.name;x=typeof x===e?x.apply(z):x}v+=d(x)+"\n </div>\n ";return v}function m(w,v){return"You must be logged in to edit your history name"}function l(y,x){var v="",w;v+='\n <div class="history-size">';if(w=p.nice_size){w=w.call(y,{hash:{},data:x})}else{w=y.nice_size;w=typeof w===e?w.apply(y):w}v+=d(w)+"</div>\n ";return v}function j(y,x){var v="",w;v+='\n \n <div class="';if(w=p.status){w=w.call(y,{hash:{},data:x})}else{w=y.status;w=typeof w===e?w.apply(y):w}v+=d(w)+'message">';if(w=p.message){w=w.call(y,{hash:{},data:x})}else{w=y.message;w=typeof w===e?w.apply(y):w}v+=d(w)+"</div>\n ";return v}function h(w,v){return"You are over your disk quota"}function t(w,v){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(w,v){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,u),data:u});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(4,l,u),data:u});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(6,j,u),data:u});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(8,h,u),data:u};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(10,t,u),data:u};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(12,s,u),data:u};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel-anon"]=b(function(h,r,p,l,t){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,h.helpers);t=t||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(x,w){var u="",v;u+='\n <div class="history-name">\n ';if(v=p.name){v=v.call(x,{hash:{},data:w})}else{v=x.name;v=typeof v===e?v.apply(x):v}u+=d(v)+"\n </div>\n ";return u}function m(x,w){var u="",v;u+='\n <div class="history-size">';if(v=p.nice_size){v=v.call(x,{hash:{},data:w})}else{v=x.nice_size;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function k(x,w){var u="",v;u+='\n \n <div class="';if(v=p.status){v=v.call(x,{hash:{},data:w})}else{v=x.status;v=typeof v===e?v.apply(x):v}u+=d(v)+'message">';if(v=p.message){v=v.call(x,{hash:{},data:w})}else{v=x.message;v=typeof v===e?v.apply(x):v}u+=d(v)+"</div>\n ";return u}function j(v,u){return"You are over your disk quota"}function g(v,u){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function s(v,u){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n \n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,t),data:t});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(5,k,t),data:t});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(7,j,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(9,g,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(11,s,t),data:t};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/packed/templates/compiled/template-history-historyPanel.js
--- a/static/scripts/packed/templates/compiled/template-history-historyPanel.js
+++ b/static/scripts/packed/templates/compiled/template-history-historyPanel.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(h,s,q,l,y){this.compilerInfo=[4,">= 1.0.0"];q=this.merge(q,h.helpers);y=y||{};var r="",i,f,p=this,e="function",c=q.blockHelperMissing,d=this.escapeExpression;function o(D,C){var z="",B,A;z+='\n <div class="history-name" title="';A={hash:{},inverse:p.noop,fn:p.program(2,n,C),data:C};if(B=q.local){B=B.call(D,A)}else{B=D.local;B=typeof B===e?B.apply(D):B}if(!q.local){B=c.call(D,B,A)}if(B||B===0){z+=B}z+='">\n ';if(B=q.name){B=B.call(D,{hash:{},data:C})}else{B=D.name;B=typeof B===e?B.apply(D):B}z+=d(B)+"\n </div>\n ";return z}function n(A,z){return"Click to rename history"}function m(C,B){var z="",A;z+='\n <div class="history-size">';if(A=q.nice_size){A=A.call(C,{hash:{},data:B})}else{A=C.nice_size;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function k(D,C){var z="",B,A;z+='\n <div class="warningmessagesmall"><strong>\n ';A={hash:{},inverse:p.noop,fn:p.program(7,j,C),data:C};if(B=q.local){B=B.call(D,A)}else{B=D.local;B=typeof B===e?B.apply(D):B}if(!q.local){B=c.call(D,B,A)}if(B||B===0){z+=B}z+="\n </strong></div>\n ";return z}function j(A,z){return"You are currently viewing a deleted history!"}function g(C,B){var z="",A;z+='\n \n <div class="';if(A=q.status){A=A.call(C,{hash:{},data:B})}else{A=C.status;A=typeof A===e?A.apply(C):A}z+=d(A)+'message">';if(A=q.message){A=A.call(C,{hash:{},data:B})}else{A=C.message;A=typeof A===e?A.apply(C):A}z+=d(A)+"</div>\n ";return z}function x(A,z){return"You are over your disk quota"}function w(A,z){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function v(A,z){return"Select all"}function u(A,z){return"For all selected"}function t(A,z){return"Your history is empty. Click 'Get Data' on the left pane to start"}r+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n ';i=q["if"].call(s,s.name,{hash:{},inverse:p.noop,fn:p.program(1,o,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=q["if"].call(s,s.nice_size,{hash:{},inverse:p.noop,fn:p.program(4,m,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=q["if"].call(s,s.deleted,{hash:{},inverse:p.noop,fn:p.program(6,k,y),data:y});if(i||i===0){r+=i}r+='\n\n <div class="message-container">\n ';i=q["if"].call(s,s.message,{hash:{},inverse:p.noop,fn:p.program(9,g,y),data:y});if(i||i===0){r+=i}r+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:p.noop,fn:p.program(11,x,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+=".\n ";f={hash:{},inverse:p.noop,fn:p.program(13,w,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:p.noop,fn:p.program(15,v,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:p.noop,fn:p.program(17,u,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:p.noop,fn:p.program(19,t,y),data:y};if(i=q.local){i=i.call(s,f)}else{i=s.local;i=typeof i===e?i.apply(s):i}if(!q.local){i=c.call(s,i,f)}if(i||i===0){r+=i}r+="\n </div>";return r})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(g,r,p,l,x){this.compilerInfo=[4,">= 1.0.0"];p=this.merge(p,g.helpers);x=x||{};var q="",i,f,e="function",d=this.escapeExpression,o=this,c=p.blockHelperMissing;function n(B,A){var y="",z;y+='\n <div class="history-name">\n ';if(z=p.name){z=z.call(B,{hash:{},data:A})}else{z=B.name;z=typeof z===e?z.apply(B):z}y+=d(z)+"\n </div>\n ";return y}function m(B,A){var y="",z;y+='\n <div class="history-size">';if(z=p.nice_size){z=z.call(B,{hash:{},data:A})}else{z=B.nice_size;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function k(C,B){var y="",A,z;y+='\n <div class="warningmessagesmall"><strong>\n ';z={hash:{},inverse:o.noop,fn:o.program(6,j,B),data:B};if(A=p.local){A=A.call(C,z)}else{A=C.local;A=typeof A===e?A.apply(C):A}if(!p.local){A=c.call(C,A,z)}if(A||A===0){y+=A}y+="\n </strong></div>\n ";return y}function j(z,y){return"You are currently viewing a deleted history!"}function h(B,A){var y="",z;y+='\n \n <div class="';if(z=p.status){z=z.call(B,{hash:{},data:A})}else{z=B.status;z=typeof z===e?z.apply(B):z}y+=d(z)+'message">';if(z=p.message){z=z.call(B,{hash:{},data:A})}else{z=B.message;z=typeof z===e?z.apply(B):z}y+=d(z)+"</div>\n ";return y}function w(z,y){return"You are over your disk quota"}function v(z,y){return"Tool execution is on hold until your disk usage drops below your allocated quota"}function u(z,y){return"Select all"}function t(z,y){return"For all selected"}function s(z,y){return"Your history is empty. Click 'Get Data' on the left pane to start"}q+='<div class="history-controls">\n <div class="history-search-controls"></div>\n\n <div class="history-title">\n ';i=p["if"].call(r,r.name,{hash:{},inverse:o.noop,fn:o.program(1,n,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="history-subtitle clear">\n ';i=p["if"].call(r,r.nice_size,{hash:{},inverse:o.noop,fn:o.program(3,m,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="history-secondary-actions"></div>\n </div>\n\n ';i=p["if"].call(r,r.deleted,{hash:{},inverse:o.noop,fn:o.program(5,k,x),data:x});if(i||i===0){q+=i}q+='\n\n <div class="message-container">\n ';i=p["if"].call(r,r.message,{hash:{},inverse:o.noop,fn:o.program(8,h,x),data:x});if(i||i===0){q+=i}q+='\n </div>\n\n <div class="quota-message errormessage">\n ';f={hash:{},inverse:o.noop,fn:o.program(10,w,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+=".\n ";f={hash:{},inverse:o.noop,fn:o.program(12,v,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='.\n </div>\n \n <div class="tags-display"></div>\n <div class="annotation-display"></div>\n\n <div class="history-dataset-actions">\n <button class="history-select-all-datasets-btn btn btn-default"\n data-mode="select">';f={hash:{},inverse:o.noop,fn:o.program(14,u,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='</button>\n <button class="history-dataset-action-popup-btn btn btn-default"\n >';f={hash:{},inverse:o.noop,fn:o.program(16,t,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+='...</button>\n </div>\n\n </div>\n\n \n <div class="datasets-list"></div>\n\n <div class="empty-history-message infomessagesmall">\n ';f={hash:{},inverse:o.noop,fn:o.program(18,s,x),data:x};if(i=p.local){i=i.call(r,f)}else{i=r.local;i=typeof i===e?i.apply(r):i}if(!p.local){i=c.call(r,i,f)}if(i||i===0){q+=i}q+="\n </div>";return q})})();
\ No newline at end of file
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/templates/compiled/history-templates.js
--- a/static/scripts/templates/compiled/history-templates.js
+++ b/static/scripts/templates/compiled/history-templates.js
@@ -305,34 +305,148 @@
});
})();(function() {
var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
-templates['template-history-historyPanel-anon'] = template(function (Handlebars,depth0,helpers,partials,data) {
+templates['template-hda-skeleton'] = template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
- var buffer = "", stack1, options, self=this, functionType="function", blockHelperMissing=helpers.blockHelperMissing, escapeExpression=this.escapeExpression;
+ var buffer = "", stack1, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
function program1(depth0,data) {
var buffer = "", stack1, options;
- buffer += "\n <div class=\"history-name\" title=\"";
+ buffer += "\n <div class=\"errormessagesmall\">\n ";
options = {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\">\n ";
+ buffer += ":\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </div>\n ";
+ return buffer;
+ }
+function program2(depth0,data) {
+
+
+ return "There was an error getting the data for this dataset";
+ }
+
+function program4(depth0,data) {
+
+ var stack1;
+ if (stack1 = helpers.error) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.error; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ return escapeExpression(stack1);
+ }
+
+function program6(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n ";
+ stack1 = helpers['if'].call(depth0, depth0.purged, {hash:{},inverse:self.program(10, program10, data),fn:self.program(7, program7, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ return buffer;
+ }
+function program7(depth0,data) {
+
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"warningmessagesmall\"><strong>\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </strong></div>\n\n ";
+ return buffer;
+ }
+function program8(depth0,data) {
+
+
+ return "This dataset has been deleted and removed from disk.";
+ }
+
+function program10(depth0,data) {
+
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"warningmessagesmall\"><strong>\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n "
+ + "\n "
+ + "\n Click <a href=\"javascript:void(0);\" class=\"dataset-undelete\">here</a> to undelete it\n or <a href=\"javascript:void(0);\" class=\"dataset-purge\">here</a> to immediately remove it from disk\n </strong></div>\n ";
+ return buffer;
+ }
+function program11(depth0,data) {
+
+
+ return "This dataset has been deleted.";
+ }
+
+function program13(depth0,data) {
+
+ var buffer = "", stack1, options;
+ buffer += "\n <div class=\"warningmessagesmall\"><strong>\n ";
+ options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
+ if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n "
+ + "\n Click <a href=\"javascript:void(0);\" class=\"dataset-unhide\">here</a> to unhide it\n </strong></div>\n ";
+ return buffer;
+ }
+function program14(depth0,data) {
+
+
+ return "This dataset has been hidden.";
+ }
+
+ buffer += "<div class=\"dataset hda\">\n <div class=\"dataset-warnings\">\n ";
+ stack1 = helpers['if'].call(depth0, depth0.error, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n ";
+ stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n ";
+ stack1 = helpers.unless.call(depth0, depth0.visible, {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </div>\n\n <div class=\"dataset-selector\"><span class=\"fa fa-2x fa-square-o\"></span></div>\n <div class=\"dataset-primary-actions\"></div>\n <div class=\"dataset-title-bar clear\" tabindex=\"0\">\n <span class=\"dataset-state-icon state-icon\"></span>\n <div class=\"dataset-title\">\n <span class=\"hda-hid\">";
+ if (stack1 = helpers.hid) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.hid; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ buffer += escapeExpression(stack1)
+ + "</span>\n <span class=\"dataset-name\">";
+ if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
+ else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
+ buffer += escapeExpression(stack1)
+ + "</span>\n </div>\n </div>\n\n <div class=\"dataset-body\"></div>\n</div>";
+ return buffer;
+ });
+})();(function() {
+ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
+templates['template-history-historyPanel-anon'] = template(function (Handlebars,depth0,helpers,partials,data) {
+ this.compilerInfo = [4,'>= 1.0.0'];
+helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
+ var buffer = "", stack1, options, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
+
+function program1(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n <div class=\"history-name\">\n ";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "\n </div>\n ";
return buffer;
}
-function program2(depth0,data) {
-
-
- return "You must be logged in to edit your history name";
- }
-function program4(depth0,data) {
+function program3(depth0,data) {
var buffer = "", stack1;
buffer += "\n <div class=\"history-size\">";
@@ -343,7 +457,7 @@
return buffer;
}
-function program6(depth0,data) {
+function program5(depth0,data) {
var buffer = "", stack1;
buffer += "\n "
@@ -359,19 +473,19 @@
return buffer;
}
-function program8(depth0,data) {
+function program7(depth0,data) {
return "You are over your disk quota";
}
-function program10(depth0,data) {
+function program9(depth0,data) {
return "Tool execution is on hold until your disk usage drops below your allocated quota";
}
-function program12(depth0,data) {
+function program11(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";
@@ -382,19 +496,19 @@
stack1 = helpers['if'].call(depth0, depth0.name, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += ".\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(10, program10, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(9, program9, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -402,7 +516,7 @@
buffer += ".\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(12, program12, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -415,31 +529,20 @@
templates['template-history-historyPanel'] = template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
- var buffer = "", stack1, options, self=this, functionType="function", blockHelperMissing=helpers.blockHelperMissing, escapeExpression=this.escapeExpression;
+ var buffer = "", stack1, options, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
function program1(depth0,data) {
- var buffer = "", stack1, options;
- buffer += "\n <div class=\"history-name\" title=\"";
- options = {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\">\n ";
+ var buffer = "", stack1;
+ buffer += "\n <div class=\"history-name\">\n ";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "\n </div>\n ";
return buffer;
}
-function program2(depth0,data) {
-
-
- return "Click to rename history";
- }
-function program4(depth0,data) {
+function program3(depth0,data) {
var buffer = "", stack1;
buffer += "\n <div class=\"history-size\">";
@@ -450,11 +553,11 @@
return buffer;
}
-function program6(depth0,data) {
+function program5(depth0,data) {
var buffer = "", stack1, options;
buffer += "\n <div class=\"warningmessagesmall\"><strong>\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -462,13 +565,13 @@
buffer += "\n </strong></div>\n ";
return buffer;
}
-function program7(depth0,data) {
+function program6(depth0,data) {
return "You are currently viewing a deleted history!";
}
-function program9(depth0,data) {
+function program8(depth0,data) {
var buffer = "", stack1;
buffer += "\n "
@@ -484,31 +587,31 @@
return buffer;
}
-function program11(depth0,data) {
+function program10(depth0,data) {
return "You are over your disk quota";
}
-function program13(depth0,data) {
+function program12(depth0,data) {
return "Tool execution is on hold until your disk usage drops below your allocated quota";
}
-function program15(depth0,data) {
+function program14(depth0,data) {
return "Select all";
}
-function program17(depth0,data) {
+function program16(depth0,data) {
return "For all selected";
}
-function program19(depth0,data) {
+function program18(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";
@@ -518,34 +621,34 @@
stack1 = helpers['if'].call(depth0, depth0.name, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n ";
- stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"message-container\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(9, program9, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(10, program10, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += ".\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(12, program12, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
- options = {hash:{},inverse:self.noop,fn:self.program(15, program15, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "</button>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
- options = {hash:{},inverse:self.noop,fn:self.program(17, program17, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(16, program16, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -553,7 +656,7 @@
buffer += "...</button>\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(19, program19, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/templates/compiled/template-history-historyPanel-anon.js
--- a/static/scripts/templates/compiled/template-history-historyPanel-anon.js
+++ b/static/scripts/templates/compiled/template-history-historyPanel-anon.js
@@ -3,31 +3,20 @@
templates['template-history-historyPanel-anon'] = template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
- var buffer = "", stack1, options, self=this, functionType="function", blockHelperMissing=helpers.blockHelperMissing, escapeExpression=this.escapeExpression;
+ var buffer = "", stack1, options, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
function program1(depth0,data) {
- var buffer = "", stack1, options;
- buffer += "\n <div class=\"history-name\" title=\"";
- options = {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\">\n ";
+ var buffer = "", stack1;
+ buffer += "\n <div class=\"history-name\">\n ";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "\n </div>\n ";
return buffer;
}
-function program2(depth0,data) {
-
-
- return "You must be logged in to edit your history name";
- }
-function program4(depth0,data) {
+function program3(depth0,data) {
var buffer = "", stack1;
buffer += "\n <div class=\"history-size\">";
@@ -38,7 +27,7 @@
return buffer;
}
-function program6(depth0,data) {
+function program5(depth0,data) {
var buffer = "", stack1;
buffer += "\n "
@@ -54,19 +43,19 @@
return buffer;
}
-function program8(depth0,data) {
+function program7(depth0,data) {
return "You are over your disk quota";
}
-function program10(depth0,data) {
+function program9(depth0,data) {
return "Tool execution is on hold until your disk usage drops below your allocated quota";
}
-function program12(depth0,data) {
+function program11(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";
@@ -77,19 +66,19 @@
stack1 = helpers['if'].call(depth0, depth0.name, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n <div class=\"message-container\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += ".\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(10, program10, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(9, program9, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -97,7 +86,7 @@
buffer += ".\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(12, program12, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/templates/compiled/template-history-historyPanel.js
--- a/static/scripts/templates/compiled/template-history-historyPanel.js
+++ b/static/scripts/templates/compiled/template-history-historyPanel.js
@@ -3,31 +3,20 @@
templates['template-history-historyPanel'] = template(function (Handlebars,depth0,helpers,partials,data) {
this.compilerInfo = [4,'>= 1.0.0'];
helpers = this.merge(helpers, Handlebars.helpers); data = data || {};
- var buffer = "", stack1, options, self=this, functionType="function", blockHelperMissing=helpers.blockHelperMissing, escapeExpression=this.escapeExpression;
+ var buffer = "", stack1, options, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing;
function program1(depth0,data) {
- var buffer = "", stack1, options;
- buffer += "\n <div class=\"history-name\" title=\"";
- options = {hash:{},inverse:self.noop,fn:self.program(2, program2, data),data:data};
- if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
- else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
- if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
- if(stack1 || stack1 === 0) { buffer += stack1; }
- buffer += "\">\n ";
+ var buffer = "", stack1;
+ buffer += "\n <div class=\"history-name\">\n ";
if (stack1 = helpers.name) { stack1 = stack1.call(depth0, {hash:{},data:data}); }
else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
buffer += escapeExpression(stack1)
+ "\n </div>\n ";
return buffer;
}
-function program2(depth0,data) {
-
-
- return "Click to rename history";
- }
-function program4(depth0,data) {
+function program3(depth0,data) {
var buffer = "", stack1;
buffer += "\n <div class=\"history-size\">";
@@ -38,11 +27,11 @@
return buffer;
}
-function program6(depth0,data) {
+function program5(depth0,data) {
var buffer = "", stack1, options;
buffer += "\n <div class=\"warningmessagesmall\"><strong>\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(7, program7, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -50,13 +39,13 @@
buffer += "\n </strong></div>\n ";
return buffer;
}
-function program7(depth0,data) {
+function program6(depth0,data) {
return "You are currently viewing a deleted history!";
}
-function program9(depth0,data) {
+function program8(depth0,data) {
var buffer = "", stack1;
buffer += "\n "
@@ -72,31 +61,31 @@
return buffer;
}
-function program11(depth0,data) {
+function program10(depth0,data) {
return "You are over your disk quota";
}
-function program13(depth0,data) {
+function program12(depth0,data) {
return "Tool execution is on hold until your disk usage drops below your allocated quota";
}
-function program15(depth0,data) {
+function program14(depth0,data) {
return "Select all";
}
-function program17(depth0,data) {
+function program16(depth0,data) {
return "For all selected";
}
-function program19(depth0,data) {
+function program18(depth0,data) {
return "Your history is empty. Click 'Get Data' on the left pane to start";
@@ -106,34 +95,34 @@
stack1 = helpers['if'].call(depth0, depth0.name, {hash:{},inverse:self.noop,fn:self.program(1, program1, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"history-subtitle clear\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(4, program4, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.nice_size, {hash:{},inverse:self.noop,fn:self.program(3, program3, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"history-secondary-actions\"></div>\n </div>\n\n ";
- stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(6, program6, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.deleted, {hash:{},inverse:self.noop,fn:self.program(5, program5, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n\n <div class=\"message-container\">\n ";
- stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(9, program9, data),data:data});
+ stack1 = helpers['if'].call(depth0, depth0.message, {hash:{},inverse:self.noop,fn:self.program(8, program8, data),data:data});
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "\n </div>\n\n <div class=\"quota-message errormessage\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(11, program11, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(10, program10, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += ".\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(13, program13, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(12, program12, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += ".\n </div>\n \n <div class=\"tags-display\"></div>\n <div class=\"annotation-display\"></div>\n\n <div class=\"history-dataset-actions\">\n <button class=\"history-select-all-datasets-btn btn btn-default\"\n data-mode=\"select\">";
- options = {hash:{},inverse:self.noop,fn:self.program(15, program15, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(14, program14, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
if(stack1 || stack1 === 0) { buffer += stack1; }
buffer += "</button>\n <button class=\"history-dataset-action-popup-btn btn btn-default\"\n >";
- options = {hash:{},inverse:self.noop,fn:self.program(17, program17, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(16, program16, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
@@ -141,7 +130,7 @@
buffer += "...</button>\n </div>\n\n </div>"
+ "\n\n "
+ "\n <div class=\"datasets-list\"></div>\n\n <div class=\"empty-history-message infomessagesmall\">\n ";
- options = {hash:{},inverse:self.noop,fn:self.program(19, program19, data),data:data};
+ options = {hash:{},inverse:self.noop,fn:self.program(18, program18, data),data:data};
if (stack1 = helpers.local) { stack1 = stack1.call(depth0, options); }
else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1.apply(depth0) : stack1; }
if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, options); }
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/scripts/templates/history-templates.html
--- a/static/scripts/templates/history-templates.html
+++ b/static/scripts/templates/history-templates.html
@@ -6,7 +6,7 @@
<div class="history-title">
{{#if name }}
- <div class="history-name" title="{{#local}}Click to rename history{{/local}}">
+ <div class="history-name">
{{name}}
</div>
{{/if}}
@@ -68,7 +68,7 @@
<div class="history-title">
{{! wouldn't this always be 'unnamed history'? }}
{{#if name }}
- <div class="history-name" title="{{#local}}You must be logged in to edit your history name{{/local}}">
+ <div class="history-name">
{{name}}
</div>
{{/if}}
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1511,7 +1511,7 @@
.icon-btn:hover{background-color:white;color:maroon}
.icon-btn.disabled{background-color:transparent;color:rgba(0,0,0,0.05)}
.search-input .search-query{width:100%;padding-right:24px}
-.search-input .search-clear,.search-input .search-loading{position:absolute;right:15px;top:10px;font-size:1.4em;line-height:23px;color:grey}
+.search-input .search-clear,.search-input .search-loading{position:relative;float:right;left:-4px;top:-23px;font-size:1.4em;line-height:23px;color:grey}
.search-input .search-clear:hover{color:#303030}
#history-refresh-button,#history-options-button{display:inline-block;height:20px;width:20px;text-align:center;line-height:17px;font-size:1.2em;padding:0px}
.history-panel [class$="messagesmall"]{margin:0px}
@@ -1522,7 +1522,7 @@
.history-panel .history-controls{margin:10px;padding:0px}.history-panel .history-controls .history-search-controls{display:none;padding:0px 0px 8px 0px}
.history-panel .history-controls .history-title{margin-bottom:4px}
.history-panel .history-controls .history-name{word-wrap:break-word;font-weight:bold}
-.history-panel .history-controls .history-title input{font-weight:bold;width:100%;margin:-2px 0 -2px -4px}
+.history-panel .history-controls .history-title input{width:100%;margin:-2px 0 -2px -4px;font-weight:bold}
.history-panel .history-controls .history-subtitle{margin-bottom:8px}
.history-panel .history-controls .history-size{float:left}
.history-panel .history-controls .history-secondary-actions{float:right}.history-panel .history-controls .history-secondary-actions .icon-btn{margin-left:2px}
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 static/style/src/less/history.less
--- a/static/style/src/less/history.less
+++ b/static/style/src/less/history.less
@@ -68,9 +68,10 @@
.search-clear,
.search-loading {
// it places the icons on the right of the bar (and puts the lotion on its skin)
- position : absolute;
- right : 15px;
- top : 10px;
+ position : relative;
+ float : right;
+ left : -4px;
+ top : -23px;
font-size : 1.4em;
line-height : 23px;
color : grey;
@@ -134,10 +135,10 @@
font-weight: bold;
}
.history-title input {
- font-weight: bold;
width: 100%;
// keep the text in position
margin: -2px 0px -2px -4px;
+ font-weight: bold;
}
.history-subtitle {
@@ -312,13 +313,6 @@
.dataset-padding;
.dataset-state-icon {
- //display: inline-block;
- //vertical-align: middle;
- //line-height: 16px;
- //width: 16px;
- //height: 16px;
- //background-position: 0 1px;
- //background-repeat: no-repeat;
}
.dataset-title {
display: inline;
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 templates/webapps/galaxy/history/history_panel.mako
--- a/templates/webapps/galaxy/history/history_panel.mako
+++ b/templates/webapps/galaxy/history/history_panel.mako
@@ -2,10 +2,12 @@
## ----------------------------------------------------------------------------
<%def name="current_history_panel( selector_to_attach_to=None, show_deleted=None, show_hidden=None, hda_id=None )">
+
+${history_panel_javascripts()}
+
<script type="text/javascript">
-function onModuleReady( historyPanel ){
+onhistoryready.done( function( historyPanel ){
// attach a panel to selector_to_attach_to and load the current history/hdas over the api
-
var currPanel = new historyPanel.HistoryPanel({
// is page sending in show settings? if so override history's
show_deleted : ${ 'true' if show_deleted == True else ( 'null' if show_deleted == None else 'false' ) },
@@ -22,43 +24,45 @@
}
});
Galaxy.currHistoryPanel = currPanel;
-}
+});
</script>
-
-${history_panel_javascripts()}
</%def>
## ----------------------------------------------------------------------------
<%def name="history_panel( history_id, selector_to_attach_to=None, \
show_deleted=None, show_hidden=None, hda_id=None )">
+
+${history_panel_javascripts()}
+
<script type="text/javascript">
-function onModuleReady( historyPanel ){
+onhistoryready.done( function( historyPanel ){
// attach a panel to selector_to_attach_to and load the history/hdas with the given history_id over the api
-
var panel = new historyPanel.HistoryPanel({
show_deleted : ${ 'true' if show_deleted == True else ( 'null' if show_deleted == None else 'false' ) },
show_hidden : ${ 'true' if show_hidden == True else ( 'null' if show_hidden == None else 'false' ) },
el : $( "${selector_to_attach_to}" ),
onready : function loadHistoryById(){
var panel = this;
- this.loadHistoryWithDetails( '${history_id}' )
+ this.loadHistoryWithHDADetails( '${history_id}' )
.fail( function(){
panel.render();
});
}
});
+});
</script>
-
-${history_panel_javascripts()}
</%def>
## ----------------------------------------------------------------------------
<%def name="bootstrapped_history_panel( history, hdas, selector_to_attach_to=None, \
show_deleted=None, show_hidden=None, hda_id=None )">
+
+${history_panel_javascripts()}
+
<script type="text/javascript">
-function onModuleReady( historyPanel ){
+onhistoryready.done( function( historyPanel ){
// attach a panel to selector_to_attach_to and use a history model with bootstrapped data
// history module is already in the dpn chain from the panel. We can re-scope it here.
@@ -67,9 +71,6 @@
historyJSON = ${h.to_json_string( history )},
hdaJSON = ${h.to_json_string( hdas )};
- // i don't like this history+user relationship, but user authentication changes views/behaviour
- historyJSON.user = Galaxy.currUser.toJSON();
-
var history = new historyModel.History( historyJSON, hdaJSON, {
logger: ( debugging )?( console ):( null )
});
@@ -81,16 +82,17 @@
model : history,
onready : function(){ this.render(); }
});
-}
+})
</script>
-
-${history_panel_javascripts()}
</%def>
## ----------------------------------------------------------------------------- generic 'base' function
<%def name="history_panel_javascripts()">
+<% print 'history_panel_javascripts' %>
${h.js(
+ "utils/localization",
+ "mvc/base-mvc",
"mvc/tags", "mvc/annotations"
)}
@@ -131,7 +133,9 @@
])}
<script type="text/javascript">
-var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false;
+var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false,
+ // use deferred to allow multiple callbacks (.done())
+ onhistoryready = jQuery.Deferred();
require.config({
baseUrl : "${h.url_for( '/static/scripts' )}"
@@ -145,7 +149,7 @@
//require([ "/static/scripts/history-panel.min.js" ], function( historyPanel ){
require([ "mvc/history/history-panel" ], function( historyPanel ){
- onModuleReady( historyPanel );
+ onhistoryready.resolve( historyPanel )
});
</script></%def>
diff -r 206055969b7cedcbfcac36c19428b9547cd5cb5d -r 7e45d419c54da8122f7b5d8e0ace3641e450a727 templates/webapps/galaxy/root/history.mako
--- a/templates/webapps/galaxy/root/history.mako
+++ b/templates/webapps/galaxy/root/history.mako
@@ -43,7 +43,8 @@
${history_panel_javascripts()}
<script type="text/javascript">
-function onModuleReady( historyPanel ){
+onhistoryready.done( function( historyPanel ){
+
// history module is already in the dpn chain from the panel. We can re-scope it here.
var historyModel = require( 'mvc/history/history-model' ),
debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false,
@@ -66,7 +67,7 @@
}
}
});
-}
+})
</script></%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: UsesHistoryMixin: add get_user_histories; use in History API, index
by commits-noreply@bitbucket.org 11 Dec '13
by commits-noreply@bitbucket.org 11 Dec '13
11 Dec '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/206055969b7c/
Changeset: 206055969b7c
User: carlfeberhard
Date: 2013-12-11 17:55:59
Summary: UsesHistoryMixin: add get_user_histories; use in History API, index
Affected #: 2 files
diff -r a831eb375268fcf80479f7bf325ec7d8a757582c -r 206055969b7cedcbfcac36c19428b9547cd5cb5d lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -30,7 +30,7 @@
from galaxy.web.form_builder import AddressField, CheckboxField, SelectField, TextArea, TextField
from galaxy.web.form_builder import build_select_field, HistoryField, PasswordField, WorkflowField, WorkflowMappingField
from galaxy.workflow.modules import module_factory
-from galaxy.model.orm import eagerload, eagerload_all
+from galaxy.model.orm import eagerload, eagerload_all, desc
from galaxy.security.validate_user_input import validate_publicname
from galaxy.util.sanitize_html import sanitize_html
from galaxy.model.item_attrs import Dictifiable
@@ -341,6 +341,28 @@
history = self.security_check( trans, history, check_ownership, check_accessible )
return history
+ def get_user_histories( self, trans, user=None, include_deleted=False, only_deleted=False ):
+ """
+ Get all the histories for a given user (defaulting to `trans.user`)
+ ordered by update time and filtered on whether they've been deleted.
+ """
+ # handle default and/or anonymous user (which still may not have a history yet)
+ user = user or trans.user
+ if not user:
+ current_history = trans.get_history()
+ return [ current_history ] if current_history else []
+
+ history_model = trans.model.History
+ query = ( trans.sa_session.query( history_model )
+ .filter( history_model.user == user )
+ .order_by( desc( history_model.table.c.update_time ) ) )
+ if only_deleted:
+ query = query.filter( history_model.deleted == True )
+ elif not include_deleted:
+ query = query.filter( history_model.deleted == False )
+
+ return query.all()
+
def get_history_datasets( self, trans, history, show_deleted=False, show_hidden=False, show_purged=False ):
""" Returns history's datasets. """
query = trans.sa_session.query( trans.model.HistoryDatasetAssociation ) \
diff -r a831eb375268fcf80479f7bf325ec7d8a757582c -r 206055969b7cedcbfcac36c19428b9547cd5cb5d lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -41,11 +41,9 @@
deleted = string_as_bool( deleted )
try:
if trans.user:
- query = ( trans.sa_session.query( trans.app.model.History )
- .filter_by( user=trans.user, deleted=deleted )
- .order_by( desc( trans.app.model.History.table.c.update_time ) )
- .all() )
- for history in query:
+ histories = self.get_user_histories( trans, user=trans.user, only_deleted=deleted )
+ #for history in query:
+ for history in histories:
item = history.to_dict(value_mapper={'id':trans.security.encode_id})
item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) )
rval.append( item )
@@ -58,6 +56,7 @@
rval.append(item)
except Exception, e:
+ raise
rval = "Error in history API"
log.error( rval + ": %s" % str(e) )
trans.response.status = 500
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
10 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4ebd2f3313b2/
Changeset: 4ebd2f3313b2
User: jmchilton
Date: 2013-12-11 17:26:14
Summary: Reduce extra-module dependencies in galaxy.tools.deps.
Eliminte older elementtree dependency. Eliminate dependency on galaxy.util:string_as_bool. Only remaining dependency in galaxy.util.submodules.
PEP-8 fix up galaxy.util.submodules so it can be copied directly into the LWR.
This allowed adding the whole galaxy.tools.deps module and submodules into LWR for remote dependency resolution.
Affected #: 5 files
diff -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 -r 4ebd2f3313b21ecac0d327055b452911551ec279 lib/galaxy/tools/deps/__init__.py
--- a/lib/galaxy/tools/deps/__init__.py
+++ b/lib/galaxy/tools/deps/__init__.py
@@ -7,7 +7,7 @@
import logging
log = logging.getLogger( __name__ )
-from galaxy.util import parse_xml
+from xml.etree import ElementTree
from .resolvers import INDETERMINATE_DEPENDENCY
from .resolvers.galaxy_packages import GalaxyPackageDependencyResolver
@@ -69,8 +69,8 @@
def __build_dependency_resolvers( self, conf_file ):
if not conf_file or not os.path.exists( conf_file ):
return self.__default_dependency_resolvers()
- tree = parse_xml( conf_file )
- return self.__parse_resolver_conf_xml( tree )
+ root = ElementTree.parse( conf_file ).getroot()
+ return self.__parse_resolver_conf_xml( root )
def __default_dependency_resolvers( self ):
return [
@@ -78,14 +78,14 @@
GalaxyPackageDependencyResolver(self),
]
- def __parse_resolver_conf_xml(self, tree):
+ def __parse_resolver_conf_xml(self, root):
"""
- :param tree: Object representing the root ``<dependency_resolvers>`` object in the file.
- :type tree: ``xml.etree.ElementTree.Element``
+ :param root: Object representing the root ``<dependency_resolvers>`` object in the file.
+ :type root: ``xml.etree.ElementTree.Element``
"""
resolvers = []
- resolvers_element = tree.getroot()
+ resolvers_element = root
for resolver_element in resolvers_element.getchildren():
resolver_type = resolver_element.tag
resolver_kwds = dict(resolver_element.items())
diff -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 -r 4ebd2f3313b21ecac0d327055b452911551ec279 lib/galaxy/tools/deps/requirements.py
--- a/lib/galaxy/tools/deps/requirements.py
+++ b/lib/galaxy/tools/deps/requirements.py
@@ -19,8 +19,7 @@
def parse_requirements_from_xml( xml_root ):
"""
- >>> from galaxy.util import parse_xml
- >>> from elementtree import ElementTree
+ >>> from xml.etree import ElementTree
>>> def load_requirements( contents ):
... contents_document = '''<tool><requirements>%s</requirements></tool>'''
... root = ElementTree.fromstring( contents_document % contents )
@@ -43,7 +42,7 @@
requirements_elem = xml_root.find( "requirements" )
requirement_elems = []
- if requirements_elem:
+ if requirements_elem is not None:
requirement_elems = requirements_elem.findall( 'requirement' )
requirements = []
diff -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 -r 4ebd2f3313b21ecac0d327055b452911551ec279 lib/galaxy/tools/deps/resolvers/galaxy_packages.py
--- a/lib/galaxy/tools/deps/resolvers/galaxy_packages.py
+++ b/lib/galaxy/tools/deps/resolvers/galaxy_packages.py
@@ -1,7 +1,6 @@
from os.path import join, islink, realpath, basename, exists, abspath
from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY, Dependency
-from galaxy.util import string_as_bool
import logging
log = logging.getLogger( __name__ )
@@ -16,7 +15,7 @@
## the tool shed so allow a fallback version of the Galaxy package
## resolver that will just grab 'default' version of exact version
## unavailable.
- self.versionless = string_as_bool(kwds.get('versionless', "false"))
+ self.versionless = str(kwds.get('versionless', "false")).lower() == "true"
self.base_path = abspath( kwds.get('base_path', dependency_manager.default_base_path) )
def resolve( self, name, version, type, **kwds ):
diff -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 -r 4ebd2f3313b21ecac0d327055b452911551ec279 lib/galaxy/tools/deps/resolvers/modules.py
--- a/lib/galaxy/tools/deps/resolvers/modules.py
+++ b/lib/galaxy/tools/deps/resolvers/modules.py
@@ -12,7 +12,6 @@
from subprocess import Popen, PIPE
from ..resolvers import DependencyResolver, INDETERMINATE_DEPENDENCY, Dependency
-from galaxy.util import string_as_bool
import logging
log = logging.getLogger( __name__ )
@@ -28,9 +27,9 @@
resolver_type = "modules"
def __init__(self, dependency_manager, **kwds):
- self.versionless = string_as_bool(kwds.get('versionless', 'false'))
+ self.versionless = _string_as_bool(kwds.get('versionless', 'false'))
find_by = kwds.get('find_by', 'avail')
- prefetch = string_as_bool(kwds.get('prefetch', DEFAULT_MODULE_PREFETCH))
+ prefetch = _string_as_bool(kwds.get('prefetch', DEFAULT_MODULE_PREFETCH))
self.modulecmd = kwds.get('modulecmd', DEFAULT_MODULECMD_PATH)
if find_by == 'directory':
modulepath = kwds.get('modulepath', self.__default_modulespath())
@@ -150,4 +149,8 @@
command = 'eval `%s sh load %s`' % (self.module_dependency_resolver.modulecmd, module_to_load)
return command
+
+def _string_as_bool( value ):
+ return str( value ).lower() == "true"
+
__all__ = [ModuleDependencyResolver]
diff -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 -r 4ebd2f3313b21ecac0d327055b452911551ec279 lib/galaxy/util/submodules.py
--- a/lib/galaxy/util/submodules.py
+++ b/lib/galaxy/util/submodules.py
@@ -1,30 +1,31 @@
from os import listdir
+
import logging
-log = logging.getLogger( __name__ )
+log = logging.getLogger(__name__)
-def submodules( module ):
- unsorted_submodule_names = __submodule_names( module )
- submodule_names = sorted( unsorted_submodule_names, reverse=True )
+def submodules(module):
+ unsorted_submodule_names = __submodule_names(module)
+ submodule_names = sorted(unsorted_submodule_names, reverse=True)
submodules = []
for submodule_name in submodule_names:
- full_submodule = "%s.%s" % ( module.__name__, submodule_name )
+ full_submodule = "%s.%s" % (module.__name__, submodule_name)
try:
- __import__( full_submodule )
- submodule = getattr( module, submodule_name )
- submodules.append( submodule )
+ __import__(full_submodule)
+ submodule = getattr(module, submodule_name)
+ submodules.append(submodule)
except BaseException, exception:
- exception_str = str( exception )
- message = "%s dynamic module could not be loaded: %s" % ( full_submodule, exception_str )
- log.debug( message )
+ exception_str = str(exception)
+ message = "%s dynamic module could not be loaded: %s" % (full_submodule, exception_str)
+ log.debug(message)
return submodules
-def __submodule_names( module ):
- module_dir = module.__path__[ 0 ]
+def __submodule_names(module):
+ module_dir = module.__path__[0]
names = []
- for fname in listdir( module_dir ):
- if not( fname.startswith( "_" ) ) and fname.endswith( ".py" ):
- submodule_name = fname[ :-len( ".py" ) ]
- names.append( submodule_name )
+ for fname in listdir(module_dir):
+ if not(fname.startswith("_")) and fname.endswith(".py"):
+ submodule_name = fname[:-len(".py")]
+ names.append(submodule_name)
return names
https://bitbucket.org/galaxy/galaxy-central/commits/34694461de2c/
Changeset: 34694461de2c
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: Refactor command_factory:build_command to reduce parameter count.
Grouping all parameters to tweak the building of this command line for remote servers (read LWR) - since I have at least one more to add.
Affected #: 3 files
diff -r 4ebd2f3313b21ecac0d327055b452911551ec279 -r 34694461de2c2863066aa24c7c0cee65837f29e5 lib/galaxy/jobs/command_factory.py
--- a/lib/galaxy/jobs/command_factory.py
+++ b/lib/galaxy/jobs/command_factory.py
@@ -2,7 +2,7 @@
from os.path import abspath
-def build_command( job, job_wrapper, include_metadata=False, include_work_dir_outputs=True, metadata_kwds={}, job_working_directory=None ):
+def build_command( job, job_wrapper, include_metadata=False, include_work_dir_outputs=True, remote_command_params={} ):
"""
Compose the sequence of commands necessary to execute a job. This will
currently include:
@@ -43,7 +43,10 @@
# Append commands to copy job outputs based on from_work_dir attribute.
if include_work_dir_outputs:
- work_dir_outputs = job.get_work_dir_outputs( job_wrapper, job_working_directory=job_working_directory )
+ work_dir_outputs_kwds = {}
+ if 'working_directory' in remote_command_params:
+ work_dir_outputs_kwds['job_working_directory'] = remote_command_params['working_directory']
+ work_dir_outputs = job.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
if work_dir_outputs:
if not captured_return_code:
commands += capture_return_code_command
@@ -55,6 +58,7 @@
# Append metadata setting commands, we don't want to overwrite metadata
# that was copied over in init_meta(), as per established behavior
if include_metadata and job_wrapper.requires_setting_metadata:
+ metadata_kwds = remote_command_params.get('metadata_kwds', {})
exec_dir = metadata_kwds.get( 'exec_dir', abspath( getcwd() ) )
tmp_dir = metadata_kwds.get( 'tmp_dir', job_wrapper.working_directory )
dataset_files_path = metadata_kwds.get( 'dataset_files_path', job.app.model.Dataset.file_path )
diff -r 4ebd2f3313b21ecac0d327055b452911551ec279 -r 34694461de2c2863066aa24c7c0cee65837f29e5 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -107,13 +107,16 @@
remote_metadata = LwrJobRunner.__remote_metadata( client )
remote_work_dir_copy = LwrJobRunner.__remote_work_dir_copy( client )
metadata_kwds = self.__build_metadata_configuration(client, job_wrapper, remote_metadata, remote_job_config)
+ remote_command_params = dict(
+ working_directory=remote_job_config['working_directory'],
+ metadata_kwds=metadata_kwds,
+ )
command_line = build_command(
self,
job_wrapper=job_wrapper,
include_metadata=remote_metadata,
include_work_dir_outputs=remote_work_dir_copy,
- metadata_kwds=metadata_kwds,
- job_working_directory=remote_job_config['working_directory']
+ remote_command_params=remote_command_params,
)
except Exception:
job_wrapper.fail( "failure preparing job", exception=True )
diff -r 4ebd2f3313b21ecac0d327055b452911551ec279 -r 34694461de2c2863066aa24c7c0cee65837f29e5 test/unit/test_command_factory.py
--- a/test/unit/test_command_factory.py
+++ b/test/unit/test_command_factory.py
@@ -81,7 +81,7 @@
self.include_work_dir_outputs = False
self.job_wrapper.metadata_line = TEST_METADATA_LINE
if kwds:
- self.__command(metadata_kwds=kwds)
+ self.__command(remote_command_params=dict(metadata_kwds=kwds))
else:
self.__command()
return self.job_wrapper.configured_external_metadata_kwds
https://bitbucket.org/galaxy/galaxy-central/commits/e94ac0f171cb/
Changeset: e94ac0f171cb
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: Allow new dependency_resolution destination for LWR runner.
It can be 'none', 'local', or 'remote'. At this point this allows one to disable command dependency injection if set to 'none' or 'remote'. Actually implementing logic for 'remote' resolution will follow.
In subsequent changes - 'remote' will make backward-imcompatiable API calls to the LWR - this is why 'none' is also provided as an option - it will be backward compatiable way to disable dependency resolution for an LWR destination.
Affected #: 3 files
diff -r 34694461de2c2863066aa24c7c0cee65837f29e5 -r e94ac0f171cb91325747434d0dd62ea6e9ea9187 lib/galaxy/jobs/command_factory.py
--- a/lib/galaxy/jobs/command_factory.py
+++ b/lib/galaxy/jobs/command_factory.py
@@ -31,8 +31,9 @@
if hasattr(job_wrapper, 'prepare_input_files_cmds') and job_wrapper.prepare_input_files_cmds is not None:
commands = "; ".join( job_wrapper.prepare_input_files_cmds + [ commands ] )
+ local_dependency_resolution = "dependency_resolution" not in remote_command_params or (remote_command_params["dependency_resolution"] == "local")
# Prepend dependency injection
- if job_wrapper.dependency_shell_commands:
+ if job_wrapper.dependency_shell_commands and local_dependency_resolution:
commands = "; ".join( job_wrapper.dependency_shell_commands + [ commands ] )
# Coping work dir outputs or setting metadata will mask return code of
diff -r 34694461de2c2863066aa24c7c0cee65837f29e5 -r e94ac0f171cb91325747434d0dd62ea6e9ea9187 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -106,10 +106,12 @@
remote_job_config = client.setup(tool.id, tool.version)
remote_metadata = LwrJobRunner.__remote_metadata( client )
remote_work_dir_copy = LwrJobRunner.__remote_work_dir_copy( client )
+ dependency_resolution = LwrJobRunner.__dependency_resolution( client )
metadata_kwds = self.__build_metadata_configuration(client, job_wrapper, remote_metadata, remote_job_config)
remote_command_params = dict(
working_directory=remote_job_config['working_directory'],
metadata_kwds=metadata_kwds,
+ dependency_resolution=dependency_resolution,
)
command_line = build_command(
self,
@@ -272,6 +274,13 @@
self.monitor_queue.put( job_state )
@staticmethod
+ def __dependency_resolution( lwr_client ):
+ dependency_resolution = lwr_client.destination_params.get( "dependency_resolution", "local" )
+ if dependency_resolution not in ["none", "local", "remote"]:
+ raise Exception("Unknown dependency_resolution value encountered %s" % dependency_resolution)
+ return dependency_resolution
+
+ @staticmethod
def __remote_metadata( lwr_client ):
remote_metadata = string_as_bool_or_none( lwr_client.destination_params.get( "remote_metadata", False ) )
return remote_metadata
diff -r 34694461de2c2863066aa24c7c0cee65837f29e5 -r e94ac0f171cb91325747434d0dd62ea6e9ea9187 test/unit/test_command_factory.py
--- a/test/unit/test_command_factory.py
+++ b/test/unit/test_command_factory.py
@@ -27,6 +27,19 @@
self.job_wrapper.dependency_shell_commands = dep_commands
self.__assert_command_is( "%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE) )
+ def test_remote_dependency_resolution(self):
+ self.include_work_dir_outputs = False
+ dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
+ self.job_wrapper.dependency_shell_commands = dep_commands
+ self.__assert_command_is(MOCK_COMMAND_LINE, remote_command_params=dict(dependency_resolution="remote"))
+
+ def test_explicit_local_dependency_resolution(self):
+ self.include_work_dir_outputs = False
+ dep_commands = [". /opt/galaxy/tools/bowtie/default/env.sh"]
+ self.job_wrapper.dependency_shell_commands = dep_commands
+ self.__assert_command_is("%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE),
+ remote_command_params=dict(dependency_resolution="local"))
+
def test_set_metadata_skipped_if_unneeded(self):
self.include_metadata = True
self.include_work_dir_outputs = False
https://bitbucket.org/galaxy/galaxy-central/commits/dc4e5f648da2/
Changeset: dc4e5f648da2
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: command_factory cleanup - fix very poorly named input parameter.
Affected #: 2 files
diff -r e94ac0f171cb91325747434d0dd62ea6e9ea9187 -r dc4e5f648da215f3a9da27fe5155d4dd2ebfbff0 lib/galaxy/jobs/command_factory.py
--- a/lib/galaxy/jobs/command_factory.py
+++ b/lib/galaxy/jobs/command_factory.py
@@ -2,7 +2,7 @@
from os.path import abspath
-def build_command( job, job_wrapper, include_metadata=False, include_work_dir_outputs=True, remote_command_params={} ):
+def build_command( runner, job_wrapper, include_metadata=False, include_work_dir_outputs=True, remote_command_params={} ):
"""
Compose the sequence of commands necessary to execute a job. This will
currently include:
@@ -47,7 +47,7 @@
work_dir_outputs_kwds = {}
if 'working_directory' in remote_command_params:
work_dir_outputs_kwds['job_working_directory'] = remote_command_params['working_directory']
- work_dir_outputs = job.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
+ work_dir_outputs = runner.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
if work_dir_outputs:
if not captured_return_code:
commands += capture_return_code_command
@@ -62,7 +62,7 @@
metadata_kwds = remote_command_params.get('metadata_kwds', {})
exec_dir = metadata_kwds.get( 'exec_dir', abspath( getcwd() ) )
tmp_dir = metadata_kwds.get( 'tmp_dir', job_wrapper.working_directory )
- dataset_files_path = metadata_kwds.get( 'dataset_files_path', job.app.model.Dataset.file_path )
+ dataset_files_path = metadata_kwds.get( 'dataset_files_path', runner.app.model.Dataset.file_path )
output_fnames = metadata_kwds.get( 'output_fnames', job_wrapper.get_output_fnames() )
config_root = metadata_kwds.get( 'config_root', None )
config_file = metadata_kwds.get( 'config_file', None )
diff -r e94ac0f171cb91325747434d0dd62ea6e9ea9187 -r dc4e5f648da215f3a9da27fe5155d4dd2ebfbff0 test/unit/test_command_factory.py
--- a/test/unit/test_command_factory.py
+++ b/test/unit/test_command_factory.py
@@ -13,7 +13,7 @@
def setUp(self):
self.job_wrapper = MockJobWrapper()
- self.job = Bunch(app=Bunch(model=Bunch(Dataset=Bunch(file_path=TEST_FILES_PATH))))
+ self.runner = Bunch(app=Bunch(model=Bunch(Dataset=Bunch(file_path=TEST_FILES_PATH))))
self.include_metadata = False
self.include_work_dir_outputs = True
@@ -105,7 +105,7 @@
def __command(self, **extra_kwds):
kwds = dict(
- job=self.job,
+ runner=self.runner,
job_wrapper=self.job_wrapper,
include_metadata=self.include_metadata,
include_work_dir_outputs=self.include_work_dir_outputs,
@@ -137,7 +137,3 @@
def get_output_fnames(self):
return ["output1"]
-
-
-class MockJob(object):
- app = Bunch()
https://bitbucket.org/galaxy/galaxy-central/commits/11888fd788bf/
Changeset: 11888fd788bf
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: Add more unit tests for command_factory.
In particular for for task splitting commands and copying work dir outputs.
Affected #: 1 file
diff -r dc4e5f648da215f3a9da27fe5155d4dd2ebfbff0 -r 11888fd788bf4364acef861f545c4e27af05d6a8 test/unit/test_command_factory.py
--- a/test/unit/test_command_factory.py
+++ b/test/unit/test_command_factory.py
@@ -13,7 +13,13 @@
def setUp(self):
self.job_wrapper = MockJobWrapper()
- self.runner = Bunch(app=Bunch(model=Bunch(Dataset=Bunch(file_path=TEST_FILES_PATH))))
+ self.workdir_outputs = []
+
+ def workdir_outputs(job_wrapper, **kwds):
+ assert job_wrapper == self.job_wrapper
+ return self.workdir_outputs
+
+ self.runner = Bunch(app=Bunch(model=Bunch(Dataset=Bunch(file_path=TEST_FILES_PATH))), get_work_dir_outputs=workdir_outputs)
self.include_metadata = False
self.include_work_dir_outputs = True
@@ -40,6 +46,16 @@
self.__assert_command_is("%s; %s" % (dep_commands[0], MOCK_COMMAND_LINE),
remote_command_params=dict(dependency_resolution="local"))
+ def test_task_prepare_inputs(self):
+ self.include_work_dir_outputs = False
+ self.job_wrapper.prepare_input_files_cmds = ["/opt/split1", "/opt/split2"]
+ self.__assert_command_is( "/opt/split1; /opt/split2; %s" % MOCK_COMMAND_LINE )
+
+ def test_workdir_outputs(self):
+ self.include_work_dir_outputs = True
+ self.workdir_outputs = [("foo", "bar")]
+ self.__assert_command_is( '%s; return_code=$?; if [ -f foo ] ; then cp foo bar ; fi; sh -c "exit $return_code"' % MOCK_COMMAND_LINE )
+
def test_set_metadata_skipped_if_unneeded(self):
self.include_metadata = True
self.include_work_dir_outputs = False
@@ -123,6 +139,7 @@
self.metadata_line = None
self.configured_external_metadata_kwds = None
self.working_directory = "job1"
+ self.prepare_input_files_cmds = None
def get_command_line(self):
return self.command_line
https://bitbucket.org/galaxy/galaxy-central/commits/ef3e337d1fc7/
Changeset: ef3e337d1fc7
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: command_factory cleanup - introduce abstraction for more readable command construction logic.
Affected #: 1 file
diff -r 11888fd788bf4364acef861f545c4e27af05d6a8 -r ef3e337d1fc7d4ee61bcf91e4ca50446eb087d6a lib/galaxy/jobs/command_factory.py
--- a/lib/galaxy/jobs/command_factory.py
+++ b/lib/galaxy/jobs/command_factory.py
@@ -13,34 +13,25 @@
- commands to set metadata (if include_metadata is True)
"""
- commands = job_wrapper.get_command_line()
+ commands_builder = CommandsBuilder(job_wrapper.get_command_line())
# All job runners currently handle this case which should never occur
- if not commands:
+ if not commands_builder.commands:
return None
- # Remove trailing semi-colon so we can start hacking up this command.
- # TODO: Refactor to compose a list and join with ';', would be more clean.
- commands = commands.rstrip("; ")
-
# Prepend version string
if job_wrapper.version_string_cmd:
- commands = "%s &> %s; " % ( job_wrapper.version_string_cmd, job_wrapper.get_version_string_path() ) + commands
+ version_command = "%s &> %s" % ( job_wrapper.version_string_cmd, job_wrapper.get_version_string_path() )
+ commands_builder.prepend_command(version_command)
# prepend getting input files (if defined)
if hasattr(job_wrapper, 'prepare_input_files_cmds') and job_wrapper.prepare_input_files_cmds is not None:
- commands = "; ".join( job_wrapper.prepare_input_files_cmds + [ commands ] )
+ commands_builder.prepend_commands(job_wrapper.prepare_input_files_cmds)
local_dependency_resolution = "dependency_resolution" not in remote_command_params or (remote_command_params["dependency_resolution"] == "local")
# Prepend dependency injection
if job_wrapper.dependency_shell_commands and local_dependency_resolution:
- commands = "; ".join( job_wrapper.dependency_shell_commands + [ commands ] )
-
- # Coping work dir outputs or setting metadata will mask return code of
- # tool command. If these are used capture the return code and ensure
- # the last thing that happens is an exit with return code.
- capture_return_code_command = "; return_code=$?"
- captured_return_code = False
+ commands_builder.prepend_commands(job_wrapper.dependency_shell_commands)
# Append commands to copy job outputs based on from_work_dir attribute.
if include_work_dir_outputs:
@@ -49,12 +40,9 @@
work_dir_outputs_kwds['job_working_directory'] = remote_command_params['working_directory']
work_dir_outputs = runner.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
if work_dir_outputs:
- if not captured_return_code:
- commands += capture_return_code_command
- captured_return_code = True
-
- commands += "; " + "; ".join( [ "if [ -f %s ] ; then cp %s %s ; fi" %
- ( source_file, source_file, destination ) for ( source_file, destination ) in work_dir_outputs ] )
+ commands_builder.capture_return_code()
+ commands_builder.append_commands([ "if [ -f %s ] ; then cp %s %s ; fi" %
+ ( source_file, source_file, destination ) for ( source_file, destination ) in work_dir_outputs ])
# Append metadata setting commands, we don't want to overwrite metadata
# that was copied over in init_meta(), as per established behavior
@@ -80,12 +68,44 @@
) or ''
metadata_command = metadata_command.strip()
if metadata_command:
- if not captured_return_code:
- commands += capture_return_code_command
- captured_return_code = True
- commands += "; cd %s; %s" % (exec_dir, metadata_command)
+ commands_builder.capture_return_code()
+ commands_builder.append_command("cd %s; %s" % (exec_dir, metadata_command))
- if captured_return_code:
- commands += '; sh -c "exit $return_code"'
+ return commands_builder.build()
- return commands
+
+class CommandsBuilder(object):
+
+ def __init__(self, initial_command):
+ # Remove trailing semi-colon so we can start hacking up this command.
+ # TODO: Refactor to compose a list and join with ';', would be more clean.
+ commands = initial_command.rstrip("; ")
+ self.commands = commands
+
+ # Coping work dir outputs or setting metadata will mask return code of
+ # tool command. If these are used capture the return code and ensure
+ # the last thing that happens is an exit with return code.
+ self.return_code_captured = False
+
+ def prepend_command(self, command):
+ self.commands = "%s; %s" % (command, self.commands)
+ return self
+
+ def prepend_commands(self, commands):
+ return self.prepend_command("; ".join(commands))
+
+ def append_command(self, command):
+ self.commands = "%s; %s" % (self.commands, command)
+
+ def append_commands(self, commands):
+ self.append_command("; ".join(commands))
+
+ def capture_return_code(self):
+ if not self.return_code_captured:
+ self.return_code_captured = True
+ self.append_command("return_code=$?")
+
+ def build(self):
+ if self.return_code_captured:
+ self.append_command('sh -c "exit $return_code"')
+ return self.commands
https://bitbucket.org/galaxy/galaxy-central/commits/188df80a411c/
Changeset: 188df80a411c
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: command_factory cleanup - split big build_command method into smaller well-named pieces.
Affected #: 1 file
diff -r ef3e337d1fc7d4ee61bcf91e4ca50446eb087d6a -r 188df80a411c01272d03e7143d2afa343d575f81 lib/galaxy/jobs/command_factory.py
--- a/lib/galaxy/jobs/command_factory.py
+++ b/lib/galaxy/jobs/command_factory.py
@@ -19,59 +19,77 @@
if not commands_builder.commands:
return None
+ __handle_version_command(commands_builder, job_wrapper)
+ __handle_task_splitting(commands_builder, job_wrapper)
+ __handle_dependency_resolution(commands_builder, job_wrapper, remote_command_params)
+
+ if include_work_dir_outputs:
+ __handle_work_dir_outputs(commands_builder, job_wrapper, runner, remote_command_params)
+
+ if include_metadata and job_wrapper.requires_setting_metadata:
+ __handle_metadata(commands_builder, job_wrapper, runner, remote_command_params)
+
+ return commands_builder.build()
+
+
+def __handle_version_command(commands_builder, job_wrapper):
# Prepend version string
if job_wrapper.version_string_cmd:
version_command = "%s &> %s" % ( job_wrapper.version_string_cmd, job_wrapper.get_version_string_path() )
commands_builder.prepend_command(version_command)
+
+def __handle_task_splitting(commands_builder, job_wrapper):
# prepend getting input files (if defined)
- if hasattr(job_wrapper, 'prepare_input_files_cmds') and job_wrapper.prepare_input_files_cmds is not None:
+ if getattr(job_wrapper, 'prepare_input_files_cmds', None):
commands_builder.prepend_commands(job_wrapper.prepare_input_files_cmds)
+
+def __handle_dependency_resolution(commands_builder, job_wrapper, remote_command_params):
local_dependency_resolution = "dependency_resolution" not in remote_command_params or (remote_command_params["dependency_resolution"] == "local")
# Prepend dependency injection
if job_wrapper.dependency_shell_commands and local_dependency_resolution:
commands_builder.prepend_commands(job_wrapper.dependency_shell_commands)
+
+def __handle_work_dir_outputs(commands_builder, job_wrapper, runner, remote_command_params):
# Append commands to copy job outputs based on from_work_dir attribute.
- if include_work_dir_outputs:
- work_dir_outputs_kwds = {}
- if 'working_directory' in remote_command_params:
- work_dir_outputs_kwds['job_working_directory'] = remote_command_params['working_directory']
- work_dir_outputs = runner.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
- if work_dir_outputs:
- commands_builder.capture_return_code()
- commands_builder.append_commands([ "if [ -f %s ] ; then cp %s %s ; fi" %
- ( source_file, source_file, destination ) for ( source_file, destination ) in work_dir_outputs ])
+ work_dir_outputs_kwds = {}
+ if 'working_directory' in remote_command_params:
+ work_dir_outputs_kwds['job_working_directory'] = remote_command_params['working_directory']
+ work_dir_outputs = runner.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
+ if work_dir_outputs:
+ commands_builder.capture_return_code()
+ commands_builder.append_commands([ "if [ -f %s ] ; then cp %s %s ; fi" %
+ ( source_file, source_file, destination ) for ( source_file, destination ) in work_dir_outputs ])
+
+def __handle_metadata(commands_builder, job_wrapper, runner, remote_command_params):
# Append metadata setting commands, we don't want to overwrite metadata
# that was copied over in init_meta(), as per established behavior
- if include_metadata and job_wrapper.requires_setting_metadata:
- metadata_kwds = remote_command_params.get('metadata_kwds', {})
- exec_dir = metadata_kwds.get( 'exec_dir', abspath( getcwd() ) )
- tmp_dir = metadata_kwds.get( 'tmp_dir', job_wrapper.working_directory )
- dataset_files_path = metadata_kwds.get( 'dataset_files_path', runner.app.model.Dataset.file_path )
- output_fnames = metadata_kwds.get( 'output_fnames', job_wrapper.get_output_fnames() )
- config_root = metadata_kwds.get( 'config_root', None )
- config_file = metadata_kwds.get( 'config_file', None )
- datatypes_config = metadata_kwds.get( 'datatypes_config', None )
- metadata_command = job_wrapper.setup_external_metadata(
- exec_dir=exec_dir,
- tmp_dir=tmp_dir,
- dataset_files_path=dataset_files_path,
- output_fnames=output_fnames,
- set_extension=False,
- config_root=config_root,
- config_file=config_file,
- datatypes_config=datatypes_config,
- kwds={ 'overwrite' : False }
- ) or ''
- metadata_command = metadata_command.strip()
- if metadata_command:
- commands_builder.capture_return_code()
- commands_builder.append_command("cd %s; %s" % (exec_dir, metadata_command))
-
- return commands_builder.build()
+ metadata_kwds = remote_command_params.get('metadata_kwds', {})
+ exec_dir = metadata_kwds.get( 'exec_dir', abspath( getcwd() ) )
+ tmp_dir = metadata_kwds.get( 'tmp_dir', job_wrapper.working_directory )
+ dataset_files_path = metadata_kwds.get( 'dataset_files_path', runner.app.model.Dataset.file_path )
+ output_fnames = metadata_kwds.get( 'output_fnames', job_wrapper.get_output_fnames() )
+ config_root = metadata_kwds.get( 'config_root', None )
+ config_file = metadata_kwds.get( 'config_file', None )
+ datatypes_config = metadata_kwds.get( 'datatypes_config', None )
+ metadata_command = job_wrapper.setup_external_metadata(
+ exec_dir=exec_dir,
+ tmp_dir=tmp_dir,
+ dataset_files_path=dataset_files_path,
+ output_fnames=output_fnames,
+ set_extension=False,
+ config_root=config_root,
+ config_file=config_file,
+ datatypes_config=datatypes_config,
+ kwds={ 'overwrite' : False }
+ ) or ''
+ metadata_command = metadata_command.strip()
+ if metadata_command:
+ commands_builder.capture_return_code()
+ commands_builder.append_command("cd %s; %s" % (exec_dir, metadata_command))
class CommandsBuilder(object):
https://bitbucket.org/galaxy/galaxy-central/commits/b513c61601ef/
Changeset: b513c61601ef
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: command_factory cleanup - a couple more small tweaks for readability.
Affected #: 1 file
diff -r 188df80a411c01272d03e7143d2afa343d575f81 -r b513c61601ef6bec6713320cd4e23fc4e020359e lib/galaxy/jobs/command_factory.py
--- a/lib/galaxy/jobs/command_factory.py
+++ b/lib/galaxy/jobs/command_factory.py
@@ -1,6 +1,9 @@
from os import getcwd
from os.path import abspath
+CAPTURE_RETURN_CODE = "return_code=$?"
+YIELD_CAPTURED_CODE = 'sh -c "exit $return_code"'
+
def build_command( runner, job_wrapper, include_metadata=False, include_work_dir_outputs=True, remote_command_params={} ):
"""
@@ -46,7 +49,8 @@
def __handle_dependency_resolution(commands_builder, job_wrapper, remote_command_params):
- local_dependency_resolution = "dependency_resolution" not in remote_command_params or (remote_command_params["dependency_resolution"] == "local")
+ local_dependency_resolution = remote_command_params.get("dependency_resolution", "local") == "local"
+
# Prepend dependency injection
if job_wrapper.dependency_shell_commands and local_dependency_resolution:
commands_builder.prepend_commands(job_wrapper.dependency_shell_commands)
@@ -60,8 +64,8 @@
work_dir_outputs = runner.get_work_dir_outputs( job_wrapper, **work_dir_outputs_kwds )
if work_dir_outputs:
commands_builder.capture_return_code()
- commands_builder.append_commands([ "if [ -f %s ] ; then cp %s %s ; fi" %
- ( source_file, source_file, destination ) for ( source_file, destination ) in work_dir_outputs ])
+ copy_commands = map(__copy_if_exists_command, work_dir_outputs)
+ commands_builder.append_commands(copy_commands)
def __handle_metadata(commands_builder, job_wrapper, runner, remote_command_params):
@@ -92,6 +96,11 @@
commands_builder.append_command("cd %s; %s" % (exec_dir, metadata_command))
+def __copy_if_exists_command(work_dir_output):
+ source_file, destination = work_dir_output
+ return "if [ -f %s ] ; then cp %s %s ; fi" % ( source_file, source_file, destination )
+
+
class CommandsBuilder(object):
def __init__(self, initial_command):
@@ -121,9 +130,11 @@
def capture_return_code(self):
if not self.return_code_captured:
self.return_code_captured = True
- self.append_command("return_code=$?")
+ self.append_command(CAPTURE_RETURN_CODE)
def build(self):
if self.return_code_captured:
- self.append_command('sh -c "exit $return_code"')
+ self.append_command(YIELD_CAPTURED_CODE)
return self.commands
+
+__all__ = [build_command]
https://bitbucket.org/galaxy/galaxy-central/commits/3a7dee0e35b7/
Changeset: 3a7dee0e35b7
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: Implement 'remote' dependency_resolution for LWR.
Set LWR destination parameter 'dependency_resolution' to remote. This will disable all dependency resolution on Galaxy side when building up command line and instead pass the tool's requirements along to the LWR server for resolution on that end. This requires a very up-to-date LWR server.
I think right now 'galaxy_packages' and 'modules' resolution would work but not 'tool_shed_package' resolution - I think more repository information related to the tool needs to be passed along to the LWR to enable this.
Updates the LWR client code through LWR changeset 4380e65 - mostly bringing in changes to enable this but also includes other small refactorings to stager.py.
Affected #: 4 files
diff -r b513c61601ef6bec6713320cd4e23fc4e020359e -r 3a7dee0e35b7b83617c8df8b943e74199941ff55 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -68,6 +68,9 @@
return
try:
+ dependency_resolution = LwrJobRunner.__dependency_resolution( client )
+ remote_dependency_resolution = dependency_resolution == "remote"
+ requirements = job_wrapper.tool.requirements if remote_dependency_resolution else []
client_job_description = ClientJobDescription(
command_line=command_line,
output_files=self.get_output_files(job_wrapper),
@@ -75,6 +78,7 @@
working_directory=job_wrapper.working_directory,
tool=job_wrapper.tool,
config_files=job_wrapper.extra_filenames,
+ requirements=requirements,
)
job_id = lwr_submit_job(client, client_job_description, remote_job_config)
log.info("lwr job submitted with job_id %s" % job_id)
diff -r b513c61601ef6bec6713320cd4e23fc4e020359e -r 3a7dee0e35b7b83617c8df8b943e74199941ff55 lib/galaxy/jobs/runners/lwr_client/client.py
--- a/lib/galaxy/jobs/runners/lwr_client/client.py
+++ b/lib/galaxy/jobs/runners/lwr_client/client.py
@@ -197,7 +197,7 @@
}
self._raw_execute("download_output", output_params, output_path=output_path)
- def launch(self, command_line):
+ def launch(self, command_line, requirements=[]):
"""
Run or queue up the execution of the supplied
`command_line` on the remote server.
@@ -211,6 +211,8 @@
submit_params = self._submit_params
if submit_params:
launch_params['params'] = dumps(submit_params)
+ if requirements:
+ launch_params['requirements'] = dumps([requirement.to_dict() for requirement in requirements])
return self._raw_execute("launch", launch_params)
def kill(self):
diff -r b513c61601ef6bec6713320cd4e23fc4e020359e -r 3a7dee0e35b7b83617c8df8b943e74199941ff55 lib/galaxy/jobs/runners/lwr_client/stager.py
--- a/lib/galaxy/jobs/runners/lwr_client/stager.py
+++ b/lib/galaxy/jobs/runners/lwr_client/stager.py
@@ -3,6 +3,7 @@
from re import findall
from re import compile
from io import open
+from contextlib import contextmanager
from .action_mapper import FileActionMapper
@@ -297,41 +298,58 @@
def finish_job(client, cleanup_job, job_completed_normally, working_directory, work_dir_outputs, output_files, working_directory_contents=[]):
"""
"""
+ download_failure_exceptions = []
+ if job_completed_normally:
+ download_failure_exceptions = __download_results(client, working_directory, work_dir_outputs, output_files, working_directory_contents)
+ return __clean(download_failure_exceptions, cleanup_job, client)
+
+
+def __download_results(client, working_directory, work_dir_outputs, output_files, working_directory_contents):
action_mapper = FileActionMapper(client)
- download_failure_exceptions = []
downloaded_working_directory_files = []
- if job_completed_normally:
- # Fetch explicit working directory outputs.
- for source_file, output_file in work_dir_outputs:
- name = basename(source_file)
- try:
- action = action_mapper.action(output_file, 'output')
- client.fetch_work_dir_output(name, working_directory, output_file, action[0])
- downloaded_working_directory_files.append(name)
- except Exception as e:
- download_failure_exceptions.append(e)
- # Remove from full output_files list so don't try to download directly.
- output_files.remove(output_file)
+ exception_tracker = DownloadExceptionTracker()
- # Fetch output files.
- for output_file in output_files:
- try:
- action = action_mapper.action(output_file, 'output')
- client.fetch_output(output_file, working_directory=working_directory, action=action[0])
- except Exception as e:
- download_failure_exceptions.append(e)
+ # Fetch explicit working directory outputs.
+ for source_file, output_file in work_dir_outputs:
+ name = basename(source_file)
+ with exception_tracker():
+ action = action_mapper.action(output_file, 'output')
+ client.fetch_work_dir_output(name, working_directory, output_file, action[0])
+ downloaded_working_directory_files.append(name)
+ # Remove from full output_files list so don't try to download directly.
+ output_files.remove(output_file)
- # Fetch remaining working directory outputs of interest.
- for name in working_directory_contents:
- if name in downloaded_working_directory_files:
- continue
- if COPY_FROM_WORKING_DIRECTORY_PATTERN.match(name):
+ # Fetch output files.
+ for output_file in output_files:
+ with exception_tracker():
+ action = action_mapper.action(output_file, 'output')
+ client.fetch_output(output_file, working_directory=working_directory, action=action[0])
+
+ # Fetch remaining working directory outputs of interest.
+ for name in working_directory_contents:
+ if name in downloaded_working_directory_files:
+ continue
+ if COPY_FROM_WORKING_DIRECTORY_PATTERN.match(name):
+ with exception_tracker():
output_file = join(working_directory, name)
action = action_mapper.action(output_file, 'output')
client.fetch_work_dir_output(name, working_directory, output_file, action=action[0])
downloaded_working_directory_files.append(name)
- return __clean(download_failure_exceptions, cleanup_job, client)
+ return exception_tracker.download_failure_exceptions
+
+
+class DownloadExceptionTracker(object):
+
+ def __init__(self):
+ self.download_failure_exceptions = []
+
+ @contextmanager
+ def __call__(self):
+ try:
+ yield
+ except Exception as e:
+ self.download_failure_exceptions.append(e)
def __clean(download_failure_exceptions, cleanup_job, client):
@@ -350,7 +368,7 @@
file_stager = FileStager(client, client_job_description, job_config)
rebuilt_command_line = file_stager.get_rewritten_command_line()
job_id = file_stager.job_id
- client.launch(rebuilt_command_line)
+ client.launch(rebuilt_command_line, requirements=client_job_description.requirements)
return job_id
@@ -383,15 +401,17 @@
Directory containing tool to execute (if a wrapper is used, it will be transferred to remote server).
working_directory : str
Local path created by Galaxy for running this job.
+ requirements : list
+ List of requirements for tool execution.
"""
- def __init__(self, tool, command_line, config_files, input_files, output_files, working_directory):
+ def __init__(self, tool, command_line, config_files, input_files, output_files, working_directory, requirements):
self.tool = tool
self.command_line = command_line
self.config_files = config_files
self.input_files = input_files
self.output_files = output_files
self.working_directory = working_directory
-
+ self.requirements = requirements
__all__ = [submit_job, ClientJobDescription, finish_job]
diff -r b513c61601ef6bec6713320cd4e23fc4e020359e -r 3a7dee0e35b7b83617c8df8b943e74199941ff55 lib/galaxy/tools/deps/requirements.py
--- a/lib/galaxy/tools/deps/requirements.py
+++ b/lib/galaxy/tools/deps/requirements.py
@@ -15,6 +15,16 @@
self.type = type
self.version = version
+ def to_dict( self ):
+ return dict(name=self.name, type=self.type, version=self.version)
+
+ @staticmethod
+ def from_dict( dict ):
+ version = dict.get( "version", None )
+ name = dict.get("name", None)
+ type = dict.get("type", None)
+ return ToolRequirement( name=name, type=type, version=version )
+
def parse_requirements_from_xml( xml_root ):
"""
https://bitbucket.org/galaxy/galaxy-central/commits/a831eb375268/
Changeset: a831eb375268
User: jmchilton
Date: 2013-12-11 17:26:15
Summary: Fill out job_conf.xml example with LWR options added over recent months.
Affected #: 1 file
diff -r 3a7dee0e35b7b83617c8df8b943e74199941ff55 -r a831eb375268fcf80479f7bf325ec7d8a757582c job_conf.xml.sample_advanced
--- a/job_conf.xml.sample_advanced
+++ b/job_conf.xml.sample_advanced
@@ -52,8 +52,37 @@
<param id="private_token">123456789changeme</param><!-- Uncomment the following statement to disable file staging (e.g.
if there is a shared file system between Galaxy and the LWR
- server). -->
+ server). Alternatively action can be set to 'copy' - to replace
+ http transfers with file system copies. --><!-- <param id="default_file_action">none</param> -->
+ <!-- The above option is just the default, the transfer behavior
+ none|copy|http can be configured on a per path basis via the
+ following file. See lib/galaxy/jobs/runners/lwr_client/action_mapper.py
+ for examples of how to configure this file. This is very beta
+ and nature of file will likely change.
+ -->
+ <!-- <param id="file_action_config">file_actions.json</param> -->
+ <!-- Uncomment following option to disable Galaxy tool dependency
+ resolution and utilize remote LWR's configuraiton of tool
+ dependency resolution instead (same options as Galaxy for
+ dependency resolution are available in LWR).
+ -->
+ <!-- <param id="dependency_resolution">remote</params> -->
+ <!-- Uncomment following option to enable setting metadata on remote
+ LWR server. The 'use_remote_datatypes' option is available for
+ determining whether to use remotely configured datatypes or local
+ ones (both alternatives are a little brittle). -->
+ <!-- <param id="remote_metadata">true</param> -->
+ <!-- <param id="use_remote_datatypes">false</param> -->
+ <!-- If remote LWR server is configured to run jobs as the real user,
+ uncomment the following line to pass the current Galaxy user
+ along. -->
+ <!-- <param id="submit_user">$__user_name__</param> -->
+ <!-- Various other submission parameters can be passed along to the LWR
+ whose use will depend on the remote LWR's configured job manager.
+ For instance:
+ -->
+ <!-- <param id="submit_native_specification">-P bignodes -R y -pe threads 8</param> --></destination><destination id="ssh_torque" runner="cli"><param id="shell_plugin">SecureShell</param>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Add a redirect for Data Source tools, with the goal of subverting mix-mode content blocking in browsers, i.e. accessing http data source from an https Galaxy. Tested as working on Safari 7.0 and FireFox 26. Subverting did not work on Chrome 31.
by commits-noreply@bitbucket.org 11 Dec '13
by commits-noreply@bitbucket.org 11 Dec '13
11 Dec '13
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/98694eecdf76/
Changeset: 98694eecdf76
User: dan
Date: 2013-12-11 16:58:48
Summary: Add a redirect for Data Source tools, with the goal of subverting mix-mode content blocking in browsers, i.e. accessing http data source from an https Galaxy. Tested as working on Safari 7.0 and FireFox 26. Subverting did not work on Chrome 31.
Affected #: 2 files
diff -r 35ae5ce8be84dcccadaf58c9b569fb9cf9daccbf -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -3003,10 +3003,10 @@
# Add link details.
if link_details:
# Add details for creating a hyperlink to the tool.
- if not self.tool_type.startswith( 'data_source' ):
- link = url_for( '/tool_runner', tool_id=self.id )
+ if not isinstance( self, DataSourceTool ):
+ link = url_for( controller='tool_runner', tool_id=self.id )
else:
- link = url_for( self.action, **self.get_static_param_values( trans ) )
+ link = url_for( controller='tool_runner', action='data_source_redirect', tool_id=self.id )
# Basic information
tool_dict.update( { 'link': link,
diff -r 35ae5ce8be84dcccadaf58c9b569fb9cf9daccbf -r 98694eecdf76e7d69c77a0743d2b65fcb1ae3c12 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -6,6 +6,7 @@
import galaxy.util
from galaxy import web
from galaxy.tools import DefaultToolState
+from galaxy.tools import DataSourceTool
from galaxy.tools.actions import upload_common
from galaxy.tools.parameters import params_to_incoming
from galaxy.tools.parameters import visit_input_values
@@ -233,6 +234,35 @@
**vars )
@web.expose
+ def data_source_redirect( self, trans, tool_id=None ):
+ """
+ Redirects a user accessing a Data Source tool to its target action link.
+ This method will subvert mix-mode content blocking in several browsers when
+ accessing non-https data_source tools from an https galaxy server.
+
+ Tested as working on Safari 7.0 and FireFox 26
+ Subverting did not work on Chrome 31
+ """
+ if tool_id is None:
+ return trans.response.send_redirect( url_for( controller="root", action="welcome" ) )
+ tool_version_select_field, tools, tool = self.__get_tool_components( tool_id,
+ tool_version=None,
+ get_loaded_tools_by_lineage=False,
+ set_selected=False )
+ # No tool matching the tool id, display an error (shouldn't happen)
+ if not tool:
+ log.error( "data_source_redirect called with tool id '%s' but no such tool exists", tool_id )
+ trans.log_event( "Tool id '%s' does not exist" % tool_id )
+ trans.response.status = 404
+ return "Tool '%s' does not exist, kwd=%s " % ( tool_id, kwd )
+
+ if isinstance( tool, DataSourceTool ):
+ link = url_for( tool.action, **tool.get_static_param_values( trans ) )
+ else:
+ link = url_for( controller='tool_runner', tool_id=tool.id )
+ return trans.response.send_redirect( link )
+
+ @web.expose
def redirect( self, trans, redirect_url=None, **kwd ):
if not redirect_url:
return trans.show_error_message( "Required URL for redirection missing" )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1b78bcbb1bc2/
Changeset: 1b78bcbb1bc2
User: jmchilton
Date: 2013-12-11 16:55:54
Summary: Add some higher-level methods to mapping unit test.
Affected #: 1 file
diff -r df88d6121d48b0b193d34445ce49916adf17a2d2 -r 1b78bcbb1bc2bc0f39149726855418ccc890a3ff test/unit/test_galaxy_mapping.py
--- a/test/unit/test_galaxy_mapping.py
+++ b/test/unit/test_galaxy_mapping.py
@@ -3,10 +3,10 @@
class MappingTests( unittest.TestCase ):
+
def test_basic( self ):
- # Start the database and connect the mapping
- model = mapping.init( "/tmp", "sqlite:///:memory:", create_tables=True )
- assert model.engine is not None
+ model = self.model
+
# Make some changes and commit them
u = model.User( email="james(a)foo.bar.baz", password="password" )
# gs = model.GalaxySession()
@@ -14,15 +14,14 @@
#h1.queries.append( model.Query( "h1->q1" ) )
#h1.queries.append( model.Query( "h1->q2" ) )
h2 = model.History( name=( "H" * 1024 ) )
- model.session.add_all( ( u, h1, h2 ) )
+ self.persist( u, h1, h2 )
#q1 = model.Query( "h2->q1" )
metadata = dict( chromCol=1, startCol=2, endCol=3 )
d1 = model.HistoryDatasetAssociation( extension="interval", metadata=metadata, history=h2, create_dataset=True, sa_session=model.session )
#h2.queries.append( q1 )
#h2.queries.append( model.Query( "h2->q2" ) )
- model.session.add( ( d1 ) )
- model.session.flush()
- model.session.expunge_all()
+ self.persist( d1 )
+
# Check
users = model.session.query( model.User ).all()
assert len( users ) == 1
@@ -41,13 +40,33 @@
#assert hists[1].datasets[0].file_name == os.path.join( "/tmp", *directory_hash_id( id ) ) + ( "/dataset_%d.dat" % id )
# Do an update and check
hists[1].name = "History 2b"
- model.session.flush()
- model.session.expunge_all()
+ self.expunge()
hists = model.session.query( model.History ).all()
assert hists[0].name == "History 1"
assert hists[1].name == "History 2b"
# gvk TODO need to ad test for GalaxySessions, but not yet sure what they should look like.
+ @classmethod
+ def setUpClass(cls):
+ # Start the database and connect the mapping
+ cls.model = mapping.init( "/tmp", "sqlite:///:memory:", create_tables=True )
+ assert cls.model.engine is not None
+
+ @classmethod
+ def query( cls, type ):
+ return cls.model.session.query( type )
+
+ @classmethod
+ def persist(cls, *args):
+ for arg in args:
+ cls.model.session.add( arg )
+ cls.expunge()
+
+ @classmethod
+ def expunge(cls):
+ cls.model.session.flush()
+ cls.model.session.expunge_all()
+
def get_suite():
suite = unittest.TestSuite()
https://bitbucket.org/galaxy/galaxy-central/commits/35ae5ce8be84/
Changeset: 35ae5ce8be84
User: jmchilton
Date: 2013-12-11 16:55:54
Summary: Higher-level abstractions for defining annotation, tag, and rating mappings...
... as well unit tests.
Affected #: 2 files
diff -r 1b78bcbb1bc2bc0f39149726855418ccc890a3ff -r 35ae5ce8be84dcccadaf58c9b569fb9cf9daccbf lib/galaxy/model/mapping.py
--- a/lib/galaxy/model/mapping.py
+++ b/lib/galaxy/model/mapping.py
@@ -1050,8 +1050,11 @@
Column( "user_id", Integer, ForeignKey( "galaxy_user.id" ), index=True ),
Column( "key", TrimmedString( 32 ), index=True, unique=True ) )
+
# With the tables defined we can define the mappers and setup the
# relationships between the model objects.
+def simple_mapping( model, **kwds ):
+ mapper( model, model.table, properties=kwds )
mapper( model.Sample, model.Sample.table,
@@ -1200,64 +1203,62 @@
mapper( model.ValidationError, model.ValidationError.table )
-mapper( model.HistoryDatasetAssociation, model.HistoryDatasetAssociation.table,
- properties=dict(
- dataset=relation(
- model.Dataset,
- primaryjoin=( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ), lazy=False ),
- # .history defined in History mapper
- copied_from_history_dataset_association=relation(
- model.HistoryDatasetAssociation,
- primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_history_dataset_association_id == model.HistoryDatasetAssociation.table.c.id ),
- remote_side=[model.HistoryDatasetAssociation.table.c.id],
- uselist=False ),
- copied_to_history_dataset_associations=relation(
- model.HistoryDatasetAssociation,
- primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_history_dataset_association_id == model.HistoryDatasetAssociation.table.c.id ) ),
- copied_from_library_dataset_dataset_association=relation(
- model.LibraryDatasetDatasetAssociation,
- primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_library_dataset_dataset_association_id == model.LibraryDatasetDatasetAssociation.table.c.id ),
- uselist=False ),
- copied_to_library_dataset_dataset_associations=relation(
- model.LibraryDatasetDatasetAssociation,
- primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_library_dataset_dataset_association_id == model.LibraryDatasetDatasetAssociation.table.c.id ) ),
- implicitly_converted_datasets=relation(
- model.ImplicitlyConvertedDatasetAssociation,
- primaryjoin=( model.ImplicitlyConvertedDatasetAssociation.table.c.hda_parent_id == model.HistoryDatasetAssociation.table.c.id ) ),
- implicitly_converted_parent_datasets=relation(
- model.ImplicitlyConvertedDatasetAssociation,
- primaryjoin=( model.ImplicitlyConvertedDatasetAssociation.table.c.hda_id == model.HistoryDatasetAssociation.table.c.id ) ),
- children=relation(
- model.HistoryDatasetAssociation,
- primaryjoin=( model.HistoryDatasetAssociation.table.c.parent_id == model.HistoryDatasetAssociation.table.c.id ),
- 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 ) ) ),
- 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" ) )
- )
+simple_mapping( model.HistoryDatasetAssociation,
+ dataset=relation(
+ model.Dataset,
+ primaryjoin=( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ), lazy=False ),
+ # .history defined in History mapper
+ copied_from_history_dataset_association=relation(
+ model.HistoryDatasetAssociation,
+ primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_history_dataset_association_id == model.HistoryDatasetAssociation.table.c.id ),
+ remote_side=[model.HistoryDatasetAssociation.table.c.id],
+ uselist=False ),
+ copied_to_history_dataset_associations=relation(
+ model.HistoryDatasetAssociation,
+ primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_history_dataset_association_id == model.HistoryDatasetAssociation.table.c.id ) ),
+ copied_from_library_dataset_dataset_association=relation(
+ model.LibraryDatasetDatasetAssociation,
+ primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_library_dataset_dataset_association_id == model.LibraryDatasetDatasetAssociation.table.c.id ),
+ uselist=False ),
+ copied_to_library_dataset_dataset_associations=relation(
+ model.LibraryDatasetDatasetAssociation,
+ primaryjoin=( model.HistoryDatasetAssociation.table.c.copied_from_library_dataset_dataset_association_id == model.LibraryDatasetDatasetAssociation.table.c.id ) ),
+ implicitly_converted_datasets=relation(
+ model.ImplicitlyConvertedDatasetAssociation,
+ primaryjoin=( model.ImplicitlyConvertedDatasetAssociation.table.c.hda_parent_id == model.HistoryDatasetAssociation.table.c.id ) ),
+ implicitly_converted_parent_datasets=relation(
+ model.ImplicitlyConvertedDatasetAssociation,
+ primaryjoin=( model.ImplicitlyConvertedDatasetAssociation.table.c.hda_id == model.HistoryDatasetAssociation.table.c.id ) ),
+ children=relation(
+ model.HistoryDatasetAssociation,
+ primaryjoin=( model.HistoryDatasetAssociation.table.c.parent_id == model.HistoryDatasetAssociation.table.c.id ),
+ 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 ) ) ),
+ 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" )
+)
-mapper( model.Dataset, model.Dataset.table,
- properties=dict(
- history_associations=relation(
- model.HistoryDatasetAssociation,
- primaryjoin=( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ) ),
- active_history_associations=relation(
- model.HistoryDatasetAssociation,
- primaryjoin=( ( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ) & ( model.HistoryDatasetAssociation.table.c.deleted == False ) & ( model.HistoryDatasetAssociation.table.c.purged == False ) ) ),
- purged_history_associations=relation(
- model.HistoryDatasetAssociation,
- primaryjoin=( ( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ) & ( model.HistoryDatasetAssociation.table.c.purged == True ) ) ),
- library_associations=relation(
- model.LibraryDatasetDatasetAssociation,
- primaryjoin=( model.Dataset.table.c.id == model.LibraryDatasetDatasetAssociation.table.c.dataset_id ) ),
- active_library_associations=relation(
- model.LibraryDatasetDatasetAssociation,
- primaryjoin=( ( model.Dataset.table.c.id == model.LibraryDatasetDatasetAssociation.table.c.dataset_id ) & ( model.LibraryDatasetDatasetAssociation.table.c.deleted == False ) ) ),
- tags=relation(model.DatasetTagAssociation, order_by=model.DatasetTagAssociation.table.c.id, backref='datasets')
- ) )
+simple_mapping( model.Dataset,
+ history_associations=relation(
+ model.HistoryDatasetAssociation,
+ primaryjoin=( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ) ),
+ active_history_associations=relation(
+ model.HistoryDatasetAssociation,
+ primaryjoin=( ( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ) & ( model.HistoryDatasetAssociation.table.c.deleted == False ) & ( model.HistoryDatasetAssociation.table.c.purged == False ) ) ),
+ purged_history_associations=relation(
+ model.HistoryDatasetAssociation,
+ primaryjoin=( ( model.Dataset.table.c.id == model.HistoryDatasetAssociation.table.c.dataset_id ) & ( model.HistoryDatasetAssociation.table.c.purged == True ) ) ),
+ library_associations=relation(
+ model.LibraryDatasetDatasetAssociation,
+ primaryjoin=( model.Dataset.table.c.id == model.LibraryDatasetDatasetAssociation.table.c.dataset_id ) ),
+ active_library_associations=relation(
+ model.LibraryDatasetDatasetAssociation,
+ primaryjoin=( ( model.Dataset.table.c.id == model.LibraryDatasetDatasetAssociation.table.c.dataset_id ) & ( model.LibraryDatasetDatasetAssociation.table.c.deleted == False ) ) ),
+ tags=relation(model.DatasetTagAssociation, order_by=model.DatasetTagAssociation.table.c.id, backref='datasets')
+)
mapper( model.HistoryDatasetAssociationDisplayAtAuthorization, model.HistoryDatasetAssociationDisplayAtAuthorization.table,
properties=dict( history_dataset_association = relation( model.HistoryDatasetAssociation ),
@@ -1751,90 +1752,63 @@
) )
# Tag tables.
+simple_mapping( model.Tag,
+ children=relation(model.Tag, backref=backref( 'parent', remote_side=[model.Tag.table.c.id] ) )
+)
-mapper( model.Tag, model.Tag.table,
- properties=dict( children=relation(model.Tag, backref=backref( 'parent', remote_side=[model.Tag.table.c.id] ) )
- ) )
-mapper( model.HistoryTagAssociation, model.HistoryTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_histories"), user=relation( model.User ) )
- )
+def tag_mapping( tag_association_class, backref_name ):
+ simple_mapping( tag_association_class, tag=relation( model.Tag, backref=backref_name), user=relation( model.User ) )
-mapper( model.DatasetTagAssociation, model.DatasetTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_datasets"), user=relation( model.User ) )
- )
+tag_mapping( model.HistoryTagAssociation, "tagged_histories" )
-mapper( model.HistoryDatasetAssociationTagAssociation, model.HistoryDatasetAssociationTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_history_dataset_associations"), user=relation( model.User ) )
- )
+tag_mapping( model.DatasetTagAssociation, "tagged_datasets" )
-mapper( model.PageTagAssociation, model.PageTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_pages"), user=relation( model.User ) )
- )
+tag_mapping( model.HistoryDatasetAssociationTagAssociation, "tagged_history_dataset_associations" )
-mapper( model.StoredWorkflowTagAssociation, model.StoredWorkflowTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_workflows"), user=relation( model.User ) )
- )
+tag_mapping( model.PageTagAssociation, "tagged_pages" )
-mapper( model.WorkflowStepTagAssociation, model.WorkflowStepTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_workflow_steps"), user=relation( model.User ) )
- )
+tag_mapping( model.StoredWorkflowTagAssociation, "tagged_workflows" )
-mapper( model.VisualizationTagAssociation, model.VisualizationTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_visualizations"), user=relation( model.User ) )
- )
+tag_mapping( model.WorkflowStepTagAssociation, "tagged_workflow_steps" )
-mapper( model.ToolTagAssociation, model.ToolTagAssociation.table,
- properties=dict( tag=relation(model.Tag, backref="tagged_tools"), user=relation( model.User ) )
- )
+tag_mapping( model.VisualizationTagAssociation, "tagged_visualizations" )
+
+tag_mapping( model.ToolTagAssociation, "tagged_tools" )
+
# Annotation tables.
+def annotation_mapping( annotation_class, **kwds ):
+ kwds = dict( [ (key, relation( value ) ) for key, value in kwds.iteritems() ] )
+ simple_mapping( annotation_class, **dict(user=relation( model.User ), **kwds ) )
-mapper( model.HistoryAnnotationAssociation, model.HistoryAnnotationAssociation.table,
- properties=dict( history=relation( model.History ), user=relation( model.User ) )
- )
+annotation_mapping( model.HistoryAnnotationAssociation, history=model.History )
-mapper( model.HistoryDatasetAssociationAnnotationAssociation, model.HistoryDatasetAssociationAnnotationAssociation.table,
- properties=dict( hda=relation( model.HistoryDatasetAssociation ), user=relation( model.User ) )
- )
+annotation_mapping( model.HistoryDatasetAssociationAnnotationAssociation, hda=model.HistoryDatasetAssociation )
-mapper( model.StoredWorkflowAnnotationAssociation, model.StoredWorkflowAnnotationAssociation.table,
- properties=dict( stored_workflow=relation( model.StoredWorkflow ), user=relation( model.User ) )
- )
+annotation_mapping( model.StoredWorkflowAnnotationAssociation, stored_workflow=model.StoredWorkflow )
-mapper( model.WorkflowStepAnnotationAssociation, model.WorkflowStepAnnotationAssociation.table,
- properties=dict( workflow_step=relation( model.WorkflowStep ), user=relation( model.User ) )
- )
+annotation_mapping( model.WorkflowStepAnnotationAssociation, workflow_step=model.WorkflowStep )
-mapper( model.PageAnnotationAssociation, model.PageAnnotationAssociation.table,
- properties=dict( page=relation( model.Page ), user=relation( model.User ) )
- )
+annotation_mapping( model.PageAnnotationAssociation, page=model.Page )
-mapper( model.VisualizationAnnotationAssociation, model.VisualizationAnnotationAssociation.table,
- properties=dict( visualization=relation( model.Visualization ), user=relation( model.User ) )
- )
+annotation_mapping( model.VisualizationAnnotationAssociation, visualization=model.Visualization )
+
# Rating tables.
+def rating_mapping( rating_class, **kwds ):
+ kwds = dict( [ (key, relation( value ) ) for key, value in kwds.iteritems() ] )
+ simple_mapping( rating_class, **dict(user=relation( model.User ), **kwds ) )
-mapper( model.HistoryRatingAssociation, model.HistoryRatingAssociation.table,
- properties=dict( history=relation( model.History ), user=relation( model.User ) )
- )
+rating_mapping( model.HistoryRatingAssociation, history=model.History )
-mapper( model.HistoryDatasetAssociationRatingAssociation, model.HistoryDatasetAssociationRatingAssociation.table,
- properties=dict( hda=relation( model.HistoryDatasetAssociation ), user=relation( model.User ) )
- )
+rating_mapping( model.HistoryDatasetAssociationRatingAssociation, hda=model.HistoryDatasetAssociation )
-mapper( model.StoredWorkflowRatingAssociation, model.StoredWorkflowRatingAssociation.table,
- properties=dict( stored_workflow=relation( model.StoredWorkflow ), user=relation( model.User ) )
- )
+rating_mapping( model.StoredWorkflowRatingAssociation, stored_workflow=model.StoredWorkflow )
-mapper( model.PageRatingAssociation, model.PageRatingAssociation.table,
- properties=dict( page=relation( model.Page ), user=relation( model.User ) )
- )
+rating_mapping( model.PageRatingAssociation, page=model.Page )
-mapper( model.VisualizationRatingAssociation, model.VisualizationRatingAssociation.table,
- properties=dict( visualization=relation( model.Visualization ), user=relation( model.User ) )
- )
+rating_mapping( model.VisualizationRatingAssociation, visualizaiton=model.Visualization )
#Data Manager tables
mapper( model.DataManagerHistoryAssociation, model.DataManagerHistoryAssociation.table,
diff -r 1b78bcbb1bc2bc0f39149726855418ccc890a3ff -r 35ae5ce8be84dcccadaf58c9b569fb9cf9daccbf test/unit/test_galaxy_mapping.py
--- a/test/unit/test_galaxy_mapping.py
+++ b/test/unit/test_galaxy_mapping.py
@@ -4,9 +4,138 @@
class MappingTests( unittest.TestCase ):
+ def test_annotations( self ):
+ model = self.model
+
+ u = model.User( email="annotator(a)example.com", password="password" )
+ self.persist( u )
+
+ def persist_and_check_annotation( annotation_class, **kwds ):
+ annotated_association = annotation_class()
+ annotated_association.annotation = "Test Annotation"
+ annotated_association.user = u
+ for key, value in kwds.iteritems():
+ setattr(annotated_association, key, value)
+ self.persist( annotated_association )
+ self.expunge()
+ stored_annotation = self.query( annotation_class ).all()[0]
+ assert stored_annotation.annotation == "Test Annotation"
+ assert stored_annotation.user.email == "annotator(a)example.com"
+
+ sw = model.StoredWorkflow()
+ sw.user = u
+ self.persist( sw )
+ persist_and_check_annotation( model.StoredWorkflowAnnotationAssociation, stored_workflow=sw )
+
+ workflow = model.Workflow()
+ workflow.stored_workflow = sw
+ self.persist( workflow )
+
+ ws = model.WorkflowStep()
+ ws.workflow = workflow
+ self.persist( ws )
+ persist_and_check_annotation( model.WorkflowStepAnnotationAssociation, workflow_step=ws )
+
+ h = model.History( name="History for Annotation", user=u)
+ self.persist( h )
+ persist_and_check_annotation( model.HistoryAnnotationAssociation, history=h )
+
+ d1 = model.HistoryDatasetAssociation( extension="txt", history=h, create_dataset=True, sa_session=model.session )
+ self.persist( d1 )
+ persist_and_check_annotation( model.HistoryDatasetAssociationAnnotationAssociation, hda=d1 )
+
+ page = model.Page()
+ page.user = u
+ self.persist( page )
+ persist_and_check_annotation( model.PageAnnotationAssociation, page=page )
+
+ visualization = model.Visualization()
+ visualization.user = u
+ self.persist( visualization )
+ persist_and_check_annotation( model.VisualizationAnnotationAssociation, visualization=visualization )
+
+ def test_ratings( self ):
+ model = self.model
+
+ u = model.User( email="rater(a)example.com", password="password" )
+ self.persist( u )
+
+ def persist_and_check_rating( rating_class, **kwds ):
+ rating_association = rating_class()
+ rating_association.rating = 5
+ rating_association.user = u
+ for key, value in kwds.iteritems():
+ setattr(rating_association, key, value)
+ self.persist( rating_association )
+ self.expunge()
+ stored_annotation = self.query( rating_class ).all()[0]
+ assert stored_annotation.rating == 5
+ assert stored_annotation.user.email == "rater(a)example.com"
+
+ sw = model.StoredWorkflow()
+ sw.user = u
+ self.persist( sw )
+ persist_and_check_rating( model.StoredWorkflowRatingAssociation, stored_workflow=sw )
+
+ h = model.History( name="History for Rating", user=u)
+ self.persist( h )
+ persist_and_check_rating( model.HistoryRatingAssociation, history=h )
+
+ d1 = model.HistoryDatasetAssociation( extension="txt", history=h, create_dataset=True, sa_session=model.session )
+ self.persist( d1 )
+ persist_and_check_rating( model.HistoryDatasetAssociationRatingAssociation, hda=d1 )
+
+ page = model.Page()
+ page.user = u
+ self.persist( page )
+ persist_and_check_rating( model.PageRatingAssociation, page=page )
+
+ visualization = model.Visualization()
+ visualization.user = u
+ self.persist( visualization )
+ persist_and_check_rating( model.VisualizationRatingAssociation, visualization=visualization )
+
+ def test_tags( self ):
+ model = self.model
+
+ my_tag = model.Tag(name="Test Tag")
+ u = model.User( email="tagger(a)example.com", password="password" )
+ self.persist( my_tag, u )
+
+ def tag_and_test( taggable_object, tag_association_class, backref_name ):
+ assert len( getattr(self.query( model.Tag ).filter( model.Tag.name == "Test Tag" ).all()[0], backref_name) ) == 0
+
+ tag_association = tag_association_class()
+ tag_association.tag = my_tag
+ taggable_object.tags = [ tag_association ]
+ self.persist( tag_association, taggable_object )
+
+ assert len( getattr(self.query( model.Tag ).filter( model.Tag.name == "Test Tag" ).all()[0], backref_name) ) == 1
+
+ sw = model.StoredWorkflow()
+ sw.user = u
+ #self.persist( sw )
+ tag_and_test( sw, model.StoredWorkflowTagAssociation, "tagged_workflows" )
+
+ h = model.History( name="History for Tagging", user=u)
+ tag_and_test( h, model.HistoryTagAssociation, "tagged_histories" )
+
+ d1 = model.HistoryDatasetAssociation( extension="txt", history=h, create_dataset=True, sa_session=model.session )
+ tag_and_test( d1, model.HistoryDatasetAssociationTagAssociation, "tagged_history_dataset_associations" )
+
+ page = model.Page()
+ page.user = u
+ tag_and_test( page, model.PageTagAssociation, "tagged_pages" )
+
+ visualization = model.Visualization()
+ visualization.user = u
+ tag_and_test( visualization, model.VisualizationTagAssociation, "tagged_visualizations" )
+
def test_basic( self ):
model = self.model
+ original_user_count = len( model.session.query( model.User ).all() )
+
# Make some changes and commit them
u = model.User( email="james(a)foo.bar.baz", password="password" )
# gs = model.GalaxySession()
@@ -24,26 +153,31 @@
# Check
users = model.session.query( model.User ).all()
- assert len( users ) == 1
- assert users[0].email == "james(a)foo.bar.baz"
- assert users[0].password == "password"
- assert len( users[0].histories ) == 1
- assert users[0].histories[0].name == "History 1"
+ assert len( users ) == original_user_count + 1
+ user = [user for user in users if user.email == "james(a)foo.bar.baz"][0]
+ assert user.email == "james(a)foo.bar.baz"
+ assert user.password == "password"
+ assert len( user.histories ) == 1
+ assert user.histories[0].name == "History 1"
hists = model.session.query( model.History ).all()
- assert hists[0].name == "History 1"
- assert hists[1].name == ( "H" * 255 )
- assert hists[0].user == users[0]
- assert hists[1].user is None
- assert hists[1].datasets[0].metadata.chromCol == 1
+ hist0 = [history for history in hists if history.name == "History 1"][0]
+ hist1 = [history for history in hists if history.name == "H" * 255][0]
+ assert hist0.name == "History 1"
+ assert hist1.name == ( "H" * 255 )
+ assert hist0.user == user
+ assert hist1.user is None
+ assert hist1.datasets[0].metadata.chromCol == 1
# The filename test has moved to objecstore
- #id = hists[1].datasets[0].id
- #assert hists[1].datasets[0].file_name == os.path.join( "/tmp", *directory_hash_id( id ) ) + ( "/dataset_%d.dat" % id )
+ #id = hist1.datasets[0].id
+ #assert hist1.datasets[0].file_name == os.path.join( "/tmp", *directory_hash_id( id ) ) + ( "/dataset_%d.dat" % id )
# Do an update and check
- hists[1].name = "History 2b"
+ hist1.name = "History 2b"
self.expunge()
hists = model.session.query( model.History ).all()
- assert hists[0].name == "History 1"
- assert hists[1].name == "History 2b"
+ hist0 = [history for history in hists if history.name == "History 1"][0]
+ hist1 = [history for history in hists if history.name == "History 2b"][0]
+ assert hist0.name == "History 1"
+ assert hist1.name == "History 2b"
# gvk TODO need to ad test for GalaxySessions, but not yet sure what they should look like.
@classmethod
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0