3 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/1298d3f6aca5/ Changeset: 1298d3f6aca5 Branch: stable User: natefoo Date: 2014-02-19 19:00:33 Summary: Stop jobs when all output datasets are deleted via the API. Affected #: 3 files diff -r 44968207ddd283d0023c72e3d25fd39b1c71eb99 -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -849,6 +849,18 @@ break return job + def stop_hda_creating_job( self, hda ): + """ + Stops an HDA's creating job if all the job's other outputs are deleted. + """ + if hda.parent_id is None and len( hda.creating_job_associations ) > 0: + # Mark associated job for deletion + job = hda.creating_job_associations[0].job + if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]: + # Are *all* of the job's other output datasets deleted? + if job.check_if_output_datasets_deleted(): + job.mark_deleted( self.app.config.track_jobs_in_database ) + self.app.job_manager.job_stop_queue.put( job.id ) class UsesLibraryMixin: diff -r 44968207ddd283d0023c72e3d25fd39b1c71eb99 -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 lib/galaxy/webapps/galaxy/api/history_contents.py --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -278,6 +278,8 @@ # get_dataset can return a string during an error if hda and isinstance( hda, trans.model.HistoryDatasetAssociation ): changed = self.set_hda_from_dict( trans, hda, payload ) + if payload.get( 'deleted', False ): + self.stop_hda_creating_job( hda ) except Exception, exception: log.error( 'Update of history (%s), HDA (%s) failed: %s', history_id, id, str( exception ), exc_info=True ) @@ -347,6 +349,8 @@ trans.sa_session.flush() rval[ 'purged' ] = True + self.stop_hda_creating_job( hda ) + trans.sa_session.flush() rval[ 'deleted' ] = True diff -r 44968207ddd283d0023c72e3d25fd39b1c71eb99 -r 1298d3f6aca59825d0eb3d32afd5686c4b1b9294 lib/galaxy/webapps/galaxy/controllers/dataset.py --- a/lib/galaxy/webapps/galaxy/controllers/dataset.py +++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py @@ -839,14 +839,7 @@ hda.mark_deleted() hda.clear_associated_files() trans.log_event( "Dataset id %s marked as deleted" % str(id) ) - if hda.parent_id is None and len( hda.creating_job_associations ) > 0: - # Mark associated job for deletion - job = hda.creating_job_associations[0].job - if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]: - # Are *all* of the job's other output datasets deleted? - if job.check_if_output_datasets_deleted(): - job.mark_deleted( self.app.config.track_jobs_in_database ) - self.app.job_manager.job_stop_queue.put( job.id ) + self.stop_hda_creating_job( hda ) trans.sa_session.flush() except Exception, e: msg = 'HDA deletion failed (encoded: %s, decoded: %s)' % ( dataset_id, id ) https://bitbucket.org/galaxy/galaxy-central/commits/0db8172d6d36/ Changeset: 0db8172d6d36 User: natefoo Date: 2014-02-19 19:01:03 Summary: merge. Affected #: 3 files diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -892,6 +892,18 @@ break return job + def stop_hda_creating_job( self, hda ): + """ + Stops an HDA's creating job if all the job's other outputs are deleted. + """ + if hda.parent_id is None and len( hda.creating_job_associations ) > 0: + # Mark associated job for deletion + job = hda.creating_job_associations[0].job + if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]: + # Are *all* of the job's other output datasets deleted? + if job.check_if_output_datasets_deleted(): + job.mark_deleted( self.app.config.track_jobs_in_database ) + self.app.job_manager.job_stop_queue.put( job.id ) class UsesLibraryMixin: diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 lib/galaxy/webapps/galaxy/api/history_contents.py --- a/lib/galaxy/webapps/galaxy/api/history_contents.py +++ b/lib/galaxy/webapps/galaxy/api/history_contents.py @@ -280,6 +280,8 @@ # get_dataset can return a string during an error if hda and isinstance( hda, trans.model.HistoryDatasetAssociation ): changed = self.set_hda_from_dict( trans, hda, payload ) + if payload.get( 'deleted', False ): + self.stop_hda_creating_job( hda ) except Exception, exception: log.error( 'Update of history (%s), HDA (%s) failed: %s', history_id, id, str( exception ), exc_info=True ) @@ -349,6 +351,8 @@ trans.sa_session.flush() rval[ 'purged' ] = True + self.stop_hda_creating_job( hda ) + trans.sa_session.flush() rval[ 'deleted' ] = True diff -r c85f8fb5d63e667b63e10cdce518254f56002f55 -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 lib/galaxy/webapps/galaxy/controllers/dataset.py --- a/lib/galaxy/webapps/galaxy/controllers/dataset.py +++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py @@ -839,14 +839,7 @@ hda.mark_deleted() hda.clear_associated_files() trans.log_event( "Dataset id %s marked as deleted" % str(id) ) - if hda.parent_id is None and len( hda.creating_job_associations ) > 0: - # Mark associated job for deletion - job = hda.creating_job_associations[0].job - if job.state in [ self.app.model.Job.states.QUEUED, self.app.model.Job.states.RUNNING, self.app.model.Job.states.NEW ]: - # Are *all* of the job's other output datasets deleted? - if job.check_if_output_datasets_deleted(): - job.mark_deleted( self.app.config.track_jobs_in_database ) - self.app.job_manager.job_stop_queue.put( job.id ) + self.stop_hda_creating_job( hda ) trans.sa_session.flush() except Exception, e: msg = 'HDA deletion failed (encoded: %s, decoded: %s)' % ( dataset_id, id ) https://bitbucket.org/galaxy/galaxy-central/commits/e51429649b44/ Changeset: e51429649b44 User: natefoo Date: 2014-02-19 19:02:12 Summary: merge. Affected #: 6 files diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 lib/galaxy/webapps/galaxy/controllers/history.py --- a/lib/galaxy/webapps/galaxy/controllers/history.py +++ b/lib/galaxy/webapps/galaxy/controllers/history.py @@ -843,35 +843,6 @@ history. <br>You can <a href="%s">continue and import this history</a> or %s. """ % ( web.url_for(controller='history', action='imp', id=id, confirm=True, referer=trans.request.referer ), referer_message ), use_panels=True ) - # Replaced with view (below) but kept (available via manual URL editing) for now - @web.expose - def original_view( self, trans, id=None, show_deleted=False, use_panels=True ): - """View a history. If a history is importable, then it is viewable by any user.""" - # Get history to view. - if not id: - return trans.show_error_message( "You must specify a history you want to view." ) - history_to_view = self.get_history( trans, id, False) - # Integrity checks. - if not history_to_view: - return trans.show_error_message( "The specified history does not exist." ) - # Admin users can view any history - if( ( history_to_view.user != trans.user ) - and ( not trans.user_is_admin() ) - and ( not history_to_view.importable ) ): - error( "Either you are not allowed to view this history or the owner of this history has not made it accessible." ) - # View history. - show_deleted = galaxy.util.string_as_bool( show_deleted ) - datasets = self.get_history_datasets( trans, history_to_view, show_deleted=show_deleted ) - try: - use_panels = galaxy.util.string_as_bool( use_panels ) - except: - pass # already a bool - return trans.stream_template_mako( "history/original_view.mako", - history = history_to_view, - datasets = datasets, - show_deleted = show_deleted, - use_panels = use_panels ) - @web.expose def view( self, trans, id=None, show_deleted=False, show_hidden=False, use_panels=True ): """ diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 static/scripts/mvc/ui.js --- a/static/scripts/mvc/ui.js +++ b/static/scripts/mvc/ui.js @@ -783,77 +783,110 @@ * }); * $( '.myElement' ).modeButton( 'callModeFn', 'bler' ); */ + /** constructor */ function ModeButton( element, options ){ this.currModeIndex = 0; - return this.init( element, options ); + return this._init( element, options ); } + /** html5 data key to store this object inside an element */ ModeButton.prototype.DATA_KEY = 'mode-button'; + /** default options */ ModeButton.prototype.defaults = { - modes : [ - { mode: 'default' } - ] + switchModesOnClick : true }; - ModeButton.prototype.init = function _init( element, options ){ + // ---- private interface + /** set up options, intial mode, and the click handler */ + ModeButton.prototype._init = function _init( element, options ){ + //console.debug( 'ModeButton._init:', element, options ); options = options || {}; this.$element = $( element ); this.options = jQuery.extend( true, {}, this.defaults, options ); + if( !options.modes ){ + throw new Error( 'ModeButton requires a "modes" array' ); + } var modeButton = this; this.$element.click( function _ModeButtonClick( event ){ - // call the curr mode fn modeButton.callModeFn(); // inc the curr mode index - modeButton._incModeIndex(); + if( modeButton.options.switchModesOnClick ){ modeButton._incModeIndex(); } // set the element html $( this ).html( modeButton.options.modes[ modeButton.currModeIndex ].html ); }); - - this.currModeIndex = 0; - if( this.options.initialMode ){ - this.currModeIndex = this._getModeIndex( this.options.initialMode ); - } - return this; + return this.reset(); }; - - - ModeButton.prototype._getModeIndex = function __getModeIndex( modeKey ){ - for( var i=0; i<this.options.modes.length; i+=1 ){ - if( this.options.modes[ i ].mode === modeKey ){ return i; } - } - throw new Error( 'mode not found: ' + modeKey ); - }; - ModeButton.prototype.getCurrMode = function _getCurrMode(){ - return this.options.modes[ this.currModeIndex ]; - }; - ModeButton.prototype.getMode = function _getMode( modeKey ){ - if( !modeKey ){ return this.getCurrMode(); } - return this.options.modes[( this._getModeIndex( modeKey ) )]; - }; - ModeButton.prototype.hasMode = function _hasMode( modeKey ){ - return !!this.getMode( modeKey ); - }; - ModeButton.prototype.currentMode = function _currentMode(){ - return this.options.modes[ this.currModeIndex ]; - }; - ModeButton.prototype.setMode = function _setMode( newModeKey ){ - var newMode = this.getMode( newModeKey ); - this.$element.html( newMode.html || null ); - return this; - }; - ModeButton.prototype._incModeIndex = function __incModeIndex(){ + /** increment the mode index to the next in the array, looping back to zero if at the last */ + ModeButton.prototype._incModeIndex = function _incModeIndex(){ this.currModeIndex += 1; if( this.currModeIndex >= this.options.modes.length ){ this.currModeIndex = 0; } return this; }; - ModeButton.prototype.callModeFn = function _callModeFn( modeKey ){ + /** get the mode index in the modes array for the given key (mode name) */ + ModeButton.prototype._getModeIndex = function _getModeIndex( modeKey ){ + for( var i=0; i<this.options.modes.length; i+=1 ){ + if( this.options.modes[ i ].mode === modeKey ){ return i; } + } + throw new Error( 'mode not found: ' + modeKey ); + }; + /** set the current mode to the one with the given index and set button html */ + ModeButton.prototype._setModeByIndex = function _setModeByIndex( index ){ + var newMode = this.options.modes[ index ]; + if( !newMode ){ + throw new Error( 'mode index not found: ' + index ); + } + this.currModeIndex = index; + if( newMode.html ){ + this.$element.html( newMode.html ); + } + return this; + }; + + // ---- public interface + /** get the current mode object (not just the mode name) */ + ModeButton.prototype.currentMode = function currentMode(){ + return this.options.modes[ this.currModeIndex ]; + }; + /** return the mode key of the current mode */ + ModeButton.prototype.current = function current(){ + // sugar for returning mode name + return this.currentMode().mode; + }; + /** get the mode with the given modeKey or the current mode if modeKey is undefined */ + ModeButton.prototype.getMode = function getMode( modeKey ){ + if( !modeKey ){ return this.currentMode(); } + return this.options.modes[( this._getModeIndex( modeKey ) )]; + }; + /** T/F if the button has the given mode */ + ModeButton.prototype.hasMode = function hasMode( modeKey ){ + try { + return !!this.getMode( modeKey ); + } catch( err ){} + return false; + }; + /** set the current mode to the mode with the given name */ + ModeButton.prototype.setMode = function setMode( modeKey ){ + return this._setModeByIndex( this._getModeIndex( modeKey ) ); + }; + /** reset to the initial mode */ + ModeButton.prototype.reset = function reset(){ + this.currModeIndex = 0; + if( this.options.initialMode ){ + this.currModeIndex = this._getModeIndex( this.options.initialMode ); + } + return this._setModeByIndex( this.currModeIndex ); + }; + /** manually call the click handler of the given mode */ + ModeButton.prototype.callModeFn = function callModeFn( modeKey ){ var modeFn = this.getMode( modeKey ).onclick; if( modeFn && jQuery.type( modeFn === 'function' ) ){ - return modeFn.call( this ); + // call with the element as context (std jquery pattern) + modeFn.call( this.$element.get(0) ); + return this; } return undefined; }; @@ -861,26 +894,32 @@ // as jq plugin jQuery.fn.extend({ modeButton : function $modeButton( options ){ - var nonOptionsArgs = jQuery.makeArray( arguments ).slice( 1 ); + if( !this.size() ){ return this; } + //TODO: does map still work with jq multi selection (i.e. $( '.class-for-many-btns' ).modeButton)? - return this.map( function(){ - var $this = $( this ), - data = $this.data( 'mode-button' ); + if( jQuery.type( options ) === 'object' ){ + return this.map( function(){ + var $this = $( this ); + $this.data( 'mode-button', new ModeButton( $this, options ) ); + return this; + }); + } - if( jQuery.type( options ) === 'object' ){ - data = new ModeButton( $this, options ); - $this.data( 'mode-button', data ); + var $first = $( this[0] ), + button = $first.data( 'mode-button' ); + console.debug( 'first, button', $first, button ); - } else if( data && jQuery.type( options ) === 'string' ){ - var fn = data[ options ]; - if( jQuery.type( fn ) === 'function' ){ - return fn.apply( data, nonOptionsArgs ); - } - } else if ( data ){ - return data; + if( !button ){ + throw new Error( 'modeButton needs an options object or string name of a function' ); + } + + if( button && jQuery.type( options ) === 'string' ){ + var fnName = options; + if( button && jQuery.type( button[ fnName ] ) === 'function' ){ + return button[ fnName ].apply( button, jQuery.makeArray( arguments ).slice( 1 ) ); } - return this; - }); + } + return button; } }); }()); diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 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,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});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=this.template(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(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});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 PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var 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}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},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.create=function _create(b,a){return new PopupMenu(b,a)};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(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;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};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function b(m,l){this.currModeIndex=0;return this.init(m,l)}b.prototype.DATA_KEY="mode-button";b.prototype.defaults={modes:[{mode:"default"}]};b.prototype.init=function f(m,l){l=l||{};this.$element=$(m);this.options=jQuery.extend(true,{},this.defaults,l);var o=this;this.$element.click(function n(p){o.callModeFn();o._incModeIndex();$(this).html(o.options.modes[o.currModeIndex].html)});this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this};b.prototype._getModeIndex=function j(l){for(var m=0;m<this.options.modes.length;m+=1){if(this.options.modes[m].mode===l){return m}}throw new Error("mode not found: "+l)};b.prototype.getCurrMode=function a(){return this.options.modes[this.currModeIndex]};b.prototype.getMode=function g(l){if(!l){return this.getCurrMode()}return this.options.modes[(this._getModeIndex(l))]};b.prototype.hasMode=function k(l){return !!this.getMode(l)};b.prototype.currentMode=function e(){return this.options.modes[this.currModeIndex]};b.prototype.setMode=function c(m){var l=this.getMode(m);this.$element.html(l.html||null);return this};b.prototype._incModeIndex=function d(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};b.prototype.callModeFn=function h(l){var m=this.getMode(l).onclick;if(m&&jQuery.type(m==="function")){return m.call(this)}return undefined};jQuery.fn.extend({modeButton:function i(m){var l=jQuery.makeArray(arguments).slice(1);return this.map(function(){var p=$(this),o=p.data("mode-button");if(jQuery.type(m)==="object"){o=new b(p,m);p.data("mode-button",o)}else{if(o&&jQuery.type(m)==="string"){var n=o[m];if(jQuery.type(n)==="function"){return n.apply(o,l)}}else{if(o){return o}}}return this})}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}()); \ No newline at end of file +var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});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=this.template(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(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});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 PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var 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}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},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.create=function _create(b,a){return new PopupMenu(b,a)};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(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;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};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=jQuery.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&jQuery.type(o==="function")){o.call(this.$element.get(0));return this}return undefined};jQuery.fn.extend({modeButton:function k(n){if(!this.size()){return this}if(jQuery.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");console.debug("first, button",p,o);if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&jQuery.type(n)==="string"){var q=n;if(o&&jQuery.type(o[q])==="function"){return o[q].apply(o,jQuery.makeArray(arguments).slice(1))}}return o}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}()); \ No newline at end of file diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 templates/webapps/galaxy/history/original_view.mako --- a/templates/webapps/galaxy/history/original_view.mako +++ /dev/null @@ -1,173 +0,0 @@ -<%namespace file="/display_common.mako" import="get_history_link, get_controller_name" /> -<%namespace file="/root/history_common.mako" import="render_dataset" /> -<%namespace file="/tagging_common.mako" import="render_individual_tagging_element, render_community_tagging_element" /> - -<%! - def inherit(context): - if context.get('use_panels'): - return '/webapps/galaxy/base_panels.mako' - else: - return '/base.mako' -%> -<%inherit file="${inherit(context)}"/> - -<%def name="javascripts()"> - ${parent.javascripts()} - ${h.js( "libs/jquery/jstorage" )} - <script type="text/javascript"> - $(function() { - init_history_items( $("div.historyItemWrapper"), false, "nochanges" ); - $( '#switch-to-link' ).click( function( event ){ - var galaxy = window.Galaxy || window.parent.Galaxy; - if( galaxy ){ - galaxy.currHistoryPanel.switchToHistory( '${ trans.security.encode_id( history.id ) }' ); - } - }); - $( '#refresh' ).click( function( event ){ window.location.reload( true ); }) - }); - </script> -</%def> - -<%def name="stylesheets()"> - ${parent.stylesheets()} - ${h.css( "history", "autocomplete_tagging" )} - - <style type="text/css"> - - /* these don't appear to be used? */ - .page-body - { - padding: 10px; - float: left; - width: 65%; - } - .page-meta - { - float: right; - width: 27%; - padding: 0.5em; - margin: 0.25em; - vertical-align: text-top; - border: 2px solid #DDDDDD; - border-top: 4px solid #DDDDDD; - } - - - body { - padding: 0px; - margin: 0px; - } - - div.unified-panel-body { - position: absolute; - top: 0px; - width: 100%; - } - - #history-name-area { - margin: 12px 0px 0px 16px; - font-size: 120%; - } - #top-links { - margin: 4px 0px 8px 16px; - } - - .historyItemContainer { - /*padding-right: 3px;*/ - } - .historyItemBody { - display: none; - } - div.historyItemWrapper { - margin: 0px 4px 0px 4px ; - border-left: 1px solid #999999; - border-right: 1px solid #999999; - } - /* TODO: unify with other history css and into .less */ - </style> - - <noscript> - <style> - .historyItemBody { - display: block; - } - </style> - </noscript> -</%def> - -<%def name="init()"> -<% - self.has_left_panel=False - self.has_right_panel=False - self.message_box_visible=False -%> -</%def> - -<%def name="body()"> - ${center_panel()} -</%def> - -<%def name="center_panel()"> - ## Get URL to other histories owned by user that owns this history. - <% - ##TODO: is there a better way to create this URL? Can't use 'f-username' as a key b/c it's not a valid identifier. - href_to_published_histories = h.url_for( controller='/history', action='list_published') - if history.user is not None: - href_to_user_histories = h.url_for( controller='/history', action='list_published', xxx=history.user.username).replace( 'xxx', 'f-username') - else: - href_to_user_histories = h.url_for( controller='/history', action='list_published' )##should this instead be be None or empty string? - %> - - <div class="unified-panel-body"> - <div style="overflow: auto; height: 100%;"> - ## Render view of history. - <div id="history-name-area" class="historyLinks" style="color: gray; font-weight: bold; padding: 0px 0px 5px 0px"> - <div id="history-name">${history.get_display_name()}</div> - </div> - - <div id="top-links" class="historyLinks" style="padding: 0px 0px 5px 0px"> - %if not history.purged and history.user != trans.user: - ##TODO: need to remove _top - <a href="${h.url_for(controller='history', action='imp', id=trans.security.encode_id(history.id) )}" - >import and start using history</a> | - <a id="refresh" href="javascript:void(0)" >${_('refresh')}</a> | - %endif - %if not history.purged and history.user == trans.user: - <a id="switch-to-link" href="javascript:void(0)">${_('switch to this history')}</a> | - <a id="refresh" href="javascript:void(0)" >${_('refresh')}</a> | - %endif - %if show_deleted: - <a href="${h.url_for(controller='history', action='view', id=trans.security.encode_id(history.id), show_deleted=False, use_panels=use_panels )}">${_('hide deleted')}</a> | - %else: - <a href="${h.url_for(controller='history', action='view', id=trans.security.encode_id(history.id), show_deleted=True, use_panels=use_panels )}">${_('show deleted')}</a> | - %endif - <a href="#" class="toggle">collapse all</a> - </div> - - %if history.deleted: - <div class="warningmessagesmall"> - ${_('You are currently viewing a deleted history!')} - </div> - <p></p> - %endif - - %if not datasets: - <div class="infomessagesmall" id="emptyHistoryMessage"> - - %else: - ## Render requested datasets, ordered from newest to oldest - %for data in datasets: - %if data.visible: - <div class="historyItemContainer visible-right-border" id="historyItemContainer-${data.id}"> - ${render_dataset( data, data.hid, show_deleted_on_refresh = show_deleted, for_editing=False )} - </div> - %endif - %endfor - - <div class="infomessagesmall" id="emptyHistoryMessage" style="display:none;"> - %endif - ${_("Your history is empty. Click 'Get Data' on the left pane to start")} - </div> - </div> - </div> -</%def> diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 templates/webapps/galaxy/history/view.mako --- a/templates/webapps/galaxy/history/view.mako +++ b/templates/webapps/galaxy/history/view.mako @@ -77,6 +77,7 @@ %endif <script type="text/javascript"> + ##TODO: remove when Galaxy is either ensured or removed from the history panel var using_panels = ${ 'false' if not use_panels else 'true' }; %if not use_panels: window.Galaxy = {}; @@ -87,113 +88,107 @@ ## ---------------------------------------------------------------------------- <%def name="center_panel()"> +<% + show_deleted = context.get( 'show_deleted', None ) + show_hidden = context.get( 'show_hidden', None ) + + user_is_owner_json = 'true' if user_is_owner else 'false' + show_deleted_json = h.to_json_string( show_deleted ) + show_hidden_json = h.to_json_string( show_hidden ) + + imp_with_deleted_url = h.url_for( controller='history', action='imp', id=history['id'], all_datasets=True ) + imp_without_deleted_url = h.url_for( controller='history', action='imp', id=history['id'] ) +%> + <div id="header" class="clear"><div id="history-view-controls" class="pull-right"> - <% - show_deleted = context.get( 'show_deleted', None ) - show_hidden = context.get( 'show_hidden', None ) - - show_deleted_js = 'true' if show_deleted == True else ( 'null' if show_deleted == None else 'false' ) - show_hidden_js = 'true' if show_hidden == True else ( 'null' if show_hidden == None else 'false' ) - print 'user_is_owner:', user_is_owner - %> %if not user_is_owner and not history[ 'purged' ]: - <a id="import" class="btn btn-default" style="display: none;" - href="${h.url_for( controller='history', action='imp', id=history['id'], all_datasets=show_deleted )}"> - ${_('Import and start using history')} - </a> + <button id="import" class="btn btn-default"></button> %endif - <button id="toggle-deleted" class="btn btn-default"> - ${_('Exclude deleted') if show_deleted else _('Include deleted')} - </button> - <button id="toggle-hidden" class="btn btn-default"> - ${_('Exclude hidden') if show_hidden else _('Include hidden')} - </button> + <button id="toggle-deleted" class="btn btn-default"></button> + <button id="toggle-hidden" class="btn btn-default"></button></div></div><div id="history-${ history[ 'id' ] }" class="history-panel unified-panel-body" style="overflow: auto;"></div><script type="text/javascript"> + $(function(){ + $( '#toggle-deleted' ).modeButton({ + initialMode : "${ 'showing_deleted' if show_deleted else 'not_showing_deleted' }", + modes: [ + { mode: 'showing_deleted', html: _l( 'Exclude deleted' ) }, + { mode: 'not_showing_deleted', html: _l( 'Include deleted' ) } + ] + }).click( function(){ + // allow the 'include/exclude deleted' button to control whether the 'import' button includes deleted + // datasets when importing or not; when deleted datasets are shown, they'll be imported + $( '#import' ).modeButton( 'setMode', + $( this ).modeButton( 'current' ) === 'showing_deleted'? 'with_deleted': 'without_deleted' ) + }); + + $( '#toggle-hidden' ).modeButton({ + initialMode : "${ 'showing_hidden' if show_hidden else 'not_showing_hidden' }", + modes: [ + { mode: 'showing_hidden', html: _l( 'Exclude hidden' ) }, + { mode: 'not_showing_hidden', html: _l( 'Include hidden' ) } + ] + }); + + $( '#import' ).modeButton({ + switchModesOnClick : false, + initialMode : "${ 'with_deleted' if show_deleted else 'without_deleted' }", + modes: [ + { mode: 'with_deleted', html: _l( 'Import with deleted datasets and start using history' ), + onclick: function importWithDeleted(){ + window.location = '${imp_with_deleted_url}'; + } + }, + { mode: 'without_deleted', html: _l( 'Import and start using history' ), + onclick: function importWithoutDeleted(){ + window.location = '${imp_without_deleted_url}'; + } + }, + ] + }); + }); + var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false, userIsOwner = ${'true' if user_is_owner else 'false'}, historyJSON = ${h.to_json_string( history )}, hdaJSON = ${h.to_json_string( hdas )}; - window.hdaJSON = hdaJSON; - - $( '#toggle-deleted' ).modeButton({ - initialMode : (${ show_deleted_js })?( 'exclude' ):( 'include' ), - modes: [ - { mode: 'exclude', html: _l( 'Exclude deleted' ) }, - { mode: 'include', html: _l( 'Include deleted' ) } - ] - }).click( function(){ - // allow the 'include/exclude deleted' button to control whether the 'import' button includes deleted datasets - // when importing or not; when deleted datasets are shown, they'll be imported - var $importBtn = $( '#import' ); - if( $importBtn.size() ){ - // a bit hacky - var href = $importBtn.attr( 'href' ), - includeDeleted = $( this ).modeButton()[0].getMode().mode === 'exclude'; - href = href.replace( /all_datasets=True|False/, ( includeDeleted )?( 'True' ):( 'False' ) ); - $importBtn.attr( 'href', href ); - $importBtn.text( includeDeleted ? _l( 'Import with deleted datasets and start using history' ) - : _l( 'Import and start using history' ) ); - } - }); - - $( '#toggle-hidden' ).modeButton({ - initialMode : (${ show_hidden_js })?( 'exclude' ):( 'include' ), - modes: [ - { mode: 'exclude', html: _l( 'Exclude hidden' ) }, - { mode: 'include', html: _l( 'Include hidden' ) } - ] - }); - - ##TODO: move to mako - if( Galaxy.currUser.id !== historyJSON.user_id ){ - $( '#import' ).show(); - } + panelToUse = ( userIsOwner )? + ({ location: 'mvc/history/history-panel', className: 'HistoryPanel' }): + ({ location: 'mvc/history/readonly-history-panel', className: 'ReadOnlyHistoryPanel' }); require.config({ baseUrl : "${h.url_for( '/static/scripts' )}" - })([ - %if user_is_owner: - 'mvc/history/history-panel' - %else: - 'mvc/history/readonly-history-panel' - %endif - ${ } - ], function( panelMod ){ - //require([ "mvc/history/history-panel" ], function( historyPanel ){ - // history module is already in the dpn chain from the panel. We can re-scope it here. - var historyModel = require( 'mvc/history/history-model' ), - hdaBaseView = require( 'mvc/dataset/hda-base' ), - history = new historyModel.History( historyJSON, hdaJSON, { - logger: ( debugging )?( console ):( null ) + })([ panelToUse.location ], function( panelMod ){ + $(function(){ + var panelClass = panelMod[ panelToUse.className ], + // history module is already in the dpn chain from the panel. We can re-scope it here. + historyModel = require( 'mvc/history/history-model' ), + hdaBaseView = require( 'mvc/dataset/hda-base' ), + history = new historyModel.History( historyJSON, hdaJSON, { + logger: ( debugging )?( console ):( null ) + }); + + window.historyPanel = new panelClass({ + show_deleted : ${show_deleted_json}, + show_hidden : ${show_hidden_json}, + el : $( "#history-" + historyJSON.id ), + model : history, + onready : function(){ + var panel = this; + $( '#toggle-deleted' ).on( 'click', function(){ + panel.toggleShowDeleted(); + }); + $( '#toggle-hidden' ).on( 'click', function(){ + panel.toggleShowHidden(); + }); + this.render(); + } }); - - window.panelMod = panelMod; - %if user_is_owner: - window.panelClass = panelMod.HistoryPanel; - %else: - window.panelClass = panelMod.ReadOnlyHistoryPanel; - %endif - window.historyPanel = new panelClass({ - show_deleted : ${show_deleted_js}, - show_hidden : ${show_hidden_js}, - el : $( "#history-" + historyJSON.id ), - model : history, - onready : function(){ - var panel = this; - $( '#toggle-deleted' ).on( 'click', function(){ - panel.toggleShowDeleted(); - }); - $( '#toggle-hidden' ).on( 'click', function(){ - panel.toggleShowHidden(); - }); - this.render(); - } }); }); </script> diff -r 0db8172d6d363ba1010df08a79f6db435f4f0ee7 -r e51429649b44d5b434a6b6f4e10daa1dbf390c20 tools/data_source/upload.xml --- a/tools/data_source/upload.xml +++ b/tools/data_source/upload.xml @@ -1,7 +1,6 @@ <?xml version="1.0"?><tool name="Upload File" id="upload1" version="1.1.4" workflow_compatible="false"> - <hidden>True</hidden><description> from your computer </description> 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.