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 2012
- 1 participants
- 142 discussions
commit/galaxy-central: carlfeberhard: history panel and popupmenu: various fixes for IE
by Bitbucket 07 Dec '12
by Bitbucket 07 Dec '12
07 Dec '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/63fc9cbe381d/
changeset: 63fc9cbe381d
user: carlfeberhard
date: 2012-12-07 22:02:21
summary: history panel and popupmenu: various fixes for IE
affected #: 3 files
diff -r b516a3fb0fc102c1b0b527f072e86a4afc74679e -r 63fc9cbe381d2719134f87c019911565e3a934a1 templates/base.mako
--- a/templates/base.mako
+++ b/templates/base.mako
@@ -54,7 +54,7 @@
info : function(){},
warn : function(){},
error : function(){},
- assert : function(){},
+ assert : function(){}
};
// Set up needed paths.
diff -r b516a3fb0fc102c1b0b527f072e86a4afc74679e -r 63fc9cbe381d2719134f87c019911565e3a934a1 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -75,7 +75,7 @@
info : function(){},
warn : function(){},
error : function(){},
- assert : function(){},
+ assert : function(){}
};
// Set up needed paths.
diff -r b516a3fb0fc102c1b0b527f072e86a4afc74679e -r 63fc9cbe381d2719134f87c019911565e3a934a1 templates/root/alternate_history.mako
--- a/templates/root/alternate_history.mako
+++ b/templates/root/alternate_history.mako
@@ -287,7 +287,7 @@
top.Galaxy.currUser = top.Galaxy.currUser;
top.Galaxy.currHistoryPanel = top.Galaxy.currHistoryPanel;
- top.Galaxy.paths = galaxy_paths;
+ //top.Galaxy.paths = galaxy_paths;
top.Galaxy.localization = GalaxyLocalization;
window.Galaxy = top.Galaxy;
@@ -297,12 +297,13 @@
GalaxyLocalization.setLocalizedString( ${ create_localization_json( get_page_localized_strings() ) } );
// add needed controller urls to GalaxyPaths
+if( !galaxy_paths ){ galaxy_paths = top.galaxy_paths || new GalaxyPaths(); }
galaxy_paths.set( 'hda', ${get_hda_url_templates()} );
galaxy_paths.set( 'history', ${get_history_url_templates()} );
$(function(){
galaxyPageSetUp();
- Galaxy.historyFrame = window;
+ //Galaxy.historyFrame = window;
var debugging = ( new PersistantStorage( '__history_panel' ).get( 'debugging' ) || false );
@@ -387,6 +388,7 @@
}
// lots of wtf here...due to infernalframes
+ //TODO: this is way tooo acrobatic
var $historyButtonWindow = $( top.document ),
HISTORY_MENU_BUTTON_ID = 'history-options-button',
$historyMenuButton = $historyButtonWindow.find( '#' + HISTORY_MENU_BUTTON_ID ),
@@ -410,44 +412,50 @@
// since the history frame reloads so often (compared to the main window),
// we need to check whether these options are there already before we add them again
- //NOTE: we use the global here because these remain bound in the main window even if panel refreshes
+ // In IE, however, NOT re-adding them creates a 'cant execute from freed script' error:
+ // so...we need to re-add the function in either case (just not the option itself)
+ //NOTE: we use the global Galaxy.currHistoryPanel here
+ // because these remain bound in the main window even if panel refreshes
//TODO: too much boilerplate
- if( popupMenu.findIndexByHtml( COLLAPSE_OPTION_TEXT ) === null ){
- popupMenu.addItem({
- html : COLLAPSE_OPTION_TEXT,
- func : function() {
- Galaxy.currHistoryPanel.collapseAllHdaBodies();
- }
- }, START_INSERTING_AT_INDEX )
+ //TODO: ugh...(in general)
+ var collapseOption = popupMenu.findItemByHtml( COLLAPSE_OPTION_TEXT );
+ if( !collapseOption ){
+ collapseOption = {
+ html : COLLAPSE_OPTION_TEXT
+ };
+ popupMenu.addItem( collapseOption, START_INSERTING_AT_INDEX )
}
+ collapseOption.func = function() {
+ Galaxy.currHistoryPanel.collapseAllHdaBodies();
+ };
- var deletedOptionIndex = popupMenu.findIndexByHtml( DELETED_OPTION_TEXT );
- if( deletedOptionIndex === null ){
- popupMenu.addItem({
- html : DELETED_OPTION_TEXT,
- func : function( clickEvent, thisMenuOption ){
- var show_deleted = Galaxy.currHistoryPanel.toggleShowDeleted();
- thisMenuOption.checked = show_deleted;
- }
- }, START_INSERTING_AT_INDEX + 1 )
- deletedOptionIndex = START_INSERTING_AT_INDEX + 1;
+ var deletedOption = popupMenu.findItemByHtml( DELETED_OPTION_TEXT );
+ if( !deletedOption ){
+ deletedOption = {
+ html : DELETED_OPTION_TEXT
+ };
+ popupMenu.addItem( deletedOption, START_INSERTING_AT_INDEX + 1 )
}
+ deletedOption.func = function( clickEvent, thisMenuOption ){
+ var show_deleted = Galaxy.currHistoryPanel.toggleShowDeleted();
+ thisMenuOption.checked = show_deleted;
+ };
// whether was there or added, update the checked option to reflect the panel's settings on the panel render
- popupMenu.options[ deletedOptionIndex ].checked = Galaxy.currHistoryPanel.storage.get( 'show_deleted' );
+ deletedOption.checked = Galaxy.currHistoryPanel.storage.get( 'show_deleted' );
- var hiddenOptionIndex = popupMenu.findIndexByHtml( HIDDEN_OPTION_TEXT );
- if( hiddenOptionIndex === null ){
- popupMenu.addItem({
- html : HIDDEN_OPTION_TEXT,
- func : function( clickEvent, thisMenuOption ){
- var show_hidden = Galaxy.currHistoryPanel.toggleShowHidden();
- thisMenuOption.checked = show_hidden;
- }
- }, START_INSERTING_AT_INDEX + 2 )
- hiddenOptionIndex = START_INSERTING_AT_INDEX + 2;
+ var hiddenOption = popupMenu.findItemByHtml( HIDDEN_OPTION_TEXT );
+ if( !hiddenOption ){
+ hiddenOption = {
+ html : HIDDEN_OPTION_TEXT
+ };
+ popupMenu.addItem( hiddenOption, START_INSERTING_AT_INDEX + 2 )
}
+ hiddenOption.func = function( clickEvent, thisMenuOption ){
+ var show_hidden = Galaxy.currHistoryPanel.toggleShowHidden();
+ thisMenuOption.checked = show_hidden;
+ };
// whether was there or added, update the checked option to reflect the panel's settings on the panel render
- popupMenu.options[ hiddenOptionIndex ].checked = Galaxy.currHistoryPanel.storage.get( 'show_hidden' );
+ hiddenOption.checked = Galaxy.currHistoryPanel.storage.get( 'show_hidden' );
})();
//TODO: both the quota meter and the options-menu stuff need to be moved out when iframes are removed
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
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/b516a3fb0fc1/
changeset: b516a3fb0fc1
user: carlfeberhard
date: 2012-12-07 20:36:44
summary: pack_scripts
affected #: 1 file
diff -r 9c90d4c2f4ccfa6303b127a51c27bd2e57402594 -r b516a3fb0fc102c1b0b527f072e86a4afc74679e static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this);if(!this.templates.wrapper){this.templates.wrapper=Handlebars.templates["template-popupmenu-wrapper"]}},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(PopupMenu.templates.menu({options:this.options,id:this.$button.attr("id")}));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width(),a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this,a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?(a):(this.options.length);this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if((_.has(this.options[a],"html"))&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.templates={menu:Handlebars.templates["template-popupmenu-menu"]};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this)},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(PopupMenu.templates.menu({options:this.options,id:this.$button.attr("id")}));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width(),a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this,a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?(a):(this.options.length);this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if((_.has(this.options[a],"html"))&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.templates={menu:Handlebars.templates["template-popupmenu-menu"]};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ 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
07 Dec '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/9c90d4c2f4cc/
changeset: 9c90d4c2f4cc
user: carlfeberhard
date: 2012-12-07 20:13:25
summary: ui.js: fix to bad template reference
affected #: 1 file
diff -r cba8dbdb8312dcfa93e0be299fb560c067266064 -r 9c90d4c2f4ccfa6303b127a51c27bd2e57402594 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -205,9 +205,6 @@
// template loading is problematic - ui is loaded in base.mako
// and the template (prev.) needed to be loaded before ui
- if( !this.templates.wrapper ){
- this.templates.wrapper = Handlebars.templates[ 'template-popupmenu-wrapper' ];
- }
},
/** Render the menu. NOTE: doesn't attach itself to the DOM.
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/changeset/6d7e637883b7/
changeset: 6d7e637883b7
user: carlfeberhard
date: 2012-12-07 19:56:53
summary: ui: adding PopupMenu view as alternate to make_popup_menu and allow changing option text, adding/removing options, and adding checkmarks for togglable options; index.mako: use PopupMenu for history-options-button; history panel: use alternate_history.mako to add 'collapse all', 'Include hidden datasets'(toggle), 'Include deleted datasets'(toggle) to history-options-button; alternate_history.mako: include better system for debugging js when changing source directly is problematic (main/test); pack_scripts;
affected #: 19 files
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 lib/galaxy/webapps/galaxy/controllers/root.py
--- a/lib/galaxy/webapps/galaxy/controllers/root.py
+++ b/lib/galaxy/webapps/galaxy/controllers/root.py
@@ -98,7 +98,6 @@
return trans.fill_template_mako( "/my_data.mako" )
@web.expose
- #def history( self, trans, as_xml=False, show_deleted=False, show_hidden=False, hda_id=None, **kwd ):
def history( self, trans, as_xml=False, show_deleted=None, show_hidden=None, hda_id=None, **kwd ):
"""
Display the current history, creating a new history if necessary.
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -288,7 +288,7 @@
},
/** String representation.
*/
- toString : function(){ return 'PersistantStorage(' + data + ')'; }
+ toString : function(){ return 'PersistantStorage(' + storageKey + ')'; }
});
return returnedStorage;
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -28,6 +28,7 @@
* @see Backbone.View#initialize
*/
initialize : function( attributes ){
+ if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
this.log( this + '.initialize:', attributes );
/** list of rendering functions for the default, primary icon-buttons. */
@@ -334,6 +335,8 @@
//TODO: not a fan of this dispatch
switch( this.model.get( 'state' ) ){
+ case HistoryDatasetAssociation.STATES.NEW :
+ break;
case HistoryDatasetAssociation.STATES.NOT_VIEWABLE :
this._render_body_not_viewable( body );
break;
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/mvc/dataset/hda-model.js
--- a/static/scripts/mvc/dataset/hda-model.js
+++ b/static/scripts/mvc/dataset/hda-model.js
@@ -130,8 +130,7 @@
//TODO: to list inclusion test
//TODO: class level readyStates list
return (
- ( state === HistoryDatasetAssociation.STATES.NEW )
- || ( state === HistoryDatasetAssociation.STATES.OK )
+ ( state === HistoryDatasetAssociation.STATES.OK )
|| ( state === HistoryDatasetAssociation.STATES.EMPTY )
|| ( state === HistoryDatasetAssociation.STATES.FAILED_METADATA )
|| ( state === HistoryDatasetAssociation.STATES.NOT_VIEWABLE )
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/mvc/history/history-panel.js
--- a/static/scripts/mvc/history/history-panel.js
+++ b/static/scripts/mvc/history/history-panel.js
@@ -140,6 +140,8 @@
* @see Backbone.View#initialize
*/
initialize : function( attributes ){
+ // set the logger if requested
+ if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
this.log( this + '.initialize:', attributes );
// set up url templates
@@ -203,7 +205,7 @@
show_deleted : false,
show_hidden : false
});
- this.log( 'this.storage:', this.storage.get() );
+ this.log( this + ' (prev) storage:', JSON.stringify( this.storage.get(), null, 2 ) );
// expanded Hdas is a map of hda.ids -> a boolean rep'ing whether this hda's body is expanded
// store any pre-expanded ids passed in
@@ -226,7 +228,7 @@
this.show_deleted = this.storage.get( 'show_deleted' );
this.show_hidden = this.storage.get( 'show_hidden' );
//this.log( 'this.show_deleted:', this.show_deleted, 'show_hidden', this.show_hidden );
- this.log( '(init\'d) this.storage:', this.storage.get() );
+ this.log( this + ' (init\'d) storage:', this.storage.get() );
},
/** Add an hda to this history's collection
@@ -351,7 +353,8 @@
historyView.hdaViews[ hdaId ] = new historyView.HDAView({
model : hda,
expanded : expanded,
- urlTemplates : historyView.hdaUrlTemplates
+ urlTemplates : historyView.hdaUrlTemplates,
+ logger : historyView.logger
});
historyView._setUpHdaListeners( historyView.hdaViews[ hdaId ] );
@@ -432,19 +435,23 @@
/** Handle the user toggling the deleted visibility by:
* (1) storing the new value in the persistant storage
* (2) re-rendering the history
+ * @returns {Boolean} new show_deleted setting
*/
toggleShowDeleted : function(){
this.storage.set( 'show_deleted', !this.storage.get( 'show_deleted' ) );
this.render();
+ return this.storage.get( 'show_deleted' );
},
/** Handle the user toggling the deleted visibility by:
* (1) storing the new value in the persistant storage
* (2) re-rendering the history
+ * @returns {Boolean} new show_hidden setting
*/
toggleShowHidden : function(){
this.storage.set( 'show_hidden', !this.storage.get( 'show_hidden' ) );
this.render();
+ return this.storage.get( 'show_hidden' );
},
/** Collapse all hda bodies and clear expandedHdas in the storage
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -76,11 +76,11 @@
iconButton : Handlebars.partials.iconButton
};
-
var IconButtonCollection = Backbone.Collection.extend({
model: IconButton
});
+
//------------------------------------------------------------------------------
/**
* Menu with multiple icon buttons. Views are not needed nor used for individual buttons.
@@ -166,15 +166,319 @@
});
+// =============================================================================
+/** @class View for a popup menu
+ * @name PopupMenu
+ *
+ * @constructs
+ */
+var PopupMenu = Backbone.View.extend(
+/** @lends PopupMenu.prototype */{
+ /* TODO:
+ add submenus
+ add hrefs
+ test various html keys
+ add make_popupmenus style
+ get template inside this file somehow
+ */
+ /** Cache the desired button element and options, set up the button click handler
+ * NOTE: attaches this view as HTML/jQ data on the button for later use.
+ */
+ //TODO: include docs on special option keys (divider, checked, etc.)
+ initialize : function( $button, options ){
+ // default settings
+ this.$button = $button || $( '<div/>' );
+ this.options = options || [];
+ //console.debug( this + '.initialize, button:', $button, ', options:', options );
+ // set up button click -> open menu behavior
+ var menu = this;
+ this.$button.click( function( event ){
+ menu._renderAndShow( event );
+ //event.stopPropagation();
+ return false;
+ });
+ // attach this view as a data object on the button - for later access
+ //TODO:?? memleak?
+ this.$button.data( 'PopupMenu', this );
+ // template loading is problematic - ui is loaded in base.mako
+ // and the template (prev.) needed to be loaded before ui
+ if( !this.templates.wrapper ){
+ this.templates.wrapper = Handlebars.templates[ 'template-popupmenu-wrapper' ];
+ }
+ },
+ /** Render the menu. NOTE: doesn't attach itself to the DOM.
+ * @see PopupMenu#_renderAndShow
+ */
+ render : function(){
+ var menu = this;
+ // render the menu body
+ this.$el.addClass( 'popmenu-wrapper' )
+ .css({
+ position: 'absolute',
+ display: 'none'
+ });
+ //BUG: anchors within a.popupmenu-option render OUTSIDE the a.popupmenu-option!?
+ this.$el.html( PopupMenu.templates.menu({
+ options : this.options,
+ // sets menu div id to '{{ id }}-menu'
+ id : this.$button.attr( 'id' )
+ }));
+ //console.debug( this.$el, ':', this.$el.html() );
+ // set up behavior on each link/anchor elem
+ if( this.options.length ){
+ this.$el.find( 'li' ).each( function( i, li ){
+ var $li = $( li ),
+ $anchor = $li.children( 'a.popupmenu-option' ),
+ menuFunc = menu.options[ i ].func;
+ //console.debug( 'setting up behavior:', i, menu.options[ i ], $li, $anchor );
+ if( $anchor.length && menuFunc ){
+ $anchor.click( function( event ){
+ menuFunc( event, menu.options[ i ] );
+ });
+ }
+ // cache the anchor as a jq obj within the options obj
+ menu.options[ i ].$li = $li;
+ });
+ }
+ return this;
+ },
+ /** Get the absolute position/offset for the menu
+ */
+ _getShownPosition : function( clickEvent ){
+ var menuWidth = this.$el.width(),
+ // display menu horiz. centered on click...
+ x = clickEvent.pageX - menuWidth / 2 ;
+ // ...but adjust that to handle horiz. scroll and window dimensions (draw entirely on visible screen area)
+ x = Math.min( x, $( document ).scrollLeft() + $( window ).width() - menuWidth - 5 );
+ x = Math.max( x, $( document ).scrollLeft() + 5 );
+
+ return {
+ top: clickEvent.pageY,
+ left: x
+ };
+ },
+
+ /** Render the menu, append to the page body at the click position, and set up the 'click-away' handlers, show
+ */
+ _renderAndShow : function( clickEvent ){
+ this.render();
+ this.$el.appendTo( 'body' );
+ this.$el.css( this._getShownPosition( clickEvent ) );
+ this._setUpCloseBehavior();
+ this.$el.show();
+ },
+
+ /** Bind an event handler to all available frames so that when anything is clicked
+ * * the menu is removed from the DOM
+ * * The event handler unbinds itself
+ */
+ _setUpCloseBehavior : function(){
+ var menu = this,
+ // function to close popup and unbind itself
+ closePopupWhenClicked = function( $elClicked ){
+ $elClicked.bind( "click.close_popup", function(){
+ menu.remove();
+ $elClicked.unbind( "click.close_popup" );
+ });
+ };
+
+ // bind to current, parent, and sibling frames
+ //TODO: (Assuming for now that this is the best way to do this...)
+ closePopupWhenClicked( $( window.document ) );
+ closePopupWhenClicked( $( window.top.document ) );
+ _.each( window.top.frames, function( siblingFrame ){
+ closePopupWhenClicked( $( siblingFrame.document ) );
+ });
+ },
+
+ /** Add a menu option/item at the given index
+ */
+ addItem : function( item, index ){
+ // append to end if no index
+ index = ( index >= 0 )?( index ):( this.options.length );
+ this.options.splice( index, 0, item );
+ return this;
+ },
+
+ /** Remove a menu option/item at the given index
+ */
+ removeItem : function( index ){
+ if( index >=0 ){
+ this.options.splice( index, 1 );
+ }
+ return this;
+ },
+
+ /** Search for a menu option by it's html
+ */
+ findIndexByHtml : function( html ){
+ for( var i=0; i<this.options.length; i++ ){
+ if( ( _.has( this.options[i], 'html' ) )
+ && ( this.options[i].html === html ) ){
+ return i;
+ }
+ }
+ return null;
+ },
+
+ /** Search for a menu option by it's html
+ */
+ findItemByHtml : function( html ){
+ return this.options[( this.findIndexByHtml( html ) )];
+ },
+
+ /** String representation. */
+ toString : function(){
+ return 'PopupMenu';
+ }
+});
+PopupMenu.templates = {
+ menu : Handlebars.templates[ 'template-popupmenu-menu' ]
+};
+
+// -----------------------------------------------------------------------------
+// the following class functions are bridges from the original make_popupmenu and make_popup_menus
+// to the newer backbone.js PopupMenu
+
+/** Create a PopupMenu from simple map initial_options activated by clicking button_element.
+ * Converts initial_options to object array used by PopupMenu.
+ * @param {jQuery|DOMElement} button_element element which, when clicked, activates menu
+ * @param {Object} initial_options map of key -> values, where
+ * key is option text, value is fn to call when option is clicked
+ * @returns {PopupMenu} the PopupMenu created
+ */
+PopupMenu.make_popupmenu = function( button_element, initial_options ){
+ var convertedOptions = [];
+ _.each( initial_options, function( optionVal, optionKey ){
+ var newOption = { html: optionKey };
+
+ // keys with null values indicate: header
+ if( optionVal === null ){ // !optionVal? (null only?)
+ newOption.header = true;
+
+ // keys with function values indicate: a menu option
+ } else if( jQuery.type( optionVal ) === 'function' ){
+ newOption.func = optionVal;
+ }
+ //TODO:?? any other special optionVals?
+ // there was no divider option originally
+ convertedOptions.push( newOption );
+ });
+ return new PopupMenu( $( button_element ), convertedOptions );
+};
+
+/** Find all anchors in $parent (using selector) and covert anchors into a PopupMenu options map.
+ * @param {jQuery} $parent the element that contains the links to convert to options
+ * @param {String} selector jq selector string to find links
+ * @returns {Object[]} the options array to initialize a PopupMenu
+ */
+//TODO: lose parent and selector, pass in array of links, use map to return options
+PopupMenu.convertLinksToOptions = function( $parent, selector ){
+ $parent = $( $parent );
+ selector = selector || 'a';
+ var options = [];
+ $parent.find( selector ).each( function( elem, i ){
+ var option = {},
+ $link = $( elem );
+
+ // convert link text to the option text (html) and the href into the option func
+ option.html = $link.text();
+ if( linkHref ){
+ var linkHref = $link.attr( 'href' ),
+ linkTarget = $link.attr( 'target' ),
+ confirmText = $link.attr( 'confirm' );
+
+ option.func = function(){
+ // if there's a "confirm" attribute, throw up a confirmation dialog, and
+ // if the user cancels - do nothing
+ if( ( confirmText ) && ( !confirm( confirmText ) ) ){ return; }
+
+ // if there's no confirm attribute, or the user accepted the confirm dialog:
+ var f;
+ switch( linkTarget ){
+ // relocate the center panel
+ case '_parent':
+ window.parent.location = linkHref;
+ break;
+
+ // relocate the entire window
+ case '_top':
+ window.top.location = linkHref;
+ break;
+
+ // Http request target is a window named demolocal on the local box
+ //TODO: I still don't understand this option (where the hell does f get set? confirm?)
+ case 'demo':
+ if( f === undefined || f.closed ){
+ f = window.open( linkHref, linkTarget );
+ f.creator = self;
+ }
+ break;
+
+ // relocate this panel
+ default:
+ window.location = linkHref;
+ }
+ };
+ }
+ options.push( option );
+ });
+ return options;
+};
+
+/** Create a single popupmenu from existing DOM button and anchor elements
+ * @param {jQuery} $buttonElement the element that when clicked will open the menu
+ * @param {jQuery} $menuElement the element that contains the anchors to convert into a menu
+ * @param {String} menuElementLinkSelector jq selector string used to find anchors to be made into menu options
+ * @returns {PopupMenu} the PopupMenu (Backbone View) that can render, control the menu
+ */
+PopupMenu.fromExistingDom = function( $buttonElement, $menuElement, menuElementLinkSelector ){
+ $buttonElement = $( $buttonElement );
+ $menuElement = $( $menuElement );
+ var options = PopupMenu.convertLinksToOptions( $menuElement, menuElementLinkSelector );
+ // we're done with the menu (having converted it to an options map)
+ $menuElement.remove();
+ return new PopupMenu( $buttonElement, options );
+};
+
+/** Create all popupmenus within a document or a more specific element
+ * @param {DOMElement} parent the DOM element in which to search for popupmenus to build (defaults to document)
+ * @param {String} menuSelector jq selector string to find popupmenu menu elements (defaults to "div[popupmenu]")
+ * @param {Function} buttonSelectorBuildFn the function to build the jq button selector.
+ * Will be passed $menuElement, parent.
+ * (Defaults to return '#' + $menuElement.attr( 'popupmenu' ); )
+ * @returns {PopupMenu[]} array of popupmenus created
+ */
+PopupMenu.make_popup_menus = function( parent, menuSelector, buttonSelectorBuildFn ){
+ parent = parent || document;
+ // orig. Glx popupmenu menus have a (non-std) attribute 'popupmenu'
+ // which contains the id of the button that activates the menu
+ menuSelector = menuSelector || 'div[popupmenu]';
+ // default to (orig. Glx) matching button to menu by using the popupmenu attr of the menu as the id of the button
+ buttonSelectorBuildFn = buttonSelectorBuildFn || function( $menuElement, parent ){
+ return '#' + $menuElement.attr( 'popupmenu' );
+ };
+
+ // aggregate and return all PopupMenus
+ var popupMenusCreated = [];
+ $( parent ).find( menuSelector ).each( function(){
+ var $menuElement = $( this ),
+ $buttonElement = $( parent ).find( buttonSelectorBuildFn( $menuElement, parent ) );
+ popupMenusCreated.push( PopupMenu.fromDom( $buttonElement, $menuElement ) );
+ $buttonElement.addClass( 'popup' );
+ });
+ return popupMenusCreated;
+}
+
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/packed/mvc/base-mvc.js
--- a/static/scripts/packed/mvc/base-mvc.js
+++ b/static/scripts/packed/mvc/base-mvc.js
@@ -1,1 +1,1 @@
-var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){if(this.model.attributes.hidden){this.$el.hide()}else{this.$el.show()}}});var LoggableMixin={logger:null,log:function(){if(this.logger){return this.logger.log.apply(this.logger,arguments)}return undefined}};var GalaxyLocalization=jQuery.extend({},{ALIAS_NAME:"_l",localizedStrings:{},setLocalizedString:function(b,a){var c=this;var d=function(f,e){if(f!==e){c.localizedStrings[f]=e}};if(jQuery.type(b)==="string"){d(b,a)}else{if(jQuery.type(b)==="object"){jQuery.each(b,function(e,f){d(e,f)})}else{throw ("Localization.setLocalizedString needs either a string or object as the first argument, given: "+b)}}},localize:function(a){return this.localizedStrings[a]||a},toString:function(){return"GalaxyLocalization"}});window[GalaxyLocalization.ALIAS_NAME]=function(a){return GalaxyLocalization.localize(a)};var PersistantStorage=function(g,d){if(!g){throw ("PersistantStorage needs storageKey argument")}d=d||{};var b=jQuery.jStorage.get,c=jQuery.jStorage.set,a=jQuery.jStorage.deleteKey;function e(i,h){i=i||{};h=h||null;return{get:function(j){if(j===undefined){return i}else{if(i.hasOwnProperty(j)){return(jQuery.type(i[j])==="object")?(new e(i[j],this)):(i[j])}}return undefined},set:function(j,k){i[j]=k;this._save();return this},deleteKey:function(j){delete i[j];this._save();return this},_save:function(){return h._save()},toString:function(){return("StorageRecursionHelper("+i+")")}}}var f={};data=b(g);if(data===null){data=jQuery.extend(true,{},d);c(g,data)}f=new e(data);jQuery.extend(f,{_save:function(h){return c(g,f.get())},destroy:function(){return a(g)},toString:function(){return"PersistantStorage("+data+")"}});return f};
\ No newline at end of file
+var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){if(this.model.attributes.hidden){this.$el.hide()}else{this.$el.show()}}});var LoggableMixin={logger:null,log:function(){if(this.logger){return this.logger.log.apply(this.logger,arguments)}return undefined}};var GalaxyLocalization=jQuery.extend({},{ALIAS_NAME:"_l",localizedStrings:{},setLocalizedString:function(b,a){var c=this;var d=function(f,e){if(f!==e){c.localizedStrings[f]=e}};if(jQuery.type(b)==="string"){d(b,a)}else{if(jQuery.type(b)==="object"){jQuery.each(b,function(e,f){d(e,f)})}else{throw ("Localization.setLocalizedString needs either a string or object as the first argument, given: "+b)}}},localize:function(a){return this.localizedStrings[a]||a},toString:function(){return"GalaxyLocalization"}});window[GalaxyLocalization.ALIAS_NAME]=function(a){return GalaxyLocalization.localize(a)};var PersistantStorage=function(g,d){if(!g){throw ("PersistantStorage needs storageKey argument")}d=d||{};var b=jQuery.jStorage.get,c=jQuery.jStorage.set,a=jQuery.jStorage.deleteKey;function e(i,h){i=i||{};h=h||null;return{get:function(j){if(j===undefined){return i}else{if(i.hasOwnProperty(j)){return(jQuery.type(i[j])==="object")?(new e(i[j],this)):(i[j])}}return undefined},set:function(j,k){i[j]=k;this._save();return this},deleteKey:function(j){delete i[j];this._save();return this},_save:function(){return h._save()},toString:function(){return("StorageRecursionHelper("+i+")")}}}var f={};data=b(g);if(data===null){data=jQuery.extend(true,{},d);c(g,data)}f=new e(data);jQuery.extend(f,{_save:function(h){return c(g,f.get())},destroy:function(){return a(g)},toString:function(){return"PersistantStorage("+g+")"}});return f};
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-var HDABaseView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",this.render,this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"});this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((!this.model.inReadyState())||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("Display data in browser");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.expanded){a.show()}else{a.hide()}return a},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+".</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to unpause")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred running this job")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this,d=this.$el.find(".historyItemBody");a=(a===undefined)?(!d.is(":visible")):(a);if(a){d.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{d.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(){},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
+var HDABaseView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urlTemplates=a.urlTemplates;this.expanded=a.expanded||false;this.model.bind("change",this.render,this)},render:function(){var b=this,e=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+e),d=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+e);this.urls=this._renderUrls(this.urlTemplates,this.model.toJSON());a.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+c);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);make_popup_menus(a);a.find(".tooltip").tooltip({placement:"bottom"});this.$el.fadeOut("fast",function(){b.$el.children().remove();b.$el.append(a).fadeIn("fast",function(){b.log(b+" rendered:",b.$el);var f="rendered";if(d){f+=":initial"}else{if(b.model.inReadyState()){f+=":ready"}}b.trigger(f)})});return this},_renderUrls:function(d,a){var b=this,c={};_.each(d,function(e,f){if(_.isObject(e)){c[f]=b._renderUrls(e,a)}else{if(f==="meta_download"){c[f]=b._renderMetaDownloadUrls(e,a)}else{try{c[f]=_.template(e,a)}catch(g){throw (b+"._renderUrls error: "+g+"\n rendering:"+e+"\n with "+JSON.stringify(a))}}}});return c},_renderMetaDownloadUrls:function(b,a){return _.map(a.meta_files,function(c){return{url:_.template(b,{id:a.id,file_type:c.file_type}),file_type:c.file_type}})},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());return a},_render_displayButton:function(){if((!this.model.inReadyState())||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.displayButton=null;return null}var a={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){a.enabled=false;a.title=_l("Cannot display datasets removed from disk")}else{a.title=_l("Display data in browser");a.href=this.urls.display}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDABaseView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});return HDABaseView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var a=this,b=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var a=HDABaseView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDABaseView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body:function(){var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(this.model.get("state")){case HistoryDatasetAssociation.STATES.NEW:break;case HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(a);break;case HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(a);break;case HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(a);break;case HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(a);break;case HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(a);break;case HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryDatasetAssociation.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.expanded){a.show()}else{a.hide()}return a},_render_body_not_viewable:function(a){a.append($("<div>"+_l("You do not have permission to view dataset")+".</div>"))},_render_body_uploading:function(a){a.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(a){a.append($("<div>"+_l("Job is waiting to run")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(a){a.append($("<div>"+_l("Job is paused. Use the history menu to unpause")+".</div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(a){a.append("<div>"+_l("Job is currently running")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append((_l("An error occurred running this job")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(a){a.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(a){a.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(a){a.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(a){a.append($(HDABaseView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));a.append('<div class="clear"/>');a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(c,a){var b=this,d=this.$el.find(".historyItemBody");a=(a===undefined)?(!d.is(":visible")):(a);if(a){d.slideDown("fast",function(){b.trigger("body-expanded",b.model.get("id"))})}else{d.slideUp("fast",function(){b.trigger("body-collapsed",b.model.get("id"))})}},remove:function(){},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+a+")"}});HDABaseView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 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 @@
-var HistoryDatasetAssociation=BaseModel.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"(unnamed dataset)",state:"ok",data_type:null,file_size:0,file_ext:"",meta_files:[],misc_blurb:"",misc_info:"",deleted:false,purged:false,visible:false,accessible:true},urlRoot:"api/histories/",url:function(){return"api/histories/"+this.get("history_id")+"/contents/"+this.get("id")},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryDatasetAssociation.STATES.NOT_VIEWABLE)}this.on("change:state",function(b,a){this.log(this+" has changed state:",b,a);if(this.inReadyState()){this.trigger("state:ready",this.get("id"),a,this.previous("state"),b)}})},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isVisible:function(b,c){var a=true;if((!b)&&(this.get("deleted")||this.get("purged"))){a=false}if((!c)&&(!this.get("visible"))){a=false}return a},inReadyState:function(){var a=this.get("state");return((a===HistoryDatasetAssociation.STATES.NEW)||(a===HistoryDatasetAssociation.STATES.OK)||(a===HistoryDatasetAssociation.STATES.EMPTY)||(a===HistoryDatasetAssociation.STATES.FAILED_METADATA)||(a===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(a===HistoryDatasetAssociation.STATES.DISCARDED)||(a===HistoryDatasetAssociation.STATES.ERROR))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryDatasetAssociation("+a+")"}});HistoryDatasetAssociation.STATES={UPLOAD:"upload",QUEUED:"queued",PAUSED:"paused",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};var HDACollection=Backbone.Collection.extend(LoggableMixin).extend({model:HistoryDatasetAssociation,initialize:function(){},ids:function(){return this.map(function(a){return a.id})},hidToCollectionIndex:function(a){if(!a){return this.models.length}var d=this.models.length-1;for(var b=d;b>=0;b--){var c=this.at(b).get("hid");if(c==a){return b}if(c<a){return b+1}}return null},getVisible:function(a,b){return this.filter(function(c){return c.isVisible(a,b)})},getStateLists:function(){var a={};_.each(_.values(HistoryDatasetAssociation.STATES),function(b){a[b]=[]});this.each(function(b){a[b.get("state")].push(b.get("id"))});return a},running:function(){var a=[];this.each(function(b){if(!b.inReadyState()){a.push(b.get("id"))}});return a},update:function(a){this.log(this+"update:",a);if(!(a&&a.length)){return[]}var c=this,b=null;_.each(a,function(f,d){var e=c.get(f);if(e){e.fetch();b.push(e)}});return b},toString:function(){return("HDACollection()")}});
\ No newline at end of file
+var HistoryDatasetAssociation=BaseModel.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"(unnamed dataset)",state:"ok",data_type:null,file_size:0,file_ext:"",meta_files:[],misc_blurb:"",misc_info:"",deleted:false,purged:false,visible:false,accessible:true},urlRoot:"api/histories/",url:function(){return"api/histories/"+this.get("history_id")+"/contents/"+this.get("id")},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryDatasetAssociation.STATES.NOT_VIEWABLE)}this.on("change:state",function(b,a){this.log(this+" has changed state:",b,a);if(this.inReadyState()){this.trigger("state:ready",this.get("id"),a,this.previous("state"),b)}})},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isVisible:function(b,c){var a=true;if((!b)&&(this.get("deleted")||this.get("purged"))){a=false}if((!c)&&(!this.get("visible"))){a=false}return a},inReadyState:function(){var a=this.get("state");return((a===HistoryDatasetAssociation.STATES.OK)||(a===HistoryDatasetAssociation.STATES.EMPTY)||(a===HistoryDatasetAssociation.STATES.FAILED_METADATA)||(a===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(a===HistoryDatasetAssociation.STATES.DISCARDED)||(a===HistoryDatasetAssociation.STATES.ERROR))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryDatasetAssociation("+a+")"}});HistoryDatasetAssociation.STATES={UPLOAD:"upload",QUEUED:"queued",PAUSED:"paused",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};var HDACollection=Backbone.Collection.extend(LoggableMixin).extend({model:HistoryDatasetAssociation,initialize:function(){},ids:function(){return this.map(function(a){return a.id})},hidToCollectionIndex:function(a){if(!a){return this.models.length}var d=this.models.length-1;for(var b=d;b>=0;b--){var c=this.at(b).get("hid");if(c==a){return b}if(c<a){return b+1}}return null},getVisible:function(a,b){return this.filter(function(c){return c.isVisible(a,b)})},getStateLists:function(){var a={};_.each(_.values(HistoryDatasetAssociation.STATES),function(b){a[b]=[]});this.each(function(b){a[b.get("state")].push(b.get("id"))});return a},running:function(){var a=[];this.each(function(b){if(!b.inReadyState()){a.push(b.get("id"))}});return a},update:function(a){this.log(this+"update:",a);if(!(a&&a.length)){return[]}var c=this,b=null;_.each(a,function(f,d){var e=c.get(f);if(e){e.fetch();b.push(e)}});return b},toString:function(){return("HDACollection()")}});
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 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 @@
-var HistoryPanel=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags"},initialize:function(a){this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("change:state",function(c,d,b){if((c.inReadyState())&&(!c.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHda(c)}},this);this.hdaViews={};this.urls={}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log("this.storage:",this.storage.get());if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log("(init'd) this.storage:",this.storage.get())},add:function(a){this.render()},addAll:function(){this.render()},removeHda:function(a,c){var b=this.hdaViews[a.get("id")];b.$el.fadeOut("fast",function(){b.$el.remove();if(c){c()}});this.model.hdas.remove(a)},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render()},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render()},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(c){this.log(this+".loadAndDisplayTags",c);var d=this.$el.find("#history-tag-area"),b=d.find(".tag-elt");this.log("\t tagArea",d," tagElt",b);if(d.is(":hidden")){if(!jQuery.trim(b.html())){var a=this;$.ajax({url:a.urls.tag,error:function(){alert(_l("Tagging failed"))},success:function(e){b.html(e);b.find(".tooltip").tooltip();d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
+var HistoryPanel=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",HDAView:HDAEditView,events:{"click #history-tag":"loadAndDisplayTags"},initialize:function(a){if(a.logger){this.logger=this.model.logger=a.logger}this.log(this+".initialize:",a);if(!a.urlTemplates){throw (this+" needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw (this+" needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw (this+" needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this._setUpWebStorage(a.initiallyExpanded,a.show_deleted,a.show_hidden);this.model.bind("change:nice_size",this.updateHistoryDiskSize,this);this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("change:state",function(c,d,b){if((c.inReadyState())&&(!c.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHda(c)}},this);this.hdaViews={};this.urls={}},_setUpWebStorage:function(b,a,c){this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(b){this.storage.set("exandedHdas",b)}if((a===true)||(a===false)){this.storage.set("show_deleted",a)}if((c===true)||(c===false)){this.storage.set("show_hidden",c)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.log(this+" (init'd) storage:",this.storage.get())},add:function(a){this.render()},addAll:function(){this.render()},removeHda:function(a,c){var b=this.hdaViews[a.get("id")];b.$el.fadeOut("fast",function(){b.$el.remove();if(c){c()}});this.model.hdas.remove(a)},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON(),e=(this.$el.children().size()===0);a.urls=this._renderUrls(a);c.append(HistoryPanel.templates.historyPanel(a));c.find(".tooltip").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(f){b.$el.fadeOut("fast",function(){f()})});$(b).queue(d,function(f){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){f()})});$(b).queue(d,function(f){this.log(b+" rendered:",b.$el);b._setUpBehaviours();if(e){b.trigger("rendered:initial")}else{b.trigger("rendered")}f()});$(b).dequeue(d);return this},_renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},renderItems:function(b){this.hdaViews={};var a=this,c=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(c,function(f){var e=f.get("id"),d=a.storage.get("expandedHdas").get(e);a.hdaViews[e]=new a.HDAView({model:f,expanded:d,urlTemplates:a.hdaUrlTemplates,logger:a.logger});a._setUpHdaListeners(a.hdaViews[e]);b.prepend(a.hdaViews[e].render().$el)});return c.length},_setUpHdaListeners:function(b){var a=this;b.bind("body-expanded",function(c){a.storage.get("expandedHdas").set(c,true)});b.bind("body-collapsed",function(c){a.storage.get("expandedHdas").deleteKey(c)})},_setUpBehaviours:function(){if(!(this.model.get("user")&&this.model.get("user").email)){return}var a=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(a.is(":hidden")){a.slideDown("fast")}else{a.slideUp("fast")}return false});async_save_text("history-name-container","history-name",this.urls.rename,"new_name",18);async_save_text("history-annotation-container","history-annotation",this.urls.annotate,"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},showQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(a.is(":hidden")){a.slideDown("fast")}},hideQuotaMessage:function(){var a=this.$el.find("#quota-message-container");if(!a.is(":hidden")){a.slideUp("fast")}},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(a){a.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},loadAndDisplayTags:function(c){this.log(this+".loadAndDisplayTags",c);var d=this.$el.find("#history-tag-area"),b=d.find(".tag-elt");this.log("\t tagArea",d," tagElt",b);if(d.is(":hidden")){if(!jQuery.trim(b.html())){var a=this;$.ajax({url:a.urls.tag,error:function(){alert(_l("Tagging failed"))},success:function(e){b.html(e);b.find(".tooltip").tooltip();d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=this.model.get("name")||"";return"HistoryPanel("+a+")"}});HistoryPanel.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var PopupMenu=Backbone.View.extend({templates:{wrapper:(function(){var a=['<ul id="<%= id %>-menu" class="dropdown-menu">',"<% if( options.length ){ %>","<% for( var i=0; i<options.length; i++ ){ var option = options[ i ]; %>","<% if( option.divider ){ %>",'<li class="divider"></li>',"<% } else { %>","<% if( option.header ){ %>",'<li class="head"><a href=""javascript:void(0);"><%- option.html %></a></li>',"<% } else { %>","<li><a ",'href="<% print( ( option.href )?( option.href ):( "javascript:void(0);" ) ) %>" ','<% if( option.target ){ %>target="<%= option.target %>" <% } %>','class="popupmenu-option">','<% if( option.checked ){ %><span class="ficon ok"></span><% } %>',"<%- option.html %>","</a></li>","<% } %>","<% } %>","<% } %>","<% } else { %>","<li>No Options.</li>","<% } %>","</ul>"];return _.template(a.join(""))}())},initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this);if(!this.templates.wrapper){this.templates.wrapper=Handlebars.templates["template-popupmenu-wrapper"]}},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(PopupMenu.templates.menu({options:this.options,id:this.$button.attr("id")}));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width(),a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this,a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?(a):(this.options.length);this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if((_.has(this.options[a],"html"))&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.templates={menu:Handlebars.templates["template-popupmenu-menu"]};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/packed/templates/compiled/template-popupmenu-menu.js
--- /dev/null
+++ b/static/scripts/packed/templates/compiled/template-popupmenu-menu.js
@@ -0,0 +1,1 @@
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-popupmenu-menu"]=b(function(f,s,q,l,x){q=q||f.helpers;var r="",i,h,d="function",c=this.escapeExpression,p=this;function o(B,A){var y="",z;y+="\n ";z=B.options;z=q.each.call(B,z,{hash:{},inverse:p.noop,fn:p.program(2,n,A)});if(z||z===0){y+=z}y+="\n";return y}function n(B,A){var y="",z;y+="\n ";z=B.divider;z=q["if"].call(B,z,{hash:{},inverse:p.program(5,k,A),fn:p.program(3,m,A)});if(z||z===0){y+=z}y+="\n ";return y}function m(z,y){return'\n <li class="divider"></li>\n '}function k(B,A){var y="",z;y+="\n ";z=B.header;z=q["if"].call(B,z,{hash:{},inverse:p.program(8,g,A),fn:p.program(6,j,A)});if(z||z===0){y+=z}y+="\n ";return y}function j(C,B){var z="",A,y;z+='\n <li class="head"><a href=""javascript:void(0);">';y=q.html;if(y){A=y.call(C,{hash:{}})}else{A=C.html;A=typeof A===d?A():A}if(A||A===0){z+=A}z+="</a></li>\n ";return z}function g(C,B){var z="",A,y;z+="\n ";z+='\n <li><a href="';A=C.href;A=q["if"].call(C,A,{hash:{},inverse:p.program(11,w,B),fn:p.program(9,e,B)});if(A||A===0){z+=A}z+='"\n ';A=C.href;A=q["if"].call(C,A,{hash:{},inverse:p.noop,fn:p.program(13,v,B)});if(A||A===0){z+=A}z+=' class="popupmenu-option">\n ';A=C.checked;A=q["if"].call(C,A,{hash:{},inverse:p.noop,fn:p.program(15,u,B)});if(A||A===0){z+=A}z+="\n ";y=q.html;if(y){A=y.call(C,{hash:{}})}else{A=C.html;A=typeof A===d?A():A}if(A||A===0){z+=A}z+="\n </a></li>\n ";return z}function e(B,A){var z,y;y=q.href;if(y){z=y.call(B,{hash:{}})}else{z=B.href;z=typeof z===d?z():z}return c(z)}function w(z,y){return"javascript:void(0);"}function v(C,B){var z="",A,y;z+='target="';y=q.target;if(y){A=y.call(C,{hash:{}})}else{A=C.target;A=typeof A===d?A():A}z+=c(A)+'"';return z}function u(z,y){return'<span class="ficon ok"></span>'}function t(z,y){return"\n <li>No Options.</li>\n"}r+='<ul id="';h=q.id;if(h){i=h.call(s,{hash:{}})}else{i=s.id;i=typeof i===d?i():i}r+=c(i)+'-menu" class="dropdown-menu">\n';i=s.options;i=i==null||i===false?i:i.length;i=q["if"].call(s,i,{hash:{},inverse:p.program(17,t,x),fn:p.program(1,o,x)});if(i||i===0){r+=i}r+="\n</ul>";return r})})();
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/templates/compiled/template-popupmenu-menu.js
--- /dev/null
+++ b/static/scripts/templates/compiled/template-popupmenu-menu.js
@@ -0,0 +1,117 @@
+(function() {
+ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
+templates['template-popupmenu-menu'] = template(function (Handlebars,depth0,helpers,partials,data) {
+ helpers = helpers || Handlebars.helpers;
+ var buffer = "", stack1, foundHelper, functionType="function", escapeExpression=this.escapeExpression, self=this;
+
+function program1(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n ";
+ stack1 = depth0.options;
+ stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n";
+ return buffer;}
+function program2(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n ";
+ stack1 = depth0.divider;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(5, program5, data),fn:self.program(3, program3, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ return buffer;}
+function program3(depth0,data) {
+
+
+ return "\n <li class=\"divider\"></li>\n ";}
+
+function program5(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n ";
+ stack1 = depth0.header;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(8, program8, data),fn:self.program(6, program6, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ return buffer;}
+function program6(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n <li class=\"head\"><a href=\"\"javascript:void(0);\">";
+ foundHelper = helpers.html;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.html; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</a></li>\n ";
+ return buffer;}
+
+function program8(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n ";
+ buffer += "\n <li><a href=\"";
+ stack1 = depth0.href;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(11, program11, data),fn:self.program(9, program9, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\"\n ";
+ stack1 = depth0.href;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += " class=\"popupmenu-option\">\n ";
+ stack1 = depth0.checked;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(15, program15, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n ";
+ foundHelper = helpers.html;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.html; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </a></li>\n ";
+ return buffer;}
+function program9(depth0,data) {
+
+ var stack1, foundHelper;
+ foundHelper = helpers.href;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.href; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ return escapeExpression(stack1);}
+
+function program11(depth0,data) {
+
+
+ return "javascript:void(0);";}
+
+function program13(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "target=\"";
+ foundHelper = helpers.target;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.target; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\"";
+ return buffer;}
+
+function program15(depth0,data) {
+
+
+ return "<span class=\"ficon ok\"></span>";}
+
+function program17(depth0,data) {
+
+
+ return "\n <li>No Options.</li>\n";}
+
+ buffer += "<ul id=\"";
+ foundHelper = helpers.id;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "-menu\" class=\"dropdown-menu\">\n";
+ stack1 = depth0.options;
+ stack1 = stack1 == null || stack1 === false ? stack1 : stack1.length;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(17, program17, data),fn:self.program(1, program1, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n</ul>";
+ return buffer;});
+})();
\ No newline at end of file
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 static/scripts/templates/ui-templates.html
--- a/static/scripts/templates/ui-templates.html
+++ b/static/scripts/templates/ui-templates.html
@@ -1,4 +1,4 @@
-<script type="text/template" class="template-history" id="template-user-quotaMeter-quota">
+<script type="text/template" class="template-user" id="template-user-quotaMeter-quota"><div id="quota-meter" class="quota-meter progress"><div id="quota-meter-bar" class="quota-meter-bar bar" style="width: {{quota_percent}}%"></div>
{{! TODO: remove the hardcoded style }}
@@ -8,7 +8,7 @@
</div></script>
-<script type="text/template" class="template-history" id="template-user-quotaMeter-usage">
+<script type="text/template" class="template-user" id="template-user-quotaMeter-usage">
{{! TODO: remove the hardcoded styles }}
<div id="quota-meter" class="quota-meter" style="background-color: transparent"><div id="quota-meter-text" class="quota-meter-text" style="top: 6px; color: white">
@@ -16,3 +16,28 @@
</div></div></script>
+
+<script type="text/template" class="template-ui" id="template-popupmenu-menu">
+<ul id="{{ id }}-menu" class="dropdown-menu">
+{{#if options.length }}
+ {{#each options }}
+ {{#if divider }}
+ <li class="divider"></li>
+ {{else}}
+ {{#if header }}
+ <li class="head"><a href=""javascript:void(0);">{{{ html }}}</a></li>
+ {{else}}
+ {{!NOTE: changed from # to void fn }}
+ <li><a href="{{#if href }}{{ href }}{{else}}javascript:void(0);{{/if}}"
+ {{#if href }}target="{{ target }}"{{/if}} class="popupmenu-option">
+ {{#if checked }}<span class="ficon ok"></span>{{/if}}
+ {{{ html }}}
+ </a></li>
+ {{/if}}
+ {{/if}}
+ {{/each}}
+{{else}}
+ <li>No Options.</li>
+{{/if}}
+</ul>
+</script>
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 templates/base.mako
--- a/templates/base.mako
+++ b/templates/base.mako
@@ -31,11 +31,18 @@
"libs/jquery/jquery",
"libs/json2",
"libs/bootstrap",
- "galaxy.base",
"libs/underscore",
"libs/backbone/backbone",
"libs/backbone/backbone-relational",
"libs/handlebars.runtime",
+ "galaxy.base"
+ )}
+
+ ${h.templates(
+ "template-popupmenu-menu"
+ )}
+
+ ${h.js(
"mvc/ui"
)}
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -56,9 +56,17 @@
'libs/backbone/backbone',
'libs/backbone/backbone-relational',
'libs/handlebars.runtime',
- 'mvc/ui',
'galaxy.base'
)}
+
+ ${h.templates(
+ "template-popupmenu-menu"
+ )}
+
+ ${h.js(
+ "mvc/ui"
+ )}
+
<script type="text/javascript">
// console protection
window.console = window.console || {
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 templates/root/alternate_history.mako
--- a/templates/root/alternate_history.mako
+++ b/templates/root/alternate_history.mako
@@ -223,10 +223,12 @@
${h.js(
"libs/jquery/jstorage",
"libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging",
- "libs/json2",
+ ##"libs/json2",
##"libs/bootstrap",
- "libs/backbone/backbone-relational",
- "mvc/base-mvc", "mvc/ui"
+ ## I think we can remove some of these
+ ##"libs/backbone/backbone-relational",
+ "mvc/base-mvc",
+ ##"mvc/ui"
)}
${h.templates(
@@ -302,13 +304,9 @@
galaxyPageSetUp();
Galaxy.historyFrame = window;
+ var debugging = ( new PersistantStorage( '__history_panel' ).get( 'debugging' ) || false );
+
// ostensibly, this is the App
- //if( window.console && console.debug ){
- // //if( console.clear ){ console.clear(); }
- // console.pretty = function( o ){ $( '<pre/>' ).text( JSON.stringify( o, null, ' ' ) ).appendTo( 'body' ); }
- // top.storage = jQuery.jStorage
- //}
-
// LOAD INITIAL DATA IN THIS PAGE - since we're already sending it...
// ...use mako to 'bootstrap' the models
var user = ${ get_current_user() },
@@ -325,7 +323,7 @@
var historyPanel = new HistoryPanel({
model : new History( history, hdas ),
urlTemplates : galaxy_paths.attributes,
- //logger : console,
+ logger : ( debugging )?( console ):( null ),
// 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' ) },
show_hidden : ${ 'true' if show_hidden == True else ( 'null' if show_hidden == None else 'false' ) }
@@ -336,13 +334,17 @@
//historyPanel = new HistoryPanel({
// model: new History(),
// urlTemplates : galaxy_paths.attributes,
- // logger : console,
+ // logger : ( debugging )?( console ):( null ),
// // 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' ) },
// show_hidden : ${ 'true' if show_hidden == True else ( 'null' if show_hidden == None else 'false' ) }
//});
//historyPanel.model.loadFromApi( history.id );
+ // set it up to be accessible across iframes
+ //TODO:?? mem leak
+ top.Galaxy.currHistoryPanel = historyPanel;
+
// QUOTA METER is a cross-frame ui element (meter in masthead, over quota message in history)
// create it and join them here for now (via events)
@@ -352,6 +354,7 @@
//window.currUser.logger = console;
var quotaMeter = new UserQuotaMeter({
model : currUser,
+ //logger : ( debugging )?( console ):( null ),
el : $( top.document ).find( '.quota-meter-container' )
});
//quotaMeter.logger = console; window.quotaMeter = quotaMeter
@@ -373,9 +376,81 @@
quotaMeter.update()
}, quotaMeter );
- // set it up to be accessible across iframes
- //TODO:?? mem leak
- top.Galaxy.currHistoryPanel = historyPanel;
+
+ //ANOTHER cross-frame element is the history-options-button...
+ // in this case, we need to change the popupmenu options listed to include some functions for this history
+ // these include: current (1 & 2) 'show/hide' delete and hidden functions, and (3) the collapse all option
+ (function(){
+ // don't try this if the history panel is in it's own window
+ if( top.document === window.document ){
+ return;
+ }
+
+ // lots of wtf here...due to infernalframes
+ var $historyButtonWindow = $( top.document ),
+ HISTORY_MENU_BUTTON_ID = 'history-options-button',
+ $historyMenuButton = $historyButtonWindow.find( '#' + HISTORY_MENU_BUTTON_ID ),
+ // jq data in another frame can only be accessed by the jQuery in that frame,
+ // get the jQuery from the top frame (that contains the history-options-button)
+ START_INSERTING_AT_INDEX = 11,
+ COLLAPSE_OPTION_TEXT = _l("Collapse Expanded Datasets"),
+ DELETED_OPTION_TEXT = _l("Include Deleted Datasets"),
+ HIDDEN_OPTION_TEXT = _l("Include Hidden Datasets");
+ windowJQ = $( top )[0].jQuery,
+ popupMenu = ( windowJQ && $historyMenuButton[0] )?( windowJQ.data( $historyMenuButton[0], 'PopupMenu' ) )
+ :( null );
+
+ //console.debug(
+ // '$historyButtonWindow:', $historyButtonWindow,
+ // '$historyMenuButton:', $historyMenuButton,
+ // 'windowJQ:', windowJQ,
+ // 'popupmenu:', popupMenu
+ //);
+ if( !popupMenu ){ return; }
+
+ // since the history frame reloads so often (compared to the main window),
+ // we need to check whether these options are there already before we add them again
+ //NOTE: we use the global here because these remain bound in the main window even if panel refreshes
+ //TODO: too much boilerplate
+ if( popupMenu.findIndexByHtml( COLLAPSE_OPTION_TEXT ) === null ){
+ popupMenu.addItem({
+ html : COLLAPSE_OPTION_TEXT,
+ func : function() {
+ Galaxy.currHistoryPanel.collapseAllHdaBodies();
+ }
+ }, START_INSERTING_AT_INDEX )
+ }
+
+ var deletedOptionIndex = popupMenu.findIndexByHtml( DELETED_OPTION_TEXT );
+ if( deletedOptionIndex === null ){
+ popupMenu.addItem({
+ html : DELETED_OPTION_TEXT,
+ func : function( clickEvent, thisMenuOption ){
+ var show_deleted = Galaxy.currHistoryPanel.toggleShowDeleted();
+ thisMenuOption.checked = show_deleted;
+ }
+ }, START_INSERTING_AT_INDEX + 1 )
+ deletedOptionIndex = START_INSERTING_AT_INDEX + 1;
+ }
+ // whether was there or added, update the checked option to reflect the panel's settings on the panel render
+ popupMenu.options[ deletedOptionIndex ].checked = Galaxy.currHistoryPanel.storage.get( 'show_deleted' );
+
+ var hiddenOptionIndex = popupMenu.findIndexByHtml( HIDDEN_OPTION_TEXT );
+ if( hiddenOptionIndex === null ){
+ popupMenu.addItem({
+ html : HIDDEN_OPTION_TEXT,
+ func : function( clickEvent, thisMenuOption ){
+ var show_hidden = Galaxy.currHistoryPanel.toggleShowHidden();
+ thisMenuOption.checked = show_hidden;
+ }
+ }, START_INSERTING_AT_INDEX + 2 )
+ hiddenOptionIndex = START_INSERTING_AT_INDEX + 2;
+ }
+ // whether was there or added, update the checked option to reflect the panel's settings on the panel render
+ popupMenu.options[ hiddenOptionIndex ].checked = Galaxy.currHistoryPanel.storage.get( 'show_hidden' );
+ })();
+
+ //TODO: both the quota meter and the options-menu stuff need to be moved out when iframes are removed
return;
});
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 templates/root/index.mako
--- a/templates/root/index.mako
+++ b/templates/root/index.mako
@@ -10,7 +10,7 @@
$(function(){
// Init history options.
$("#history-options-button").css( "position", "relative" );
- make_popupmenu( $("#history-options-button"), {
+ var popupmenu = PopupMenu.make_popupmenu( $("#history-options-button"), {
"${_("History Lists")}": null,
"${_("Saved Histories")}": function() {
galaxy_main.location = "${h.url_for( controller='history', action='list')}";
@@ -40,18 +40,6 @@
"${_("Resume Paused Jobs")}": function() {
galaxy_history.location = "${h.url_for( controller='history', action='resume_paused_jobs', current=True)}";
},
- "${_("Collapse Expanded Datasets")}": function() {
- Galaxy.currHistoryPanel.collapseAllHdaBodies();
- //galaxy_history.location = "${h.url_for( controller='root', action='history', show_deleted=True)}";
- },
- "${_("Show/Hide Deleted Datasets")}": function() {
- Galaxy.currHistoryPanel.toggleShowDeleted();
- //galaxy_history.location = "${h.url_for( controller='root', action='history', show_deleted=True)}";
- },
- "${_("Show/Hide Hidden Datasets")}": function() {
- Galaxy.currHistoryPanel.toggleShowHidden();
- //galaxy_history.location = "${h.url_for( controller='root', action='history', show_hidden=True)}";
- },
"${_("Unhide Hidden Datasets")}": function() {
if ( confirm( "Really unhide all hidden datasets?" ) ) {
galaxy_main.location = "${h.url_for( controller='history', action='unhide_datasets', current=True )}";
@@ -83,7 +71,6 @@
galaxy_main.location = "${h.url_for( controller='history', action='import_archive' )}";
}
});
-
});
</script></%def>
diff -r 330f05e523aee275c91f3e5de1177f8eb832d512 -r 6d7e637883b7e0e4c72c08a1269ca422da087661 test/functional/test_history_functions.py
--- a/test/functional/test_history_functions.py
+++ b/test/functional/test_history_functions.py
@@ -14,11 +14,12 @@
name = 'anonymous'
self.new_history( name=name )
global anonymous_history
- anonymous_history = sa_session.query( galaxy.model.History ) \
- .filter( and_( galaxy.model.History.table.c.deleted==False,
- galaxy.model.History.table.c.name==name ) ) \
- .order_by( desc( galaxy.model.History.table.c.create_time ) ) \
- .first()
+ anonymous_history = (
+ sa_session.query( galaxy.model.History )
+ .filter( and_( galaxy.model.History.table.c.deleted==False, galaxy.model.History.table.c.name==name ) )
+ .order_by( desc( galaxy.model.History.table.c.create_time ) )
+ .first()
+ )
assert anonymous_history is not None, "Problem retrieving anonymous_history from database"
# Upload a dataset to anonymous_history so it will be set as the current history after login
self.upload_file( '1.bed', dbkey='hg18' )
@@ -235,27 +236,35 @@
# Check list of histories to make sure shared history3 was cloned
strings_displayed=[ "Clone of '%s' shared by '%s'" % ( history3.name, admin_user.email ) ]
self.view_stored_active_histories( strings_displayed=strings_displayed )
+
def test_035_clone_current_history( self ):
"""Testing cloning the current history"""
# logged in as regular_user1
self.logout()
self.login( email=admin_user.email )
+
# Current history should be history3, add more datasets to history3, then delete them so we can
# test cloning activatable datasets as well as only the active datasets
self.upload_file( '2.bed', dbkey='hg18' )
- hda_2_bed = sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
- .filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history3.id,
- galaxy.model.HistoryDatasetAssociation.table.c.name=='2.bed' ) ) \
- .first()
+ hda_2_bed = (
+ sa_session.query( galaxy.model.HistoryDatasetAssociation )
+ .filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history3.id,
+ galaxy.model.HistoryDatasetAssociation.table.c.name=='2.bed' ) )
+ .first()
+ )
assert hda_2_bed is not None, "Problem retrieving hda_2_bed from database"
self.delete_history_item( str( hda_2_bed.id ) )
+
self.upload_file( '3.bed', dbkey='hg18' )
- hda_3_bed = sa_session.query( galaxy.model.HistoryDatasetAssociation ) \
- .filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history3.id,
- galaxy.model.HistoryDatasetAssociation.table.c.name=='3.bed' ) ) \
- .first()
+ hda_3_bed = (
+ sa_session.query( galaxy.model.HistoryDatasetAssociation )
+ .filter( and_( galaxy.model.HistoryDatasetAssociation.table.c.history_id==history3.id,
+ galaxy.model.HistoryDatasetAssociation.table.c.name=='3.bed' ) )
+ .first()
+ )
assert hda_3_bed is not None, "Problem retrieving hda_3_bed from database"
self.delete_history_item( str( hda_3_bed.id ) )
+
# Test cloning activatable datasets
self.clone_history( self.security.encode_id( history3.id ),
'activatable',
@@ -267,6 +276,7 @@
.order_by( desc( galaxy.model.History.table.c.create_time ) ) \
.first()
assert history3_clone2 is not None, "Problem retrieving history3_clone2 from database"
+
# Check list of histories to make sure shared history3 was cloned
self.view_stored_active_histories( strings_displayed=[ "Clone of '%s'" % history3.name ] )
# Switch to the cloned history to make sure activatable datasets were cloned
@@ -307,6 +317,7 @@
raise AssertionError, "Deleted datasets incorrectly included in cloned history history3_clone3"
except:
pass
+
def test_040_sharing_mulitple_histories_with_multiple_users( self ):
"""Testing sharing multiple histories containing only public datasets with multiple users"""
# Logged in as admin_user
https://bitbucket.org/galaxy/galaxy-central/changeset/cba8dbdb8312/
changeset: cba8dbdb8312
user: carlfeberhard
date: 2012-12-07 20:00:51
summary: clean up; pack
affected #: 3 files
diff -r 6d7e637883b7e0e4c72c08a1269ca422da087661 -r cba8dbdb8312dcfa93e0be299fb560c067266064 static/scripts/mvc/history/history-model.js
--- a/static/scripts/mvc/history/history-model.js
+++ b/static/scripts/mvc/history/history-model.js
@@ -66,7 +66,6 @@
//});
//this.bind( 'all', function( event ){
// //this.log( this + '', arguments );
- // console.info( this + '', arguments );
//});
},
diff -r 6d7e637883b7e0e4c72c08a1269ca422da087661 -r cba8dbdb8312dcfa93e0be299fb560c067266064 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -190,7 +190,6 @@
// default settings
this.$button = $button || $( '<div/>' );
this.options = options || [];
- //console.debug( this + '.initialize, button:', $button, ', options:', options );
// set up button click -> open menu behavior
var menu = this;
@@ -230,7 +229,6 @@
// sets menu div id to '{{ id }}-menu'
id : this.$button.attr( 'id' )
}));
- //console.debug( this.$el, ':', this.$el.html() );
// set up behavior on each link/anchor elem
if( this.options.length ){
@@ -239,7 +237,6 @@
$anchor = $li.children( 'a.popupmenu-option' ),
menuFunc = menu.options[ i ].func;
- //console.debug( 'setting up behavior:', i, menu.options[ i ], $li, $anchor );
if( $anchor.length && menuFunc ){
$anchor.click( function( event ){
menuFunc( event, menu.options[ i ] );
diff -r 6d7e637883b7e0e4c72c08a1269ca422da087661 -r cba8dbdb8312dcfa93e0be299fb560c067266064 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var PopupMenu=Backbone.View.extend({templates:{wrapper:(function(){var a=['<ul id="<%= id %>-menu" class="dropdown-menu">',"<% if( options.length ){ %>","<% for( var i=0; i<options.length; i++ ){ var option = options[ i ]; %>","<% if( option.divider ){ %>",'<li class="divider"></li>',"<% } else { %>","<% if( option.header ){ %>",'<li class="head"><a href=""javascript:void(0);"><%- option.html %></a></li>',"<% } else { %>","<li><a ",'href="<% print( ( option.href )?( option.href ):( "javascript:void(0);" ) ) %>" ','<% if( option.target ){ %>target="<%= option.target %>" <% } %>','class="popupmenu-option">','<% if( option.checked ){ %><span class="ficon ok"></span><% } %>',"<%- option.html %>","</a></li>","<% } %>","<% } %>","<% } %>","<% } else { %>","<li>No Options.</li>","<% } %>","</ul>"];return _.template(a.join(""))}())},initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this);if(!this.templates.wrapper){this.templates.wrapper=Handlebars.templates["template-popupmenu-wrapper"]}},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(PopupMenu.templates.menu({options:this.options,id:this.$button.attr("id")}));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width(),a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this,a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?(a):(this.options.length);this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if((_.has(this.options[a],"html"))&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.templates={menu:Handlebars.templates["template-popupmenu-menu"]};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b||$("<div/>");this.options=a||[];var c=this;this.$button.click(function(d){c._renderAndShow(d);return false});this.$button.data("PopupMenu",this);if(!this.templates.wrapper){this.templates.wrapper=Handlebars.templates["template-popupmenu-wrapper"]}},render:function(){var a=this;this.$el.addClass("popmenu-wrapper").css({position:"absolute",display:"none"});this.$el.html(PopupMenu.templates.menu({options:this.options,id:this.$button.attr("id")}));if(this.options.length){this.$el.find("li").each(function(c,b){var f=$(b),e=f.children("a.popupmenu-option"),d=a.options[c].func;if(e.length&&d){e.click(function(g){d(g,a.options[c])})}a.options[c].$li=f})}return this},_getShownPosition:function(b){var c=this.$el.width(),a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_renderAndShow:function(a){this.render();this.$el.appendTo("body");this.$el.css(this._getShownPosition(a));this._setUpCloseBehavior();this.$el.show()},_setUpCloseBehavior:function(){var b=this,a=function(c){c.bind("click.close_popup",function(){b.remove();c.unbind("click.close_popup")})};a($(window.document));a($(window.top.document));_.each(window.top.frames,function(c){a($(c.document))})},addItem:function(b,a){a=(a>=0)?(a):(this.options.length);this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if((_.has(this.options[a],"html"))&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.templates={menu:Handlebars.templates["template-popupmenu-menu"]};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(j){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}var i;switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;case"demo":if(i===undefined||i.closed){i=window.open(j,k);i.creator=self}break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};
\ 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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/d50bf81b0966/
changeset: d50bf81b0966
user: inithello
date: 2012-12-07 18:04:42
summary: Generate new metadata when repository dependencies have been added or removed.
affected #: 1 file
diff -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb -r d50bf81b096669ae82b614b94a606be773943445 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -504,6 +504,35 @@
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
reset_tool_data_tables( trans.app )
return repository, tool, message
+def new_repository_dependency_metadata_required( trans, repository, metadata_dict ):
+ """
+ Compare the last saved metadata for each repository dependency in the repository with the new
+ metadata in metadata_dict to determine if a new repository_metadata table record is required,
+ or if the last saved metadata record can be updated instead.
+ """
+ if 'repository_dependencies' in metadata_dict:
+ repository_metadata = get_latest_repository_metadata( trans, repository.id )
+ if repository_metadata:
+ metadata = repository_metadata.metadata
+ if metadata and 'repository_dependencies' in metadata:
+ saved_repository_dependencies = metadata[ 'repository_dependencies' ][ 'repository_dependencies' ]
+ new_repository_dependencies = metadata_dict[ 'repository_dependencies' ][ 'repository_dependencies' ]
+ # The saved metadata must be a subset of the new metadata.
+ for new_repository_dependency_metadata in new_repository_dependencies:
+ if new_repository_dependency_metadata not in saved_repository_dependencies:
+ return True
+ for saved_repository_dependency_metadata in saved_repository_dependencies:
+ if saved_repository_dependency_metadata not in new_repository_dependencies:
+ return True
+ else:
+ # We have repository metadata that does not include metadata for any repository dependencies in the
+ # repository, so we can update the existing repository metadata.
+ return False
+ else:
+ # There is no saved repository metadata, so we need to create a new repository_metadata table record.
+ return True
+ # The received metadata_dict includes no metadata for repository dependencies, so a new repository_metadata table record is not needed.
+ return False
def new_tool_metadata_required( trans, repository, metadata_dict ):
"""
Compare the last saved metadata for each tool in the repository with the new metadata in metadata_dict to determine if a new repository_metadata
@@ -579,7 +608,9 @@
if metadata_dict:
downloadable = is_downloadable( metadata_dict )
repository_metadata = None
- if new_tool_metadata_required( trans, repository, metadata_dict ) or new_workflow_metadata_required( trans, repository, metadata_dict ):
+ if new_repository_dependency_metadata_required( trans, repository, metadata_dict ) or \
+ new_tool_metadata_required( trans, repository, metadata_dict ) or \
+ new_workflow_metadata_required( trans, repository, metadata_dict ):
# Create a new repository_metadata table row.
repository_metadata = create_or_update_repository_metadata( trans,
encoded_id,
https://bitbucket.org/galaxy/galaxy-central/changeset/330f05e523ae/
changeset: 330f05e523ae
user: inithello
date: 2012-12-07 18:05:43
summary: Tool shed functional tests for repository dependency features. Cleaned up import *s.
affected #: 9 files
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/base/common.py
--- a/test/tool_shed/base/common.py
+++ b/test/tool_shed/base/common.py
@@ -9,7 +9,7 @@
test_user_1_name = 'user1'
new_repository_dependencies_xml = '''<?xml version="1.0"?>
-<repositories>
+<repositories${description}><repository toolshed="${toolshed_url}" name="${repository_name}" owner="${owner}" changeset_revision="${changeset_revision}" /></repositories>
'''
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/base/twilltestcase.py
--- a/test/tool_shed/base/twilltestcase.py
+++ b/test/tool_shed/base/twilltestcase.py
@@ -1,8 +1,7 @@
-from base.twilltestcase import *
-from galaxy.webapps.community.util.hgweb_config import *
-from test_db_util import *
-from common import *
-import string
+import galaxy.webapps.community.util.hgweb_config
+import common, string, os
+from base.twilltestcase import tc, from_json_string, TwillTestCase, security
+from test_db_util import get_repository_metadata_by_repository_id_changeset_revision
from galaxy import eggs
eggs.require('mercurial')
@@ -14,7 +13,7 @@
self.security = security.SecurityHelper( id_secret='changethisinproductiontoo' )
self.history_id = None
self.hgweb_config_dir = os.environ.get( 'TEST_HG_WEB_CONFIG_DIR' )
- self.hgweb_config_manager = HgWebConfigManager()
+ self.hgweb_config_manager = galaxy.webapps.community.util.hgweb_config.HgWebConfigManager()
self.hgweb_config_manager.hgweb_config_dir = self.hgweb_config_dir
self.host = os.environ.get( 'TOOL_SHED_TEST_HOST' )
self.port = os.environ.get( 'TOOL_SHED_TEST_PORT' )
@@ -138,8 +137,12 @@
tc.fv( "1", "selected_files_to_delete", ','.join( files_to_delete ) )
tc.submit( 'select_files_to_delete_button' )
self.check_for_strings( strings_displayed, strings_not_displayed )
- def display_manage_repository_page( self, repository, strings_displayed=[], strings_not_displayed=[] ):
- url = '/repository/manage_repository?id=%s' % self.security.encode_id( repository.id )
+ def display_manage_repository_page( self, repository, changeset_revision=None, strings_displayed=[], strings_not_displayed=[] ):
+ base_url = '/repository/manage_repository?id=%s' % self.security.encode_id( repository.id )
+ if changeset_revision is not None:
+ url = '%s&changeset_revision=%s' % ( base_url, changeset_revision )
+ else:
+ url = base_url
self.visit_url( url )
self.check_for_strings( strings_displayed, strings_not_displayed )
def display_repository_clone_page( self, owner_name, repository_name, strings_displayed=[], strings_not_displayed=[] ):
@@ -209,14 +212,19 @@
else:
string = string.replace( character, replacement )
return string
- def generate_repository_dependency_xml( self, repository, xml_filename ):
+ def generate_repository_dependency_xml( self, repository, xml_filename, dependency_description='' ):
changeset_revision = self.get_repository_tip( repository )
- template_parser = string.Template( new_repository_dependencies_xml )
+ if dependency_description:
+ description = ' description="%s"' % dependency_description
+ else:
+ description = dependency_description
+ template_parser = string.Template( common.new_repository_dependencies_xml )
repository_dependency_xml = template_parser.safe_substitute( toolshed_url=self.url,
owner=repository.user.username,
repository_name=repository.name,
- changeset_revision=changeset_revision )
- # Save the generated xml to test-data/emboss_5/repository_dependencies.xml.
+ changeset_revision=changeset_revision,
+ description=description )
+ # Save the generated xml to the specified location.
file( xml_filename, 'w' ).write( repository_dependency_xml )
def get_latest_repository_metadata_for_repository( self, repository ):
# TODO: This will not work as expected. Fix it.
@@ -293,6 +301,13 @@
( self.security.encode_id( repository.id ), tool_xml_path, changeset_revision )
self.visit_url( url )
self.check_for_strings( strings_displayed, strings_not_displayed )
+ def repository_is_new( self, repository ):
+ repo = hg.repository( ui.ui(), self.get_repo_path( repository ) )
+ tip_ctx = repo.changectx( repo.changelog.tip() )
+ return tip_ctx.rev() < 0
+ def reset_repository_metadata( self, repository ):
+ url = '/repository/reset_all_metadata?id=%s' % self.security.encode_id( repository.id )
+ self.visit_url( url )
def revoke_write_access( self, repository, username ):
url = '/repository/manage_repository?user_access_button=Remove&id=%s&remove_auth=%s' % \
( self.security.encode_id( repository.id ), username )
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/functional/test_0000_basic_repository_features.py
--- a/test/tool_shed/functional/test_0000_basic_repository_features.py
+++ b/test/tool_shed/functional/test_0000_basic_repository_features.py
@@ -1,5 +1,5 @@
-from tool_shed.base.twilltestcase import *
-from tool_shed.base.test_db_util import *
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+from tool_shed.base.test_db_util import get_repository_by_name_and_owner, get_user, get_private_role
repository_name = 'filtering'
repository_description = "Galaxy's filtering tool"
@@ -9,14 +9,14 @@
def test_0000_initiate_users( self ):
"""Create necessary user accounts and login as an admin user."""
- self.login( email=test_user_1_email, username=test_user_1_name )
- test_user_1 = get_user( test_user_1_email )
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = get_user( common.test_user_1_email )
assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % test_user_1_email
test_user_1_private_role = get_private_role( test_user_1 )
self.logout()
- self.login( email=admin_email, username=admin_username )
- admin_user = get_user( admin_email )
- assert admin_user is not None, 'Problem retrieving user with email %s from the database' % admin_email
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
admin_user_private_role = get_private_role( admin_user )
def test_0005_create_categories( self ):
"""Create categories"""
@@ -33,27 +33,27 @@
strings_displayed=strings_displayed )
def test_0015_edit_repository( self ):
"""Edit the repository name, description, and long description"""
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
new_name = "renamed_filtering"
new_description = "Edited filtering tool"
new_long_description = "Edited long description"
self.edit_repository_information( repository, repo_name=new_name, description=new_description, long_description=new_long_description )
def test_0020_change_repository_category( self ):
"""Change the categories associated with the filtering repository"""
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.edit_repository_categories( repository, categories_to_add=[ "Text Analysis" ], categories_to_remove=[ "Text Manipulation" ] )
def test_0025_grant_write_access( self ):
'''Grant write access to another user'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
- self.grant_write_access( repository, usernames=[ test_user_1_name ] )
- self.revoke_write_access( repository, test_user_1_name )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
+ self.grant_write_access( repository, usernames=[ common.test_user_1_name ] )
+ self.revoke_write_access( repository, common.test_user_1_name )
def test_0030_upload_filtering_1_1_0( self ):
"""Upload filtering_1.1.0.tar to the repository"""
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository, 'filtering/filtering_1.1.0.tar', commit_message="Uploaded filtering 1.1.0" )
def test_0035_verify_repository( self ):
'''Display basic repository pages'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
latest_changeset_revision = self.get_repository_tip( repository )
self.check_for_valid_tools( repository, strings_displayed=[ 'Filter1' ] )
self.check_count_of_metadata_revisions_associated_with_repository( repository, metadata_count=1 )
@@ -61,12 +61,12 @@
self.check_repository_tools_for_changeset_revision( repository, tip )
self.check_repository_metadata( repository, tip_only=False )
self.browse_repository( repository, strings_displayed=[ 'Browse %s revision' % repository.name, '(repository tip)' ] )
- self.display_repository_clone_page( admin_username,
+ self.display_repository_clone_page( common.admin_username,
repository_name,
strings_displayed=[ 'Uploaded filtering 1.1.0', latest_changeset_revision ] )
def test_0040_alter_repository_states( self ):
'''Test toggling the malicious and deprecated repository flags.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.set_repository_malicious( repository, set_malicious=True, strings_displayed=[ 'The repository tip has been defined as malicious.' ] )
self.set_repository_malicious( repository,
set_malicious=False,
@@ -82,7 +82,7 @@
set_deprecated=False )
def test_0045_display_repository_tip_file( self ):
'''Display the contents of filtering.xml in the repository tip revision'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.display_repository_file_contents( repository=repository,
filename='filtering.xml',
filepath=None,
@@ -90,7 +90,7 @@
strings_not_displayed=[] )
def test_0050_upload_filtering_txt_file( self ):
'''Upload filtering.txt file associated with tool version 1.1.0.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
'filtering/filtering.txt',
commit_message="Uploaded filtering.txt",
@@ -99,7 +99,7 @@
self.display_manage_repository_page( repository, strings_displayed=[ 'Readme file for filtering 1.1.0' ] )
def test_0055_upload_filtering_test_data( self ):
'''Upload filtering test data.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository, 'filtering/filtering_test_data.tar', commit_message="Uploaded filtering test data", remove_repo_files_not_in_tar='No' )
self.display_repository_file_contents( repository=repository,
filename='1.bed',
@@ -109,14 +109,14 @@
self.check_repository_metadata( repository, tip_only=True )
def test_0060_upload_filtering_2_2_0( self ):
'''Upload filtering version 2.2.0'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
'filtering/filtering_2.2.0.tar',
commit_message="Uploaded filtering 2.2.0",
remove_repo_files_not_in_tar='No' )
def test_0065_verify_filtering_repository( self ):
'''Verify the new tool versions and repository metadata.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
tip = self.get_repository_tip( repository )
self.check_for_valid_tools( repository )
strings_displayed = self.get_repository_metadata_revisions( repository ).append( 'Select a revision' )
@@ -126,7 +126,7 @@
self.check_repository_metadata( repository, tip_only=False )
def test_0070_upload_readme_txt_file( self ):
'''Upload readme.txt file associated with tool version 2.2.0.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository, 'readme.txt', commit_message="Uploaded readme.txt" )
self.display_manage_repository_page( repository, strings_displayed=[ 'This is a readme file.' ] )
# Verify that there is a different readme file for each metadata revision.
@@ -134,13 +134,13 @@
self.display_manage_repository_page( repository, strings_displayed=[ 'Readme file for filtering 1.1.0', 'This is a readme file.' ] )
def test_0075_delete_readme_txt_file( self ):
'''Delete the readme.txt file.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.delete_files_from_repository( repository, filenames=[ 'readme.txt' ] )
self.check_count_of_metadata_revisions_associated_with_repository( repository, metadata_count=2 )
self.display_manage_repository_page( repository, strings_displayed=[ 'Readme file for filtering 1.1.0' ] )
def test_0080_search_for_valid_filter_tool( self ):
'''Search for the filtering tool by tool ID, name, and version.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
tip_changeset = self.get_repository_tip( repository )
search_fields = dict( tool_id='Filter1', tool_name='filter', tool_version='2.2.0' )
self.search_for_valid_tools( search_fields=search_fields, strings_displayed=[ tip_changeset ], strings_not_displayed=[] )
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/functional/test_0010_repository_with_tool_dependencies.py
--- a/test/tool_shed/functional/test_0010_repository_with_tool_dependencies.py
+++ b/test/tool_shed/functional/test_0010_repository_with_tool_dependencies.py
@@ -1,5 +1,5 @@
-from tool_shed.base.twilltestcase import *
-from tool_shed.base.test_db_util import *
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+from tool_shed.base.test_db_util import get_repository_by_name_and_owner, get_user, get_private_role
repository_name = 'freebayes'
repository_description = "Galaxy's freebayes tool"
@@ -10,8 +10,8 @@
def test_0000_create_or_login_admin_user( self ):
"""Create necessary user accounts and login as an admin user."""
self.logout()
- self.login( email=admin_email, username=admin_username )
- admin_user = get_user( admin_email )
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = get_user( common.admin_email )
assert admin_user is not None, 'Problem retrieving user with email %s from the database' % admin_email
admin_user_private_role = get_private_role( admin_user )
def test_0005_create_category( self ):
@@ -24,7 +24,7 @@
repository_long_description=repository_long_description,
categories=[ 'SNP Analysis' ],
strings_displayed=[] )
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
'freebayes/freebayes.xml',
valid_tools_only=False,
@@ -37,7 +37,7 @@
strings_displayed=[ 'requires an entry', 'tool_data_table_conf.xml' ] )
def test_0015_upload_missing_tool_data_table_conf_file( self ):
'''Upload the missing tool_data_table_conf.xml.sample file to the repository.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
'freebayes/tool_data_table_conf.xml.sample',
valid_tools_only=False,
@@ -50,27 +50,27 @@
strings_displayed=[ 'refers to a file', 'sam_fa_indices.loc' ] )
def test_0020_upload_missing_sample_loc_file( self ):
'''Upload the missing sam_fa_indices.loc.sample file to the repository.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
'freebayes/sam_fa_indices.loc.sample',
strings_displayed=[],
commit_message='Uploaded tool data table .loc file.' )
def test_0025_upload_invalid_tool_dependency_xml( self ):
'''Upload tool_dependencies.xml defining version 0.9.5 of the freebayes package.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
os.path.join( 'freebayes', 'invalid_tool_dependencies', 'tool_dependencies.xml' ),
strings_displayed=[ 'Name, version and type from a tool requirement tag does not match' ],
commit_message='Uploaded invalid tool dependency XML.' )
def test_0030_upload_valid_tool_dependency_xml( self ):
'''Upload tool_dependencies.xml defining version 0.9.4_9696d0ce8a962f7bb61c4791be5ce44312b81cf8 of the freebayes package.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.upload_file( repository,
os.path.join( 'freebayes', 'tool_dependencies.xml' ),
commit_message='Uploaded valid tool dependency XML.' )
def test_0035_verify_tool_dependencies( self ):
'''Verify that the uploaded tool_dependencies.xml specifies the correct package versions.'''
- repository = get_repository_by_name_and_owner( repository_name, admin_username )
+ repository = get_repository_by_name_and_owner( repository_name, common.admin_username )
self.display_manage_repository_page( repository,
strings_displayed=[ 'freebayes', '0.9.4_9696d0ce8a9', 'samtools', '0.1.18', 'Valid tools' ],
strings_not_displayed=[ 'Invalid tools' ] )
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/functional/test_0020_basic_repository_dependencies.py
--- a/test/tool_shed/functional/test_0020_basic_repository_dependencies.py
+++ b/test/tool_shed/functional/test_0020_basic_repository_dependencies.py
@@ -1,11 +1,11 @@
-from tool_shed.base.twilltestcase import *
-from tool_shed.base.test_db_util import *
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+from tool_shed.base.test_db_util import get_repository_by_name_and_owner, get_user, get_private_role
datatypes_repository_name = 'emboss_datatypes'
datatypes_repository_description = "Galaxy applicable data formats used by Emboss tools."
datatypes_repository_long_description = "Galaxy applicable data formats used by Emboss tools. This repository contains no tools."
-emboss_repository_name = 'emboss_5'
+emboss_repository_name = 'emboss_0020'
emboss_repository_description = 'Galaxy wrappers for Emboss version 5.0.0 tools'
emboss_repository_long_description = 'Galaxy wrappers for Emboss version 5.0.0 tools'
@@ -14,56 +14,56 @@
def test_0000_initiate_users( self ):
"""Create necessary user accounts and login as an admin user."""
self.logout()
- self.login( email=admin_email, username=admin_username )
- admin_user = get_user( admin_email )
- assert admin_user is not None, 'Problem retrieving user with email %s from the database' % admin_email
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % common.admin_email
admin_user_private_role = get_private_role( admin_user )
self.logout()
- self.login( email=test_user_1_email, username=test_user_1_name )
- test_user_1 = get_user( test_user_1_email )
- assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % regular_email
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = get_user( common.test_user_1_email )
+ assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % common.test_user_1_email
test_user_1_private_role = get_private_role( test_user_1 )
def test_0005_create_category( self ):
"""Create Sequence Analysis category"""
self.logout()
- self.login( email=admin_email, username=admin_username )
+ self.login( email=common.admin_email, username=common.admin_username )
self.create_category( 'Sequence Analysis', 'Tools for performing Protein and DNA/RNA analysis' )
def test_0010_create_emboss_datatypes_repository_and_upload_tarball( self ):
'''Create and populate the emboss_datatypes repository.'''
self.logout()
- self.login( email=test_user_1_email, username=test_user_1_name )
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
self.create_repository( datatypes_repository_name,
datatypes_repository_description,
repository_long_description=datatypes_repository_long_description,
categories=[ 'Sequence Analysis' ],
strings_displayed=[] )
- repository = get_repository_by_name_and_owner( datatypes_repository_name, test_user_1_name )
+ repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
self.upload_file( repository, 'emboss/datatypes/datatypes_conf.xml', commit_message='Uploaded datatypes_conf.xml.' )
def test_0015_verify_datatypes_in_datatypes_repository( self ):
'''Verify that the emboss_datatypes repository contains datatype entries.'''
- repository = get_repository_by_name_and_owner( datatypes_repository_name, test_user_1_name )
+ repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
self.display_manage_repository_page( repository, strings_displayed=[ 'Datatypes', 'equicktandem', 'hennig86', 'vectorstrip' ] )
def test_0020_create_emboss_5_repository_and_upload_files( self ):
- '''Create and populate the emboss_5 repository.'''
+ '''Create and populate the emboss_5_0020 repository.'''
self.create_repository( emboss_repository_name,
emboss_repository_description,
repository_long_description=emboss_repository_long_description,
categories=[ 'Text Manipulation' ],
strings_displayed=[] )
- repository = get_repository_by_name_and_owner( emboss_repository_name, test_user_1_name )
- self.upload_file( repository, 'emboss/5/emboss.tar', commit_message='Uploaded emboss_5.tar' )
+ repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ self.upload_file( repository, 'emboss/emboss.tar', commit_message='Uploaded emboss_5.tar' )
def test_0025_generate_and_upload_repository_dependencies_xml( self ):
'''Generate and upload the repository_dependencies.xml file'''
- repository = get_repository_by_name_and_owner( emboss_repository_name, test_user_1_name )
- datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, test_user_1_name )
+ repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
self.generate_repository_dependency_xml( datatypes_repository, self.get_filename( 'emboss/5/repository_dependencies.xml' ) )
self.upload_file( repository, 'emboss/5/repository_dependencies.xml', commit_message='Uploaded repository_dependencies.xml' )
def test_0030_verify_emboss_5_repository_dependency_on_emboss_datatypes( self ):
'''Verify that the emboss_5 repository now depends on the emboss_datatypes repository with correct name, owner, and changeset revision.'''
- repository = get_repository_by_name_and_owner( emboss_repository_name, test_user_1_name )
- datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, test_user_1_name )
+ repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
changeset_revision = self.get_repository_tip( datatypes_repository )
- strings_displayed = [ datatypes_repository_name, test_user_1_name, changeset_revision, 'Repository dependencies' ]
+ strings_displayed = [ datatypes_repository_name, common.test_user_1_name, changeset_revision, 'Repository dependencies' ]
self.display_manage_repository_page( repository, strings_displayed=strings_displayed )
def test_0035_cleanup( self ):
'''Clean up generated test data.'''
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/functional/test_0030_repository_dependency_revisions.py
--- /dev/null
+++ b/test/tool_shed/functional/test_0030_repository_dependency_revisions.py
@@ -0,0 +1,134 @@
+from tool_shed.base.twilltestcase import ShedTwillTestCase, common, os
+from tool_shed.base.test_db_util import get_repository_by_name_and_owner, get_user, get_private_role
+
+datatypes_repository_name = 'emboss_datatypes'
+datatypes_repository_description = "Galaxy applicable data formats used by Emboss tools."
+datatypes_repository_long_description = "Galaxy applicable data formats used by Emboss tools. This repository contains no tools."
+
+emboss_repository_name = 'emboss'
+emboss_5_repository_name = 'emboss_5_0030'
+emboss_6_repository_name = 'emboss_6_0030'
+emboss_repository_description = 'Galaxy wrappers for Emboss version 5.0.0 tools'
+emboss_repository_long_description = 'Galaxy wrappers for Emboss version 5.0.0 tools'
+
+class TestRepositoryDependencyRevisions( ShedTwillTestCase ):
+ '''Test dependencies on different revisions of a repository.'''
+ '''
+ create repository emboss_5_0030
+ create repository emboss_6_0030
+ create repository emboss_datatypes if necessary
+ create repository emboss
+ emboss_5 has repository_dependency.xml file that defines emboss_datatypes
+ emboss_6 has repository_dependency.xml file that defines emboss_datatypes
+ get information to create repository dependency imformation for emboss
+ emboss depends on emboss_5
+ then emboss depends on emboss_6
+ verify per-changeset dependencies
+ '''
+ def test_0000_initiate_users( self ):
+ """Create necessary user accounts."""
+ self.logout()
+ self.login( email=common.admin_email, username=common.admin_username )
+ admin_user = get_user( common.admin_email )
+ assert admin_user is not None, 'Problem retrieving user with email %s from the database' % admin_email
+ admin_user_private_role = get_private_role( admin_user )
+ self.logout()
+ self.login( email=common.test_user_1_email, username=common.test_user_1_name )
+ test_user_1 = get_user( common.test_user_1_email )
+ assert test_user_1 is not None, 'Problem retrieving user with email %s from the database' % regular_email
+ test_user_1_private_role = get_private_role( test_user_1 )
+ def test_0005_create_repositories( self ):
+ '''Create the emboss_5_0030, emboss_6_0030, emboss_datatypes, and emboss repositories and populate the emboss_datatypes repository.'''
+ emboss_5_repository = get_repository_by_name_and_owner( emboss_5_repository_name, common.test_user_1_name )
+ if emboss_5_repository is None:
+ self.create_repository( emboss_5_repository_name,
+ emboss_repository_description,
+ repository_long_description=emboss_repository_long_description,
+ categories=[ 'Sequence Analysis' ],
+ strings_displayed=[] )
+ emboss_5_repository = get_repository_by_name_and_owner( emboss_5_repository_name, common.test_user_1_name )
+ self.upload_file( emboss_5_repository, 'emboss/emboss.tar', commit_message='Uploaded tool tarball.' )
+ emboss_6_repository = get_repository_by_name_and_owner( emboss_6_repository_name, common.test_user_1_name )
+ if emboss_6_repository is None:
+ self.create_repository( emboss_6_repository_name,
+ emboss_repository_description,
+ repository_long_description=emboss_repository_long_description,
+ categories=[ 'Sequence Analysis' ],
+ strings_displayed=[] )
+ emboss_6_repository = get_repository_by_name_and_owner( emboss_6_repository_name, common.test_user_1_name )
+ self.upload_file( emboss_6_repository, 'emboss/emboss.tar', commit_message='Uploaded tool tarball..' )
+ datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
+ if datatypes_repository is None:
+ self.create_repository( datatypes_repository_name,
+ datatypes_repository_description,
+ repository_long_description=datatypes_repository_long_description,
+ categories=[ 'Sequence Analysis' ],
+ strings_displayed=[] )
+ datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
+ if self.repository_is_new( datatypes_repository ):
+ self.upload_file( datatypes_repository, 'emboss/datatypes/datatypes_conf.xml', commit_message='Uploaded datatypes_conf.xml.' )
+ emboss_repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ if emboss_repository is None:
+ self.create_repository( emboss_repository_name,
+ emboss_repository_description,
+ repository_long_description=emboss_repository_long_description,
+ categories=[ 'Sequence Analysis' ],
+ strings_displayed=[] )
+ emboss_repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ self.upload_file( emboss_5_repository, 'emboss/emboss.tar', commit_message='Uploaded tool tarball.' )
+ def test_0010_generate_repository_dependencies_for_emboss_5( self ):
+ '''Generate a repository_dependencies.xml file specifying emboss_datatypes and upload it to the emboss_5 repository.'''
+ datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
+ self.generate_repository_dependency_xml( datatypes_repository, self.get_filename( 'emboss/repository_dependencies.xml' ) )
+ emboss_5_repository = get_repository_by_name_and_owner( emboss_5_repository_name, common.test_user_1_name )
+ self.upload_file( emboss_5_repository, 'emboss/repository_dependencies.xml', commit_message='Uploaded repository_depepndencies.xml.' )
+ def test_0015_generate_repository_dependencies_for_emboss_6( self ):
+ '''Generate a repository_dependencies.xml file specifying emboss_datatypes and upload it to the emboss_6 repository.'''
+ emboss_6_repository = get_repository_by_name_and_owner( emboss_6_repository_name, common.test_user_1_name )
+ self.upload_file( emboss_6_repository, 'emboss/repository_dependencies.xml', commit_message='Uploaded repository_depepndencies.xml.' )
+ def test_0020_generate_repository_dependency_on_emboss_5( self ):
+ '''Create and upload repository_dependencies.xml for the emboss_5_0030 repository.'''
+ emboss_repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ emboss_5_repository = get_repository_by_name_and_owner( emboss_5_repository_name, common.test_user_1_name )
+ self.generate_repository_dependency_xml( emboss_5_repository,
+ self.get_filename( 'emboss/5/repository_dependencies.xml' ),
+ dependency_description='Emboss requires the Emboss 5 repository.' )
+ self.upload_file( emboss_repository,
+ 'emboss/5/repository_dependencies.xml',
+ commit_message='Uploaded dependency configuration specifying emboss_5' )
+ def test_0025_generate_repository_dependency_on_emboss_6( self ):
+ '''Create and upload repository_dependencies.xml for the emboss_6_0030 repository.'''
+ emboss_repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ emboss_6_repository = get_repository_by_name_and_owner( emboss_6_repository_name, common.test_user_1_name )
+ self.generate_repository_dependency_xml( emboss_6_repository,
+ self.get_filename( 'emboss/6/repository_dependencies.xml' ),
+ dependency_description='Emboss requires the Emboss 6 repository.' )
+ self.upload_file( emboss_repository,
+ 'emboss/6/repository_dependencies.xml',
+ commit_message='Uploaded dependency configuration specifying emboss_6' )
+ def test_0030_verify_repository_dependency_revisions( self ):
+ '''Verify that different metadata revisions of the emboss repository have different repository dependencies.'''
+ repository = get_repository_by_name_and_owner( emboss_repository_name, common.test_user_1_name )
+ # Reset emboss metadata to pick up the repository dependency changes.
+# self.reset_repository_metadata( repository )
+ repository_metadata = [ ( metadata.metadata, metadata.changeset_revision ) for metadata in self.get_repository_metadata( repository ) ]
+ datatypes_repository = get_repository_by_name_and_owner( datatypes_repository_name, common.test_user_1_name )
+ datatypes_tip = self.get_repository_tip( datatypes_repository )
+ # Iterate through all metadata revisions and check for repository dependencies.
+ for metadata, changeset_revision in repository_metadata:
+ repository_dependency_metadata = metadata[ 'repository_dependencies' ][ 'repository_dependencies' ][ 0 ]
+ # Remove the tool shed URL, because that's not displayed on the page (yet?)
+ repository_dependency_metadata.pop( repository_dependency_metadata.index( self.url ) )
+ # Add the dependency description and datatypes repository details to the strings to check.
+ repository_dependency_metadata.extend( [ metadata[ 'repository_dependencies' ][ 'description' ],
+ datatypes_repository_name,
+ datatypes_repository.user.username,
+ datatypes_tip ] )
+ self.display_manage_repository_page( repository,
+ changeset_revision=changeset_revision,
+ strings_displayed=[ str( metadata ) for metadata in repository_dependency_metadata ] )
+ def test_0035_cleanup( self ):
+ '''Clean up generated repository dependency XML files.'''
+ for filename in [ 'emboss/5/repository_dependencies.xml', 'emboss/6/repository_dependencies.xml', 'emboss/repository_dependencies.xml' ]:
+ if os.path.exists( self.get_filename( filename ) ):
+ os.remove( self.get_filename( filename ) )
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/test_data/emboss/5/emboss.tar
Binary file test/tool_shed/test_data/emboss/5/emboss.tar has changed
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/test_data/emboss/6/emboss.tar
Binary file test/tool_shed/test_data/emboss/6/emboss.tar has changed
diff -r d50bf81b096669ae82b614b94a606be773943445 -r 330f05e523aee275c91f3e5de1177f8eb832d512 test/tool_shed/test_data/emboss/emboss.tar
Binary file test/tool_shed/test_data/emboss/emboss.tar has changed
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
07 Dec '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/0b3db8ce29d6/
changeset: 0b3db8ce29d6
user: jgoecks
date: 2012-12-07 17:46:03
summary: Visualization framework enhancements: (a) refactor orphan vars and functions into mixins; (b) remove overly-qualified model references; (c) add support for multiple data types, gracefully falling back if a converter is not available; and (d) add bigwig as an index datatype for BAM.
affected #: 6 files
diff -r 6591b6ebfb4ea56118941deef03855412c2c00fd -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -239,7 +239,7 @@
except:
return "Binary bam alignments file (%s)" % ( data.nice_size( dataset.get_size() ) )
def get_track_type( self ):
- return "ReadTrack", {"data": "bai", "index": "summary_tree"}
+ return "ReadTrack", { "data": "bai", "index": [ "bigwig", "summary_tree" ] }
Binary.register_sniffable_binary_format("bam", "bam", Bam)
diff -r 6591b6ebfb4ea56118941deef03855412c2c00fd -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -872,6 +872,16 @@
PAUSED = 'paused',
SETTING_METADATA = 'setting_metadata',
FAILED_METADATA = 'failed_metadata' )
+
+ conversion_messages = Bunch( PENDING = "pending",
+ NO_DATA = "no data",
+ NO_CHROMOSOME = "no chromosome",
+ NO_CONVERTER = "no converter",
+ NO_TOOL = "no tool",
+ DATA = "data",
+ ERROR = "error",
+ OK = "ok" )
+
permitted_actions = get_permitted_actions( filter='DATASET' )
file_path = "/tmp/"
object_store = None # This get initialized in mapping.py (method init) by app.py
@@ -996,6 +1006,7 @@
class DatasetInstance( object ):
"""A base class for all 'dataset instances', HDAs, LDAs, etc"""
states = Dataset.states
+ conversion_messages = Dataset.conversion_messages
permitted_actions = Dataset.permitted_actions
def __init__( self, id=None, hid=None, name=None, info=None, blurb=None, peek=None, tool_version=None, extension=None,
dbkey=None, metadata=None, history=None, dataset=None, deleted=False, designation=None,
@@ -1170,9 +1181,9 @@
if dep_dataset is None:
# None means converter is running first time
return None
- elif dep_dataset.state == trans.app.model.Job.states.ERROR:
+ elif dep_dataset.state == Job.states.ERROR:
raise ConverterDependencyException("A dependency (%s) was in an error state." % dependency)
- elif dep_dataset.state != trans.app.model.Job.states.OK:
+ elif dep_dataset.state != Job.states.OK:
# Pending
return None
deps[dependency] = dep_dataset
@@ -1196,12 +1207,11 @@
for name, value in self.metadata.items():
# HACK: MetadataFile objects do not have a type/ext, so need to use metadata name
# to determine type.
- if dataset_ext == 'bai' and name == 'bam_index' and isinstance( value, trans.app.model.MetadataFile ):
+ if dataset_ext == 'bai' and name == 'bam_index' and isinstance( value, MetadataFile ):
# HACK: MetadataFile objects cannot be used by tools, so return
# a fake HDA that points to metadata file.
- fake_dataset = trans.app.model.Dataset( state=trans.app.model.Dataset.states.OK,
- external_filename=value.file_name )
- fake_hda = trans.app.model.HistoryDatasetAssociation( dataset=fake_dataset )
+ fake_dataset = Dataset( state=Dataset.states.OK, external_filename=value.file_name )
+ fake_hda = HistoryDatasetAssociation( dataset=fake_dataset )
return fake_hda
def clear_associated_files( self, metadata_safe = False, purge = False ):
raise 'Unimplemented'
@@ -1311,16 +1321,26 @@
track_type, data_sources = self.datatype.get_track_type()
data_sources_dict = {}
msg = None
- for source_type, data_source in data_sources.iteritems():
+ for source_type, source_list in data_sources.iteritems():
+ data_source = None
if source_type == "data_standalone":
# Nothing to do.
msg = None
+ data_source = source_list
else:
# Convert.
- msg = self.convert_dataset( trans, data_source )
+ if isinstance( source_list, str ):
+ source_list = [ source_list ]
+
+ # Loop through sources until viable one is found.
+ for source in source_list:
+ msg = self.convert_dataset( trans, source )
+ if msg == self.conversion_messages.PENDING:
+ data_source = source
+ break
# Store msg.
- data_sources_dict[ source_type ] = { "name" : data_source, "message": msg }
+ data_sources_dict[ source_type ] = { "name": data_source, "message": msg }
return data_sources_dict
@@ -1331,35 +1351,23 @@
was converted successfully.
"""
- # FIXME: copied from controller.py
- messages = Bunch(
- PENDING = "pending",
- NO_DATA = "no data",
- NO_CHROMOSOME = "no chromosome",
- NO_CONVERTER = "no converter",
- NO_TOOL = "no tool",
- DATA = "data",
- ERROR = "error",
- OK = "ok"
- )
-
# Get converted dataset; this will start the conversion if necessary.
try:
converted_dataset = self.get_converted_dataset( trans, target_type )
except NoConverterException:
- return messages.NO_CONVERTER
+ return self.conversion_messages.NO_CONVERTER
except ConverterDependencyException, dep_error:
- return { 'kind': messages.ERROR, 'message': dep_error.value }
+ return { 'kind': self.conversion_messages.ERROR, 'message': dep_error.value }
# Check dataset state and return any messages.
msg = None
- if converted_dataset and converted_dataset.state == trans.app.model.Dataset.states.ERROR:
- job_id = trans.sa_session.query( trans.app.model.JobToOutputDatasetAssociation ) \
+ if converted_dataset and converted_dataset.state == Dataset.states.ERROR:
+ job_id = trans.sa_session.query( JobToOutputDatasetAssociation ) \
.filter_by( dataset_id=converted_dataset.id ).first().job_id
- job = trans.sa_session.query( trans.app.model.Job ).get( job_id )
- msg = { 'kind': messages.ERROR, 'message': job.stderr }
- elif not converted_dataset or converted_dataset.state != trans.app.model.Dataset.states.OK:
- msg = messages.PENDING
+ job = trans.sa_session.query( Job ).get( job_id )
+ msg = { 'kind': self.conversion_messages.ERROR, 'message': job.stderr }
+ elif not converted_dataset or converted_dataset.state != Dataset.states.OK:
+ msg = self.conversion_messages.PENDING
return msg
@@ -2414,7 +2422,7 @@
elif not trans.app.config.smtp_server:
comments = "Email notification failed as SMTP server not set in config file"
if comments:
- event = trans.app.model.RequestEvent( self, self.state, comments )
+ event = RequestEvent( self, self.state, comments )
trans.sa_session.add( event )
trans.sa_session.flush()
return comments
diff -r 6591b6ebfb4ea56118941deef03855412c2c00fd -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb lib/galaxy/visualization/data_providers/registry.py
--- a/lib/galaxy/visualization/data_providers/registry.py
+++ b/lib/galaxy/visualization/data_providers/registry.py
@@ -1,6 +1,9 @@
from galaxy.visualization.data_providers.basic import ColumnDataProvider
-from galaxy.visualization.data_providers.genome import *
+from galaxy.visualization.data_providers import genome
+from galaxy.model import NoConverterException
from galaxy.visualization.data_providers.phyloviz import PhylovizDataProvider
+from galaxy.datatypes.tabular import Tabular, Vcf
+from galaxy.datatypes.interval import Interval, ENCODEPeak, ChromatinInteractions, Gtf, Gff, Bed
from galaxy.datatypes.xml import Phyloxml
from galaxy.datatypes.data import Newick, Nexus
@@ -15,20 +18,20 @@
# is original dataset type.
self.dataset_type_name_to_data_provider = {
"tabix": {
- Vcf: VcfTabixDataProvider,
- Bed: BedTabixDataProvider,
- Gtf: GtfTabixDataProvider,
- ENCODEPeak: ENCODEPeakTabixDataProvider,
- Interval: IntervalTabixDataProvider,
- ChromatinInteractions: ChromatinInteractionsTabixDataProvider,
- "default" : TabixDataProvider
+ Vcf: genome.VcfTabixDataProvider,
+ Bed: genome.BedTabixDataProvider,
+ Gtf: genome.GtfTabixDataProvider,
+ ENCODEPeak: genome.ENCODEPeakTabixDataProvider,
+ Interval: genome.IntervalTabixDataProvider,
+ ChromatinInteractions: genome.ChromatinInteractionsTabixDataProvider,
+ "default" : genome.TabixDataProvider
},
- "interval_index": IntervalIndexDataProvider,
- "bai": BamDataProvider,
- "bam": SamDataProvider,
- "summary_tree": SummaryTreeDataProvider,
- "bigwig": BigWigDataProvider,
- "bigbed": BigBedDataProvider
+ "interval_index": genome.IntervalIndexDataProvider,
+ "bai": genome.BamDataProvider,
+ "bam": genome.SamDataProvider,
+ "summary_tree": genome.SummaryTreeDataProvider,
+ "bigwig": genome.BigWigDataProvider,
+ "bigbed": genome.BigBedDataProvider
}
def get_data_provider( self, trans, name=None, source='data', raw=False, original_dataset=None ):
@@ -41,15 +44,15 @@
if raw:
# Working with raw data.
if isinstance( original_dataset.datatype, Gff ):
- data_provider_class = RawGFFDataProvider
+ data_provider_class = genome.RawGFFDataProvider
elif isinstance( original_dataset.datatype, Bed ):
- data_provider_class = RawBedDataProvider
+ data_provider_class = genome.RawBedDataProvider
elif isinstance( original_dataset.datatype, Vcf ):
- data_provider_class = RawVcfDataProvider
+ data_provider_class = genome.RawVcfDataProvider
elif isinstance( original_dataset.datatype, Tabular ):
- data_provider_class = ColumnDataProvider
+ data_provider_class = genome.ColumnDataProvider
elif isinstance( original_dataset.datatype, ( Nexus, Newick, Phyloxml ) ):
- data_provider_class = PhylovizDataProvider
+ data_provider_class = genome.PhylovizDataProvider
data_provider = data_provider_class( original_dataset=original_dataset )
@@ -87,10 +90,20 @@
# Get data provider mapping and data provider.
_ , data_provider_mapping = original_dataset.datatype.get_track_type()
if 'data_standalone' in data_provider_mapping:
- data_provider_name = data_provider_mapping[ 'data_standalone' ]
+ data_provider = self.get_data_provider( trans,
+ name=data_provider_mapping[ 'data_standalone' ],
+ original_dataset=original_dataset )
else:
- data_provider_name = data_provider_mapping[ source ]
-
- data_provider = self.get_data_provider( trans, name=data_provider_name, original_dataset=original_dataset )
+ source_list = data_provider_mapping[ source ]
+ if isinstance( source_list, str ):
+ source_list = [ source_list ]
+
+ # Find a valid data provider in the source list.
+ for source in source_list:
+ try:
+ data_provider = self.get_data_provider( trans, name=source, original_dataset=original_dataset )
+ break
+ except NoConverterException:
+ pass
return data_provider
\ No newline at end of file
diff -r 6591b6ebfb4ea56118941deef03855412c2c00fd -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -190,37 +190,6 @@
# -- Mixins for working with Galaxy objects. --
#
-# Message strings returned to browser
-messages = Bunch(
- PENDING = "pending",
- NO_DATA = "no data",
- NO_CHROMOSOME = "no chromosome",
- NO_CONVERTER = "no converter",
- NO_TOOL = "no tool",
- DATA = "data",
- ERROR = "error",
- OK = "ok"
-)
-
-def get_highest_priority_msg( message_list ):
- """
- Returns highest priority message from a list of messages.
- """
- return_message = None
-
- # For now, priority is: job error (dict), no converter, pending.
- for message in message_list:
- if message is not None:
- if isinstance(message, dict):
- return_message = message
- break
- elif message == messages.NO_CONVERTER:
- return_message = message
- elif return_message == None and message == messages.PENDING:
- return_message = message
- return return_message
-
-
class SharableItemSecurityMixin:
""" Mixin for handling security for sharable items. """
def security_check( self, trans, item, check_ownership=False, check_accessible=False ):
@@ -313,11 +282,11 @@
Returns a message if dataset is not ready to be used in visualization.
"""
if not dataset:
- return messages.NO_DATA
+ return dataset.conversion_messages.NO_DATA
if dataset.state == trans.app.model.Job.states.ERROR:
- return messages.ERROR
+ return dataset.conversion_messages.ERROR
if dataset.state != trans.app.model.Job.states.OK:
- return messages.PENDING
+ return dataset.conversion_messages.PENDING
return None
@@ -624,7 +593,7 @@
# If there are no messages (messages indicate data is not ready/available), get data.
messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
- message = get_highest_priority_msg( messages_list )
+ message = self._get_highest_priority_msg( messages_list )
if message:
rval = message
else:
@@ -646,6 +615,27 @@
return rval
+ # FIXME: this method probably belongs down in the model.Dataset class.
+ def _get_highest_priority_msg( self, message_list ):
+ """
+ Returns highest priority message from a list of messages.
+ """
+ return_message = None
+
+ # For now, priority is: job error (dict), no converter, pending.
+ for message in message_list:
+ if message is not None:
+ if isinstance(message, dict):
+ return_message = message
+ break
+ elif message == "no converter":
+ return_message = message
+ elif return_message == None and message == "pending":
+ return_message = message
+ return return_message
+
+
+
class UsesStoredWorkflowMixin( SharableItemSecurityMixin ):
""" Mixin for controllers that use StoredWorkflow objects. """
def get_stored_workflow( self, trans, id, check_ownership=True, check_accessible=False ):
diff -r 6591b6ebfb4ea56118941deef03855412c2c00fd -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb lib/galaxy/webapps/galaxy/api/datasets.py
--- a/lib/galaxy/webapps/galaxy/api/datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/datasets.py
@@ -4,7 +4,7 @@
import logging, os, string, shutil, urllib, re, socket
from galaxy import util, datatypes, jobs, web, util
from galaxy.visualization.data_providers.genome import FeatureLocationIndexDataProvider
-from galaxy.web.base.controller import BaseAPIController, UsesVisualizationMixin, get_highest_priority_msg, messages
+from galaxy.web.base.controller import BaseAPIController, UsesVisualizationMixin
from galaxy.web.framework.helpers import is_true
log = logging.getLogger( __name__ )
@@ -64,7 +64,7 @@
msg = self.check_dataset_state( trans, dataset )
if not msg:
- msg = messages.DATA
+ msg = dataset.conversion_messages.DATA
return msg
@@ -80,7 +80,7 @@
# Get datasources and check for messages (which indicate errors). Retry if flag is set.
data_sources = dataset.get_datasources( trans )
messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
- msg = get_highest_priority_msg( messages_list )
+ msg = self._get_highest_priority_msg( messages_list )
if msg:
if retry:
# Clear datasources and then try again.
@@ -92,12 +92,12 @@
# If there is a chrom, check for data on the chrom.
if chrom:
data_provider_registry = trans.app.data_provider_registry
- data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset= dataset, source='index' )
+ data_provider = trans.app.data_provider_registry.get_data_provider( trans, original_dataset=dataset, source='index' )
if not data_provider.has_data( chrom ):
- return messages.NO_DATA
+ return dataset.conversion_messages.NO_DATA
# Have data if we get here
- return { "status": messages.DATA, "valid_chroms": None }
+ return { "status": dataset.conversion_messages.DATA, "valid_chroms": None }
def _search_features( self, trans, dataset, query ):
"""
@@ -121,17 +121,17 @@
# Parameter check.
if not chrom:
- return messages.NO_DATA
+ return dataset.conversion_messages.NO_DATA
# Dataset check.
msg = self.check_dataset_state( trans, dataset )
if msg:
return msg
- # Get datasources and check for messages.
+ # Get datasources and check for essages.
data_sources = dataset.get_datasources( trans )
messages_list = [ data_source_dict[ 'message' ] for data_source_dict in data_sources.values() ]
- return_message = get_highest_priority_msg( messages_list )
+ return_message = self._get_highest_priority_msg( messages_list )
if return_message:
return return_message
diff -r 6591b6ebfb4ea56118941deef03855412c2c00fd -r 0b3db8ce29d68bf7fe8e2a37699f58c2d9fdbddb lib/galaxy/webapps/galaxy/api/tools.py
--- a/lib/galaxy/webapps/galaxy/api/tools.py
+++ b/lib/galaxy/webapps/galaxy/api/tools.py
@@ -1,5 +1,5 @@
from galaxy import web, util
-from galaxy.web.base.controller import BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesVisualizationMixin, messages, get_highest_priority_msg
+from galaxy.web.base.controller import BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesVisualizationMixin
from galaxy.visualization.genome.visual_analytics import get_dataset_job
from galaxy.visualization.genomes import GenomeRegion
from galaxy.util.json import to_json_string, from_json_string
@@ -57,7 +57,7 @@
tool_id = payload[ 'tool_id' ]
tool = trans.app.toolbox.get_tool( tool_id )
if not tool:
- return { "message": { "type": "error", "text" : messages.NO_TOOL } }
+ return { "message": { "type": "error", "text" : trans.app.model.Dataset.conversion_messages.NO_TOOL } }
# Set running history from payload parameters.
# History not set correctly as part of this API call for
@@ -123,7 +123,7 @@
#
tool = trans.app.toolbox.get_tool( tool_id )
if not tool:
- return messages.NO_TOOL
+ return trans.app.model.Dataset.conversion_messages.NO_TOOL
# HACK: add run button so that tool.handle_input will run tool.
kwargs['runtool_btn'] = 'Execute'
@@ -199,7 +199,7 @@
original_job = get_dataset_job( original_dataset )
tool = trans.app.toolbox.get_tool( original_job.tool_id )
if not tool:
- return messages.NO_TOOL
+ return trans.app.model.Dataset.conversion_messages.NO_TOOL
tool_params = dict( [ ( p.name, p.value ) for p in original_job.parameters ] )
# TODO: rather than set new inputs using dict of json'ed value, unpack parameters and set using set_param_value below.
@@ -226,7 +226,7 @@
messages_list.append( msg )
# Return any messages generated during conversions.
- return_message = get_highest_priority_msg( messages_list )
+ return_message = self._get_highest_priority_msg( messages_list )
if return_message:
return to_json_string( return_message )
@@ -290,7 +290,7 @@
break
if not success:
- return messages.ERROR
+ return trans.app.model.Dataset.conversion_messages.ERROR
#
# Set input datasets for tool. If running on regions, extract and use subset
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
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/6591b6ebfb4e/
changeset: 6591b6ebfb4e
user: jgoecks
date: 2012-12-07 16:33:39
summary: Converter enhancements: (a) add bam to bigwig converter; (b) update datatypes.conf.sample to include new converter (disabled by default and documented with requirements) and remove unneeded dependency for bam to summary tree converter; and (c) remove deprecated page tags from bedgraph to bigwig converter.
affected #: 3 files
diff -r 8305907fa2312da14cf4d500fba1675a169b5517 -r 6591b6ebfb4ea56118941deef03855412c2c00fd datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -7,7 +7,12 @@
<datatype extension="fli" type="galaxy.datatypes.tabular:FeatureLocationIndex" display_in_upload="false"/><datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true"><converter file="bam_to_bai.xml" target_datatype="bai"/>
- <converter file="bam_to_summary_tree_converter.xml" target_datatype="summary_tree" depends_on="bai"/>
+ <converter file="bam_to_summary_tree_converter.xml" target_datatype="summary_tree"/>
+ <!--
+ Caution: (a) this converter requires bedtools to be installed and (b) it is very memory intensive and
+ is not recommended for most laptops/desktops.
+ <converter file="bam_to_bigwig_converter.xml" target_datatype="bigwig"/>
+ --><display file="ucsc/bam.xml" /><display file="ensembl/ensembl_bam.xml" /><display file="igv/bam.xml" />
diff -r 8305907fa2312da14cf4d500fba1675a169b5517 -r 6591b6ebfb4ea56118941deef03855412c2c00fd lib/galaxy/datatypes/converters/bam_to_bigwig_converter.xml
--- /dev/null
+++ b/lib/galaxy/datatypes/converters/bam_to_bigwig_converter.xml
@@ -0,0 +1,14 @@
+<tool id="CONVERTER_bam_to_bigwig_0" name="Convert BAM to BigWig" version="1.0.0" hidden="true">
+ <!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <command>
+ bedtools genomecov -bg -split -ibam $input -g $chromInfo | wigToBigWig stdin $chromInfo $output
+ </command>
+ <inputs>
+ <param format="bam" name="input" type="data" label="Choose BAM file"/>
+ </inputs>
+ <outputs>
+ <data format="bigwig" name="output"/>
+ </outputs>
+ <help>
+ </help>
+</tool>
diff -r 8305907fa2312da14cf4d500fba1675a169b5517 -r 6591b6ebfb4ea56118941deef03855412c2c00fd lib/galaxy/datatypes/converters/bedgraph_to_bigwig_converter.xml
--- a/lib/galaxy/datatypes/converters/bedgraph_to_bigwig_converter.xml
+++ b/lib/galaxy/datatypes/converters/bedgraph_to_bigwig_converter.xml
@@ -2,9 +2,7 @@
<!-- Used internally to generate track indexes --><command>grep -v "^track" $input | wigToBigWig -clip stdin $chromInfo $output</command><inputs>
- <page><param format="bedgraph" name="input" type="data" label="Choose wiggle"/>
- </page></inputs><outputs><data format="bigwig" name="output"/>
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/changeset/be37937a0b5b/
changeset: be37937a0b5b
user: jgoecks
date: 2012-12-07 16:15:48
summary: Add needed import.
affected #: 1 file
diff -r ad6d34f4decb896e65d988cdd71a09f3fad62722 -r be37937a0b5b05c6047720758bf330087c099e6c lib/galaxy/webapps/galaxy/api/datasets.py
--- a/lib/galaxy/webapps/galaxy/api/datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/datasets.py
@@ -3,6 +3,7 @@
"""
import logging, os, string, shutil, urllib, re, socket
from galaxy import util, datatypes, jobs, web, util
+from galaxy.visualization.data_providers.genome import FeatureLocationIndexDataProvider
from galaxy.web.base.controller import BaseAPIController, UsesVisualizationMixin, get_highest_priority_msg, messages
from galaxy.web.framework.helpers import is_true
https://bitbucket.org/galaxy/galaxy-central/changeset/8305907fa231/
changeset: 8305907fa231
user: jgoecks
date: 2012-12-07 16:18:50
summary: Fixes for bam_to_summary_tree converter: (a) remove deprecated page tags and (b) use bai from metadata rather than from dependency injection.
affected #: 1 file
diff -r be37937a0b5b05c6047720758bf330087c099e6c -r 8305907fa2312da14cf4d500fba1675a169b5517 lib/galaxy/datatypes/converters/bam_to_summary_tree_converter.xml
--- a/lib/galaxy/datatypes/converters/bam_to_summary_tree_converter.xml
+++ b/lib/galaxy/datatypes/converters/bam_to_summary_tree_converter.xml
@@ -1,11 +1,10 @@
<tool id="CONVERTER_bam_to_summary_tree_0" name="Convert BAM to Summary Tree" version="1.0.0" hidden="true">
-<!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
- <command interpreter="python">sam_or_bam_to_summary_tree_converter.py --bam $input1 $bai $output1</command>
+ <!-- <description>__NOT_USED_CURRENTLY_FOR_CONVERTERS__</description> -->
+ <command interpreter="python">
+ sam_or_bam_to_summary_tree_converter.py --bam $input1 $input1.metadata.bam_index $output1
+ </command><inputs>
- <page>
- <param format="bam" name="input1" type="data" label="Choose BAM file"/>
- <param format="bai" name="bai" type="data" label="BAI index file"/>
- </page>
+ <param format="bam" name="input1" type="data" label="Choose BAM file"/></inputs><outputs><data format="summary_tree" name="output1"/>
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: fix to trackster links when dbkey is empty; pack_scripts
by Bitbucket 06 Dec '12
by Bitbucket 06 Dec '12
06 Dec '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/ad6d34f4decb/
changeset: ad6d34f4decb
user: carlfeberhard
date: 2012-12-06 23:34:18
summary: history panel: fix to trackster links when dbkey is empty; pack_scripts
affected #: 2 files
diff -r 75e427a748d0b3e89ccdf246f22499c2f44d9e2a -r ad6d34f4decb896e65d988cdd71a09f3fad62722 static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -189,6 +189,8 @@
dataset_id: this.model.get( 'id' ),
hda_ldda: 'hda'
};
+ // Add dbkey to params if it exists.
+ if( dbkey ){ params.dbkey = dbkey; }
if( !( this.model.hasData() )
|| !( visualizations && visualizations.length )
@@ -209,8 +211,6 @@
//TODO: make this more concise
// map a function to each visualization in the icon's attributes
// create a popupmenu from that map
- // Add dbkey to params if it exists.
- if( dbkey ){ params.dbkey = dbkey; }
/** @inner */
function create_viz_action( visualization ) {
@@ -513,10 +513,13 @@
//TODO: should be imported from trackster.js
function create_trackster_action_fn(vis_url, dataset_params, dbkey) {
return function() {
- var params = {};
- if (dbkey) { params.dbkey = dbkey; }
+ var listTracksParams = {};
+ if (dbkey){
+ // list_tracks seems to use 'f-dbkey' (??)
+ listTracksParams[ 'f-dbkey' ] = dbkey;
+ }
$.ajax({
- url: vis_url + '/list_tracks?f-' + $.param(params),
+ url: vis_url + '/list_tracks?' + $.param( listTracksParams ),
dataType: "html",
error: function() { alert( _l( "Could not add this dataset to browser" ) + '.' ); },
success: function(table_html) {
diff -r 75e427a748d0b3e89ccdf246f22499c2f44d9e2a -r ad6d34f4decb896e65d988cdd71a09f3fad62722 static/scripts/packed/mvc/dataset/hda-edit.js
--- a/static/scripts/packed/mvc/dataset/hda-edit.js
+++ b/static/scripts/packed/mvc/dataset/hda-edit.js
@@ -1,1 +1,1 @@
-var HDAEditView=HDABaseView.extend(LoggableMixin).extend({initialize:function(a){HDABaseView.prototype.initialize.call(this,a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(a){b.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var a={title:_l("Delete"),href:this.urls["delete"],id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if(this.model.get("deleted")||this.model.get("purged")){a={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDABaseView.templates.hdaSummary(a)},_render_errButton:function(){if(this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var c=this.model.get("dbkey"),a=this.model.get("visualizations"),f=this.urls.visualization,d={},g={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(!(this.model.hasData())||!(a&&a.length)||!(f)){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:f,icon_class:"chart_curve"})});var b=this.visualizationsButton.render().$el;b.addClass("visualize-icon");if(c){g.dbkey=c}function e(h){switch(h){case"trackster":return create_trackster_action_fn(f,g,c);case"scatterplot":return create_scatterplot_action_fn(f,g);default:return function(){window.parent.location=f+"/"+h+"?"+$.param(g)}}}if(a.length===1){b.attr("title",a[0]);b.click(e(a[0]))}else{_.each(a,function(i){var h=i.charAt(0).toUpperCase()+i.slice(1);d[_l(h)]=e(i)});make_popupmenu(b,d)}return b},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||(!this.urls.tags.get)){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||(!this.urls.annotation.get)){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAEditView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAEditView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_body_error:function(a){HDABaseView.prototype._render_body_error.call(this,a);var b=a.find("#primary-actions-"+this.model.get("id"));b.prepend(this._render_errButton())},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!jQuery.trim(a.html())){$.ajax({url:this.urls.tags.get,error:function(){alert(_l("Tagging failed"))},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.urls.annotation.set;if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.urls.annotation.get,error:function(){alert(_l("Annotations failed"))},success:function(e){if(e===""){e="<em>"+_l("Describe or add notes to dataset")+"</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAEditView.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function create_scatterplot_action_fn(a,b){action=function(){var d=$(window.parent.document).find("iframe#galaxy_main"),c=a+"/scatterplot?"+$.param(b);d.attr("src",c);$("div.popmenu-wrapper").remove();return false};return action}function create_trackster_action_fn(a,c,b){return function(){var d={};if(b){d.dbkey=b}$.ajax({url:a+"/list_tracks?f-"+$.param(d),dataType:"html",error:function(){alert(_l("Could not add this dataset to browser")+".")},success:function(e){var f=window.parent;f.show_modal(_l("View Data in a New or Saved Visualization"),"",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal(_l("Add Data to Saved Visualization"),e,{Cancel:function(){f.hide_modal()},"Add to visualization":function(){$(f.document).find("input[name=id]:checked").each(function(){var g=$(this).val();c.id=g;f.location=a+"/trackster?"+$.param(c)})}})},"View in new visualization":function(){f.location=a+"/trackster?"+$.param(c)}})}});return false}};
\ No newline at end of file
+var HDAEditView=HDABaseView.extend(LoggableMixin).extend({initialize:function(a){HDABaseView.prototype.initialize.call(this,a);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_render_warnings:function(){return $(jQuery.trim(HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(a){b.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var a={title:_l("Delete"),href:this.urls["delete"],id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if(this.model.get("deleted")||this.model.get("purged")){a={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDABaseView.templates.hdaSummary(a)},_render_errButton:function(){if(this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var c=this.model.get("dbkey"),a=this.model.get("visualizations"),f=this.urls.visualization,d={},g={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(c){g.dbkey=c}if(!(this.model.hasData())||!(a&&a.length)||!(f)){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:f,icon_class:"chart_curve"})});var b=this.visualizationsButton.render().$el;b.addClass("visualize-icon");function e(h){switch(h){case"trackster":return create_trackster_action_fn(f,g,c);case"scatterplot":return create_scatterplot_action_fn(f,g);default:return function(){window.parent.location=f+"/"+h+"?"+$.param(g)}}}if(a.length===1){b.attr("title",a[0]);b.click(e(a[0]))}else{_.each(a,function(i){var h=i.charAt(0).toUpperCase()+i.slice(1);d[_l(h)]=e(i)});make_popupmenu(b,d)}return b},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||(!this.urls.tags.get)){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||(!this.urls.annotation.get)){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAEditView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAEditView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_body_error:function(a){HDABaseView.prototype._render_body_error.call(this,a);var b=a.find("#primary-actions-"+this.model.get("id"));b.prepend(this._render_errButton())},_render_body_ok:function(a){a.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!jQuery.trim(a.html())){$.ajax({url:this.urls.tags.get,error:function(){alert(_l("Tagging failed"))},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.urls.annotation.set;if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.urls.annotation.get,error:function(){alert(_l("Annotations failed"))},success:function(e){if(e===""){e="<em>"+_l("Describe or add notes to dataset")+"</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAEditView.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function create_scatterplot_action_fn(a,b){action=function(){var d=$(window.parent.document).find("iframe#galaxy_main"),c=a+"/scatterplot?"+$.param(b);d.attr("src",c);$("div.popmenu-wrapper").remove();return false};return action}function create_trackster_action_fn(a,c,b){return function(){var d={};if(b){d["f-dbkey"]=b}$.ajax({url:a+"/list_tracks?"+$.param(d),dataType:"html",error:function(){alert(_l("Could not add this dataset to browser")+".")},success:function(e){var f=window.parent;f.show_modal(_l("View Data in a New or Saved Visualization"),"",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal(_l("Add Data to Saved Visualization"),e,{Cancel:function(){f.hide_modal()},"Add to visualization":function(){$(f.document).find("input[name=id]:checked").each(function(){var g=$(this).val();c.id=g;f.location=a+"/trackster?"+$.param(c)})}})},"View in new visualization":function(){f.location=a+"/trackster?"+$.param(c)}})}});return false}};
\ 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: greg: Fixes for handling repository dependencies in the tool shed.
by Bitbucket 06 Dec '12
by Bitbucket 06 Dec '12
06 Dec '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/75e427a748d0/
changeset: 75e427a748d0
user: greg
date: 2012-12-06 23:00:54
summary: Fixes for handling repository dependencies in the tool shed.
affected #: 2 files
diff -r 7b791a48be76604324f23445293d55948f789dde -r 75e427a748d0b3e89ccdf246f22499c2f44d9e2a lib/galaxy/util/shed_util_common.py
--- a/lib/galaxy/util/shed_util_common.py
+++ b/lib/galaxy/util/shed_util_common.py
@@ -1200,7 +1200,6 @@
if 'description' not in all_repository_dependencies:
description = repository_dependencies_dict.get( 'description', None )
all_repository_dependencies[ 'description' ] = description
-
# The next key of interest in repository_dependencies_dict is 'repository_dependencies', which is a list of tuples.
repository_dependencies_tups = repository_dependencies_dict[ 'repository_dependencies' ]
for repository_dependency in repository_dependencies_tups:
@@ -1231,6 +1230,7 @@
else:
# Insert this repository_dependency.
all_repository_dependencies[ repository_dependencies_root_key ] = [ repository_dependency ]
+ handled.append( repository_dependency )
if tool_shed_is_this_tool_shed( tool_shed ):
# The repository is in the current tool shed.
required_repository = get_repository_by_name_and_owner( trans, name, owner )
diff -r 7b791a48be76604324f23445293d55948f789dde -r 75e427a748d0b3e89ccdf246f22499c2f44d9e2a lib/galaxy/webapps/community/util/container_util.py
--- a/lib/galaxy/webapps/community/util/container_util.py
+++ b/lib/galaxy/webapps/community/util/container_util.py
@@ -36,7 +36,14 @@
listified_repository_dependency = repository_dependency.listify
for contained_repository_dependency in self.repository_dependencies:
if contained_repository_dependency.listify == listified_repository_dependency:
- self.repository_dependencies.remove( contained_repository_dependency )
+ self.repository_dependencies.remove( contained_repository_dependency )
+ def to_repository_dependency( self, repository_dependency_id ):
+ toolshed, name, owner, changeset_revision = self.key.split( STRSEP )
+ return RepositoryDependency( id=repository_dependency_id,
+ toolshed=toolshed,
+ repository_name=name,
+ repository_owner=owner,
+ changeset_revision=changeset_revision )
class Datatype( object ):
"""Datatype object"""
@@ -199,36 +206,45 @@
# Create the Repository dependencies folder and add it to the root folder.
repository_dependencies_folder_key = repository_dependencies[ 'root_key' ]
repository_dependencies_folder = Folder( id=folder_id, key=repository_dependencies_folder_key, label=label, parent=repository_dependencies_root_folder )
- # The received repository_dependencies is a dictionary with a single 'description' key, and one or more repository_dependency keys.
+ del repository_dependencies[ 'root_key' ]
+ # The received repository_dependencies is a dictionary with keys: 'root_key', 'description', and one or more repository_dependency keys.
# We want the description value associated with the repository_dependencies_folder.
repository_dependencies_folder.description = repository_dependencies.get( 'description', None )
repository_dependencies_root_folder.folders.append( repository_dependencies_folder )
+ del repository_dependencies[ 'description' ]
+ # The remaining keys in repository_dependencies should all be folders.
+ folder_keys = repository_dependencies.keys()
+ # If repository_dependencies_folder_key is an entry in repository_dependencies, process it first.
+ if repository_dependencies_folder_key in repository_dependencies:
+ val = repository_dependencies[ repository_dependencies_folder_key ]
+ repository_dependencies_folder, folder_id, repository_dependency_id = handle_repository_dependencies_entry( repository_dependencies_root_folder,
+ repository_dependencies_folder,
+ repository_dependencies_folder_key,
+ folder_keys,
+ folder_id,
+ repository_dependency_id,
+ repository_name,
+ repository_owner,
+ changeset_revision,
+ repository_dependencies_folder_key,
+ val )
+ del repository_dependencies[ repository_dependencies_folder_key ]
for key, val in repository_dependencies.items():
- if key in [ 'root_key', 'description' ]:
- continue
- # Only create a new folder object if necessary.
- folder = get_folder( repository_dependencies_root_folder, key )
- if not folder:
- # Create a new folder.
- folder_id += 1
- label = generate_repository_dependencies_folder_label_from_key( repository_name, repository_owner, changeset_revision, key )
- folder = Folder( id=folder_id, key=key, label=label, parent=repository_dependencies_folder )
- for repository_dependency_tup in val:
- toolshed, name, owner, changeset_revision = repository_dependency_tup
- # Create a new repository_dependency.
- repository_dependency_id += 1
- repository_dependency = RepositoryDependency( id=repository_dependency_id,
- toolshed=toolshed,
- repository_name=name,
- repository_owner=owner,
- changeset_revision=changeset_revision )
- # Insert the repository_dependency into the folder.
- folder.repository_dependencies.append( repository_dependency )
- if not get_folder( repository_dependencies_folder, key ):
- # Insert the folder into the list.
- repository_dependencies_folder.folders.append( folder )
+ repository_dependencies_folder, folder_id, repository_dependency_id = handle_repository_dependencies_entry( repository_dependencies_root_folder,
+ repository_dependencies_folder,
+ repository_dependencies_folder_key,
+ folder_keys,
+ folder_id,
+ repository_dependency_id,
+ repository_name,
+ repository_owner,
+ changeset_revision,
+ key,
+ val )
+ # Cast empty folders to be repository dependencies.
+ repository_dependencies_folder, repository_dependency_id = cast_empty_repository_dependency_folders( repository_dependencies_folder,
+ repository_dependency_id )
# Remove repository_dependencies that are also folders, and coerce empty folders into repository dependencies.
- prune_repository_dependencies( repository_dependencies_folder, repository_dependencies_folder )
else:
repository_dependencies_root_folder = None
return folder_id, repository_dependencies_root_folder
@@ -360,13 +376,23 @@
else:
workflows_root_folder = None
return folder_id, workflows_root_folder
+def cast_empty_repository_dependency_folders( folder, repository_dependency_id ):
+ if not folder.folders and not folder.repository_dependencies:
+ repository_dependency_id += 1
+ repository_dependency = folder.to_repository_dependency( repository_dependency_id )
+ if not folder.parent.contains_repository_dependency( repository_dependency ):
+ folder.parent.repository_dependencies.append( repository_dependency )
+ folder.parent.folders.remove( folder )
+ for sub_folder in folder.folders:
+ return cast_empty_repository_dependency_folders( sub_folder, repository_dependency_id )
+ return folder, repository_dependency_id
def generate_repository_dependencies_folder_label_from_key( repository_name, repository_owner, changeset_revision, key ):
"""Return a repository dependency label based on the repository dependency key."""
if key_is_current_repositorys_key( repository_name, repository_owner, changeset_revision, key ):
label = 'Repository dependencies'
else:
- toolshed_base_url, name, owner, revision = get_components_from_key( key )
- label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( name, revision, owner )
+ #toolshed_base_url, name, owner, revision = get_components_from_key( key )
+ label = "Repository <b>%s</b> revision <b>%s</b> owned by <b>%s</b>" % ( repository_name, changeset_revision, repository_owner )
return label
def generate_repository_dependencies_key_for_repository( toolshed_base_url, repository_name, repository_owner, changeset_revision ):
# FIXME: assumes tool shed is current tool shed since repository dependencies across tool sheds is not yet supported.
@@ -391,25 +417,61 @@
repository_owner = items[ 2 ]
changeset_revision = items[ 3 ]
return toolshed_base_url, repository_name, repository_owner, changeset_revision
-def is_folder( folder_keys, toolshed_base_url, repository_name, repository_owner, changeset_revision ):
- key = '%s%s%s%s%s%s%s' % ( toolshed_base_url, STRSEP, repository_name, STRSEP, repository_owner, STRSEP, changeset_revision )
+def handle_repository_dependencies_entry( repository_dependencies_root_folder, repository_dependencies_folder, repository_dependencies_folder_key,
+ folder_keys, folder_id, repository_dependency_id, repository_name, repository_owner, changeset_revision,
+ key, val ):
+ # Only create a new folder object if necessary.
+ folder = get_folder( repository_dependencies_root_folder, key )
+ if not folder:
+ folder_id += 1
+ label = generate_repository_dependencies_folder_label_from_key( repository_name, repository_owner, changeset_revision, key )
+ folder = Folder( id=folder_id, key=key, label=label, parent=repository_dependencies_folder )
+ for repository_dependency_tup in val:
+ toolshed, name, owner, changeset_revision = repository_dependency_tup
+ if is_root_repository( repository_dependencies_folder_key, toolshed, name, owner ):
+ # Do not include repository dependencies that point to a revision within the same repository.
+ continue
+ if is_or_should_be_folder( folder_keys, toolshed, name, owner, changeset_revision ):
+ check_folder_key = generate_repository_dependencies_key_for_repository( toolshed, name, owner, changeset_revision )
+ if get_folder( repository_dependencies_root_folder, check_folder_key ):
+ continue
+ else:
+ # Create a new folder, which may be populated later.
+ folder_id += 1
+ label = generate_repository_dependencies_folder_label_from_key( name, owner, changeset_revision, key )
+ sub_folder = Folder( id=folder_id, key=check_folder_key, label=label, parent=repository_dependencies_folder )
+ folder.folders.append( sub_folder )
+ else:
+ repository_dependency_id += 1
+ repository_dependency = RepositoryDependency( id=repository_dependency_id,
+ toolshed=toolshed,
+ repository_name=name,
+ repository_owner=owner,
+ changeset_revision=changeset_revision )
+ # Insert the repository_dependency into the folder.
+ folder.repository_dependencies.append( repository_dependency )
+ if not get_folder( repository_dependencies_folder, folder.key ):
+ if folder.folders:
+ # Insert the folder into the list.
+ repository_dependencies_folder.folders.append( folder )
+ return repository_dependencies_folder, folder_id, repository_dependency_id
+def is_or_should_be_folder( folder_keys, toolshed, repository_name, repository_owner, changeset_revision ):
+ key = '%s%s%s%s%s%s%s' % ( toolshed, STRSEP, repository_name, STRSEP, repository_owner, STRSEP, changeset_revision )
return key in folder_keys
+def is_root_repository( repository_dependencies_folder_key, toolshed, repository_name, repository_owner ):
+ # Return True if a repository dependency points to a revision within it's own repository.
+ repository_dependencies_folder_tup = repository_dependencies_folder_key.split( STRSEP )
+ rdf_toolshed, rdf_repository_name, rdf_repository_owner, rdf_changeset_revision = repository_dependencies_folder_tup
+ return rdf_toolshed == toolshed and rdf_repository_name == repository_name and rdf_repository_owner == repository_owner
def key_is_current_repositorys_key( repository_name, repository_owner, changeset_revision, key ):
toolshed_base_url, key_name, key_owner, key_changeset_revision = get_components_from_key( key )
return repository_name == key_name and repository_owner == key_owner and changeset_revision == key_changeset_revision
-def prune_folder( folder, repository_dependency, key ):
- if get_folder( folder, key ):
- folder.remove_repository_dependency( repository_dependency )
+def print_folders( pad, folder ):
+ # For debugging...
+ pad_str = ''
+ for i in range( 1, pad ):
+ pad_str += ' '
+ print '%s%s' % ( pad_str, folder.key )
for sub_folder in folder.folders:
- prune_folder( sub_folder, repository_dependency, key )
-def prune_repository_dependencies( folder, root_folder ):
- """Remove repository_dependencies that are also folders, and coerce empty folders into repository dependencies."""
- remove_repository_dependencies( folder, root_folder )
- for sub_folder in folder.folders:
- prune_repository_dependencies( sub_folder, root_folder )
-def remove_repository_dependencies( folder, root_folder ):
- for repository_dependency in folder.repository_dependencies:
- toolshed, name, owner, changeset_revision = repository_dependency.listify
- key = generate_repository_dependencies_key_for_repository( toolshed, name, owner, changeset_revision )
- prune_folder( root_folder, repository_dependency, key )
+ print_folders( pad+5, sub_folder )
\ 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