commit/galaxy-central: 2 new changesets
2 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/changeset/e825b868a31f/ changeset: e825b868a31f user: carlfeberhard date: 2012-10-30 21:39:47 summary: history.js: add hda updater, pull model data from common api code (in initial mako render, and on fetch/update), set up url templates for history, hda models affected #: 8 files diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/mvc/history.js --- a/static/scripts/mvc/history.js +++ b/static/scripts/mvc/history.js @@ -7,101 +7,182 @@ TODO: currently, adding a dataset (via tool execute, etc.) creates a new dataset and refreshes the page + from mako template: + BUG: imported, shared history with unaccessible dataset errs in historycontents when getting history + (entire history is inaccessible) + BUG: anon user, broken updater (upload) + added check_state to UsesHistoryDatasetAssocMixin + BUG: anon user + BUG: historyItem, error'd ds show display, download? + + from loadFromAPI: + BUG: not showing previous annotations + + fixed: + BUG: history, broken intial hist state (running, updater, etc.) + ??: doesn't seem to happen anymore + BUG: collapse all should remove all expanded from storage + FIXED: hideAllItemBodies now resets storage.expandedItems + BUG: historyItem, shouldn't allow tag, annotate, peek on purged datasets + FIXED: ok state now shows only: info, rerun + BUG: history?, some ids aren't returning encoded... + FIXED:??? + BUG: history, showing deleted ds + FIXED + UGH: historyItems have to be decorated with history_ids (api/histories/:history_id/contents/:id) + FIXED by adding history_id to history_contents.show + BUG: history, if hist has err'd ds, hist has perm state 'error', updater on following ds's doesn't run + FIXED by reordering history state from ds' states here and histories + BUG: history, broken annotation on reload (can't get thru api (sets fine, tho)) + FIXED: get thru api for now + + to relational model? + HDACollection, meta_files, display_apps, etc. + + + break this file up + localize all + ?: render url templates on init or render? + ?: history, annotation won't accept unicode + quota mgr + show_deleted/hidden: + use storage + on/off ui + move histview fadein/out in render to app? + don't draw body until it's first expand event + + hierarchy: + dataset -> hda + history -> historyForEditing, historyForViewing + display_structured? + + btw: get an error'd ds by running fastqc on fastq (when you don't have it installed) meta: + css/html class/id 'item' -> hda + add classes, ids on empty divs + events (local/ui and otherwise) require.js convert function comments to jsDoc style, complete comments move inline styles into base.less watch the magic strings watch your globals - all: - add classes, ids on empty divs - incorporate relations? - events (local/ui and otherwise) - have info bodies prev. opened, redisplay on refresh - transfer history.mako js: - updater, etc. - create viz icon - trackster - scatterplot - phylo-viz - on ready: - delete function - check_transfer_status (running->ok) - quota meter update - - historyItemView: - poly HistoryItemView (and HistoryView?) on: for_editing, display_structured, trans.user - don't draw body until it's first unhide event - HIview state transitions (eg. upload -> ok), curr: build new, delete old, place new (in render) - move visualizations menu - include phyloviz - - History: - renaming broken - tags rendering broken (url?) - annotation (url?) - meta controls : collapse all, rename, annotate, etc. - - collection: - show_deleted, show_hidden (thru js - no refresh) - + features: + lineage + hide button + show permissions in info + show shared/sharing status on ds, history + maintain scroll position on refresh (storage?) + selection, multi-select (and actions common to selected (ugh)) + searching + sorting, re-shuffling ============================================================================= */ -//TODO: use initialize (or validate) to check purged AND deleted -> purged XOR deleted -var HistoryItem = BaseModel.extend( LoggableMixin ).extend({ +var HistoryDatasetAssociation = BaseModel.extend( LoggableMixin ).extend({ // a single HDA model // uncomment this out see log messages //logger : console, defaults : { + // ---these are part of an HDA proper: + + // parent (containing) history + history_id : null, + // often used with tagging + model_class : 'HistoryDatasetAssociation', + // index within history (??) + hid : 0, + // ---whereas these are Dataset related/inherited + id : null, - name : '', - data_type : null, - file_size : 0, - genome_build : null, - metadata_data_lines : 0, - metadata_dbkey : null, - metadata_sequences : 0, + name : '', + // one of HistoryDatasetAssociation.STATES + state : '', + // sniffed datatype (sam, tabular, bed, etc.) + data_type : null, + // size in bytes + file_size : 0, + + // array of associated file types (eg. [ 'bam_index', ... ]) + meta_files : [], misc_blurb : '', - misc_info : '', - model_class : '', - state : '', + misc_info : '', + deleted : false, purged : false, + // aka. !hidden + visible : false, + // based on trans.user (is_admin or security_agent.can_access_dataset( <user_roles>, hda.dataset )) + accessible : false, - // clash with BaseModel here? - visible : true, - - for_editing : true, - // additional urls will be passed and added, if permissions allow their use - - bodyIsShown : false + // this needs to be removed (it is a function of the view type (e.g. HDAForEditingView)) + for_editing : true + }, + + // fetch location of this history in the api + url : function(){ + //TODO: get this via url router + return 'api/histories/' + this.get( 'history_id' ) + '/contents/' + this.get( 'id' ); }, + // (curr) only handles changing state of non-accessible hdas to STATES.NOT_VIEWABLE + //TODO: use initialize (or validate) to check purged AND deleted -> purged XOR deleted initialize : function(){ this.log( this + '.initialize', this.attributes ); this.log( '\tparent history_id: ' + this.get( 'history_id' ) ); - //TODO: accessible is set in alt_hist - // this state is not in trans.app.model.Dataset.states - set it here + //!! this state is not in trans.app.model.Dataset.states - set it here if( !this.get( 'accessible' ) ){ - this.set( 'state', HistoryItem.STATES.NOT_VIEWABLE ); + this.set( 'state', HistoryDatasetAssociation.STATES.NOT_VIEWABLE ); } + + this.on( 'change', function( event, x, y, z ){ + this.log( this + ' has changed:', event, x, y, z ); + }); }, + isDeletedOrPurged : function(){ + return ( this.get( 'deleted' ) || this.get( 'purged' ) ); + }, + + // roughly can_edit from history_common.mako - not deleted or purged = editable isEditable : function(){ - // roughly can_edit from history_common.mako - not deleted or purged = editable return ( //this.get( 'for_editing' ) - //&& !( this.get( 'deleted' ) || this.get( 'purged' ) ) - !( this.get( 'deleted' ) || this.get( 'purged' ) ) + //&& !( this.get( 'deleted' ) || this.get( 'purged' ) )?? + !this.isDeletedOrPurged() ); }, + + // based on show_deleted, show_hidden (gen. from the container control), would this ds show in the list of ds's? + //TODO: too many visibles + isVisible : function( show_deleted, show_hidden ){ + var isVisible = true; + if( ( !show_deleted ) + && ( this.get( 'deleted' ) || this.get( 'purged' ) ) ){ + isVisible = false; + } + if( ( !show_hidden ) + && ( !this.get( 'visible' ) ) ){ + isVisible = false; + } + return isVisible; + }, + // 'final' states are states where no processing (for the ds) is left to do on the server + inFinalState : function(){ + return ( + ( this.get( 'state' ) === HistoryDatasetAssociation.STATES.OK ) + || ( this.get( 'state' ) === HistoryDatasetAssociation.STATES.FAILED_METADATA ) + || ( this.get( 'state' ) === HistoryDatasetAssociation.STATES.EMPTY ) + || ( this.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR ) + ); + }, + + // convenience fn to match hda.has_data hasData : function(){ //TODO:?? is this equivalent to all possible hda.has_data calls? return ( this.get( 'file_size' ) > 0 ); @@ -112,13 +193,13 @@ if( this.get( 'name' ) ){ nameAndId += ':"' + this.get( 'name' ) + '"'; } - return 'HistoryItem(' + nameAndId + ')'; + return 'HistoryDatasetAssociation(' + nameAndId + ')'; } }); //------------------------------------------------------------------------------ -HistoryItem.STATES = { - NOT_VIEWABLE : 'not_viewable', // not in trans.app.model.Dataset.states +HistoryDatasetAssociation.STATES = { + NOT_VIEWABLE : 'noPermission', // not in trans.app.model.Dataset.states NEW : 'new', UPLOAD : 'upload', QUEUED : 'queued', @@ -131,34 +212,310 @@ FAILED_METADATA : 'failed_metadata' }; +//============================================================================== +var HDACollection = Backbone.Collection.extend( LoggableMixin ).extend({ + model : HistoryDatasetAssociation, + + logger : console, + + // return the ids of every hda in this collection + ids : function(){ + return this.map( function( item ){ return item.id; }); + }, + + // return an HDA collection containing every 'shown' hda based on show_deleted/hidden + getVisible : function( show_deleted, show_hidden ){ + return new HDACollection( + this.filter( function( item ){ return item.isVisible( show_deleted, show_hidden ); }) + ); + }, + + // get a map where <possible hda state> : [ <list of hda ids in that state> ] + getStateLists : function(){ + var stateLists = {}; + _.each( _.values( HistoryDatasetAssociation.STATES ), function( state ){ + stateLists[ state ] = []; + }); + //NOTE: will err on unknown state + this.each( function( item ){ + stateLists[ item.get( 'state' ) ].push( item.get( 'id' ) ); + }); + return stateLists; + }, + + // update (fetch -> render) the hdas with the ids given + update : function( ids ){ + this.log( this + 'update:', ids ); + + if( !( ids && ids.length ) ){ return; } + + var collection = this; + _.each( ids, function( id, index ){ + var historyItem = collection.get( id ); + historyItem.fetch(); + }); + }, + + toString : function(){ + return ( 'HDACollection(' + this.ids().join(',') + ')' ); + } +}); + //============================================================================== -var HistoryItemView = BaseView.extend( LoggableMixin ).extend({ - //??TODO: add alias in initialize this.hda = this.model? - // view for HistoryItem model above +var History = BaseModel.extend( LoggableMixin ).extend({ + //TODO: bind change events from items and collection to this (itemLengths, states) // uncomment this out see log messages //logger : console, + // values from api (may need more) + defaults : { + id : '', + name : '', + state : '', + + //TODO: wire these to items (or this) + show_deleted : false, + show_hidden : false, + + diskSize : 0, + deleted : false, + + tags : [], + annotation : null, + + //TODO: quota msg and message? how to get those over the api? + message : null, + quotaMsg : false + }, + + url : function(){ + // api location of history resource + //TODO: hardcoded + return 'api/histories/' + this.get( 'id' ); + }, + + initialize : function( initialSettings, initialHdas ){ + this.log( this + ".initialize:", initialSettings, initialHdas ); + + this.hdas = new HDACollection(); + + // if we've got hdas passed in the constructor, load them and set up updates if needed + if( initialHdas && initialHdas.length ){ + this.hdas.reset( initialHdas ); + this.checkForUpdates(); + } + + this.on( 'change', function( event, x, y, z ){ + this.log( this + ' has changed:', event, x, y, z ); + }); + }, + + // get data via the api (alternative to sending options,hdas to initialize) + loadFromAPI : function( historyId, callback ){ + var history = this; + + // fetch the history AND the user (mainly to see if they're logged in at this point) + history.attributes.id = historyId; + //TODO:?? really? fetch user here? + jQuery.when( jQuery.ajax( 'api/users/current' ), history.fetch() + + ).then( function( userResponse, historyResponse ){ + //console.warn( 'fetched user, history: ', userResponse, historyResponse ); + history.attributes.user = userResponse[0]; //? meh. + history.log( history ); + + }).then( function(){ + // ...then the hdas (using contents?ids=...) + jQuery.ajax( history.url() + '/contents?' + jQuery.param({ + ids : history.itemIdsFromStateIds().join( ',' ) + + // reset the collection to the hdas returned + })).success( function( hdas ){ + //console.warn( 'fetched hdas' ); + history.hdas.reset( hdas ); + history.checkForUpdates(); + callback(); + }); + }); + }, + + // reduce the state_ids map of hda id lists -> a single list of ids + //...ugh - seems roundabout; necessary because the history doesn't have a straightforward list of ids + // (and history_contents/index curr returns a summary only) + hdaIdsFromStateIds : function(){ + return _.reduce( _.values( this.get( 'state_ids' ) ), function( reduction, currIdList ){ + return reduction.concat( currIdList ); + }); + }, + + // get the history's state from it's cummulative ds states, delay + update if needed + checkForUpdates : function( datasets ){ + // get overall History state from collection, run updater if History has running/queued hdas + this.stateFromStateIds(); + if( ( this.get( 'state' ) === HistoryDatasetAssociation.STATES.RUNNING ) + || ( this.get( 'state' ) === HistoryDatasetAssociation.STATES.QUEUED ) ){ + this.stateUpdater(); + } + return this; + }, + + // sets history state based on current hdas' states + // ported from api/histories.traverse (with placement of error state changed) + stateFromStateIds : function(){ + var stateIdLists = this.hdas.getStateLists(); + this.attributes.state_ids = stateIdLists; + + //TODO: make this more concise + if( ( stateIdLists.running.length > 0 ) + || ( stateIdLists.upload.length > 0 ) + || ( stateIdLists.setting_metadata.length > 0 ) ){ + this.set( 'state', HistoryDatasetAssociation.STATES.RUNNING ); + + } else if( stateIdLists.queued.length > 0 ){ + this.set( 'state', HistoryDatasetAssociation.STATES.QUEUED ); + + } else if( ( stateIdLists.error.length > 0 ) + || ( stateIdLists.failed_metadata.length > 0 ) ){ + this.set( 'state', HistoryDatasetAssociation.STATES.ERROR ); + + } else if( stateIdLists.ok.length === this.hdas.length ){ + this.set( 'state', HistoryDatasetAssociation.STATES.OK ); + + } else { + throw( this + '.stateFromStateDetails: unable to determine ' + + 'history state from hda states: ' + this.get( 'state_ids' ) ); + } + return this; + }, + + // update this history, find any hda's running/queued, update ONLY those that have changed states, + // set up to run this again in some interval of time + stateUpdater : function(){ + var history = this, + oldState = this.get( 'state' ), + // state ids is a map of every possible hda state, each containing a list of ids for hdas in that state + oldStateIds = this.get( 'state_ids' ); + + // pull from the history api + //TODO: fetch? + jQuery.ajax( 'api/histories/' + this.get( 'id' ) + + ).success( function( response ){ + //this.log( 'historyApiRequest, response:', response ); + history.set( response ); + history.log( 'current history state:', history.get( 'state' ), '(was)', oldState ); + + // for each state, check for the difference between old dataset states and new + // the goal here is to check ONLY those datasets that have changed states (not all datasets) + var changedIds = []; + _.each( _.keys( response.state_ids ), function( state ){ + var diffIds = _.difference( response.state_ids[ state ], oldStateIds[ state ] ); + // aggregate those changed ids + changedIds = changedIds.concat( diffIds ); + }); + + // send the changed ids (if any) to dataset collection to have them fetch their own model changes + if( changedIds.length ){ + history.hdas.update( changedIds ); + } + + // set up to keep pulling if this history in run/queue state + //TODO: magic number here + if( ( history.get( 'state' ) === HistoryDatasetAssociation.STATES.RUNNING ) + || ( history.get( 'state' ) === HistoryDatasetAssociation.STATES.QUEUED ) ){ + setTimeout( function(){ + history.stateUpdater(); + }, 4000 ); + } + + }).error( function( xhr, status, error ){ + if( console && console.warn ){ + console.warn( 'Error getting history updates from the server:', xhr, status, error ); + } + alert( 'Error getting history updates from the server.\n' + error ); + }); + }, + + toString : function(){ + var nameString = ( this.get( 'name' ) )? + ( ',' + this.get( 'name' ) ) : ( '' ); + return 'History(' + this.get( 'id' ) + nameString + ')'; + } +}); + +//============================================================================== +var HDAView = BaseView.extend( LoggableMixin ).extend({ + //??TODO: add alias in initialize this.hda = this.model? + // view for HistoryDatasetAssociation model above + + // uncomment this out see log messages + logger : console, + tagName : "div", className : "historyItemContainer", // ................................................................................ SET UP initialize : function( attributes ){ - this.log( this + '.initialize:', this, this.model ); - this.visible = attributes.visible; + this.log( this + '.initialize:', attributes ); + + // render urlTemplates (gen. provided by GalaxyPaths) to urls + if( !attributes.urlTemplates ){ throw( 'HDAView needs urlTemplates on initialize' ); } + this.urls = this.renderUrls( attributes.urlTemplates, this.model.toJSON() ); + + // whether the body of this hda is expanded (shown) + this.expanded = attributes.expanded || false; + + // re-render the entire view on any model change + this.model.bind( 'change', this.render, this ); }, + // urlTemplates is a map (or nested map) of underscore templates (currently, anyhoo) + // use the templates to create the apropo urls for each action this ds could use + renderUrls : function( urlTemplates, modelJson ){ + var hdaView = this, + urls = {}; + _.each( urlTemplates, function( urlTemplateOrObj, urlKey ){ + // object == nested templates: recurse + if( _.isObject( urlTemplateOrObj ) ){ + urls[ urlKey ] = hdaView.renderUrls( urlTemplateOrObj, modelJson ); + + // string == template: + } else { + // meta_down load is a special case (see renderMetaDownloadUrls) + //TODO: should be a better (gen.) way to handle this case + if( urlKey === 'meta_download' ){ + urls[ urlKey ] = hdaView.renderMetaDownloadUrls( urlTemplateOrObj, modelJson ); + } else { + urls[ urlKey ] = _.template( urlTemplateOrObj, modelJson ); + } + } + }); + return urls; + }, + + // there can be more than one meta_file to download, so return a list of url and file_type for each + renderMetaDownloadUrls : function( urlTemplate, modelJson ){ + return _.map( modelJson.meta_files, function( meta_file ){ + return { + url : _.template( urlTemplate, { id: modelJson.id, file_type: meta_file.file_type }), + file_type : meta_file.file_type + }; + }); + }, + // ................................................................................ RENDER MAIN - //??: this style builds an entire, new DOM tree - is that what we want?? render : function(){ - var id = this.model.get( 'id' ), - state = this.model.get( 'state' ); - this.clearReferences(); - + var view = this, + id = this.model.get( 'id' ), + state = this.model.get( 'state' ), + itemWrapper = $( '<div/>' ).attr( 'id', 'historyItem-' + id ); + + this._clearReferences(); this.$el.attr( 'id', 'historyItemContainer-' + id ); - var itemWrapper = $( '<div/>' ).attr( 'id', 'historyItem-' + id ) + itemWrapper .addClass( 'historyItemWrapper' ).addClass( 'historyItem' ) .addClass( 'historyItem-' + state ); @@ -167,33 +524,52 @@ this.body = $( this._render_body() ); itemWrapper.append( this.body ); + //TODO: move to own function: setUpBehaviours + // we can potentially skip this step and call popupmenu directly on the download button + make_popup_menus( itemWrapper ); + // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.) itemWrapper.find( '.tooltip' ).tooltip({ placement : 'bottom' }); - // we can potentially skip this step and call popupmenu directly on the download button - make_popup_menus( itemWrapper ); - - //TODO: better transition/method than this... - this.$el.children().remove(); - return this.$el.append( itemWrapper ); + // transition... + this.$el.fadeOut( 'fast', function(){ + view.$el.children().remove(); + view.$el.append( itemWrapper ).fadeIn( 'fast', function(){ + view.log( view + ' rendered:', view.$el ); + view.trigger( 'rendered' ); + }); + }); + return this; }, - clearReferences : function(){ - //??TODO: best way? + //NOTE: button renderers have the side effect of caching their IconButtonViews to this view + // clear out cached sub-views, dom refs, etc. from prev. render + _clearReferences : function(){ + //??TODO: we should reset these in the button logic checks (i.e. if not needed this.button = null; return null) //?? do we really need these - not so far + //TODO: at least move these to a map this.displayButton = null; this.editButton = null; this.deleteButton = null; this.errButton = null; + this.showParamsButton = null; + this.rerunButton = null; + this.visualizationsButton = null; + this.tagButton = null; + this.annotateButton = null; }, // ................................................................................ RENDER WARNINGS + // hda warnings including: is deleted, is purged, is hidden (including links to further actions (undelete, etc.)) _render_warnings : function(){ // jQ errs on building dom with whitespace - if there are no messages, trim -> '' - return $( jQuery.trim( HistoryItemView.templates.messages( this.model.toJSON() ) ) ); + return $( jQuery.trim( HDAView.templates.messages( + _.extend( this.model.toJSON(), { urls: this.urls } ) + ))); }, // ................................................................................ RENDER TITLEBAR + // the part of an hda always shown (whether the body is expanded or not): title link, title buttons _render_titleBar : function(){ var titleBar = $( '<div class="historyItemTitleBar" style="overflow: hidden"></div>' ); titleBar.append( this._render_titleButtons() ); @@ -203,6 +579,8 @@ }, // ................................................................................ display, edit attr, delete + // icon-button group for the common, most easily accessed actions + //NOTE: these are generally displayed for almost every hda state (tho poss. disabled) _render_titleButtons : function(){ // render the display, edit attr and delete icon-buttons var buttonDiv = $( '<div class="historyItemButtons"></div>' ); @@ -212,31 +590,45 @@ return buttonDiv; }, - //TODO: ?? the three title buttons render for err'd datasets: is this normal? + // icon-button to display this hda in the galaxy main iframe _render_displayButton : function(){ - // don't show display while uploading - if( this.model.get( 'state' ) === HistoryItem.STATES.UPLOAD ){ return null; } + // don't show display if not in final state, error'd, or not accessible + if( ( !this.model.inFinalState() ) + || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR ) + || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.NOT_VIEWABLE ) + || ( !this.model.get( 'accessible' ) ) ){ + return null; + } + var displayBtnData = { + icon_class : 'display' + }; + // show a disabled display if the data's been purged - displayBtnData = ( this.model.get( 'purged' ) )?({ - title : 'Cannot display datasets removed from disk', - enabled : false, - icon_class : 'display' + if( this.model.get( 'purged' ) ){ + displayBtnData.enabled = false; + displayBtnData.title = 'Cannot display datasets removed from disk'; - // if not, render the display icon-button with href - }):({ - title : 'Display data in browser', - href : this.model.get( 'display_url' ), - target : ( this.model.get( 'for_editing' ) )?( 'galaxy_main' ):( null ), - icon_class : 'display' - }); + } else { + displayBtnData.title = 'Display data in browser'; + displayBtnData.href = this.urls.display; + } + + if( this.model.get( 'for_editing' ) ){ + displayBtnData.target = 'galaxy_main'; + } + this.displayButton = new IconButtonView({ model : new IconButton( displayBtnData ) }); return this.displayButton.render().$el; }, + // icon-button to edit the attributes (format, permissions, etc.) this hda _render_editButton : function(){ // don't show edit while uploading, or if editable - if( ( this.model.get( 'state' ) === HistoryItem.STATES.UPLOAD ) + if( ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.UPLOAD ) + || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.ERROR ) + || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.NOT_VIEWABLE ) + || ( !this.model.get( 'accessible' ) ) || ( !this.model.get( 'for_editing' ) ) ){ return null; } @@ -245,7 +637,7 @@ deleted = this.model.get( 'deleted' ), editBtnData = { title : 'Edit attributes', - href : this.model.get( 'edit_url' ), + href : this.urls.edit, target : 'galaxy_main', icon_class : 'edit' }; @@ -254,29 +646,33 @@ //TODO: if for_editing if( deleted || purged ){ editBtnData.enabled = false; - } - if( deleted ){ - editBtnData.title = 'Undelete dataset to edit attributes'; - } else if( purged ){ - editBtnData.title = 'Cannot edit attributes of datasets removed from disk'; + if( purged ){ + editBtnData.title = 'Cannot edit attributes of datasets removed from disk'; + } else if( deleted ){ + editBtnData.title = 'Undelete dataset to edit attributes'; + } } this.editButton = new IconButtonView({ model : new IconButton( editBtnData ) }); return this.editButton.render().$el; }, + // icon-button to delete this hda _render_deleteButton : function(){ - // don't show delete if not editable - if( !this.model.get( 'for_editing' ) ){ return null; } + // don't show delete if... + if( ( !this.model.get( 'for_editing' ) ) + || ( this.model.get( 'state' ) === HistoryDatasetAssociation.STATES.NOT_VIEWABLE ) + || ( !this.model.get( 'accessible' ) ) ){ + return null; + } var deleteBtnData = { title : 'Delete', - href : this.model.get( 'delete_url' ), + href : this.urls[ 'delete' ], id : 'historyItemDeleter-' + this.model.get( 'id' ), icon_class : 'delete' }; - if( ( this.model.get( 'deleted' ) || this.model.get( 'purged' ) ) - && ( !this.model.get( 'delete_url' ) ) ){ + if( this.model.get( 'deleted' ) || this.model.get( 'purged' ) ){ deleteBtnData = { title : 'Dataset is already deleted', icon_class : 'delete', @@ -288,22 +684,27 @@ }, // ................................................................................ titleLink + // render the hid and hda.name as a link (that will expand the body) _render_titleLink : function(){ - return $( jQuery.trim( HistoryItemView.templates.titleLink( this.model.toJSON() ) ) ); + return $( jQuery.trim( HDAView.templates.titleLink( + _.extend( this.model.toJSON(), { urls: this.urls } ) + ))); }, // ................................................................................ RENDER BODY + // render the data/metadata summary (format, size, misc info, etc.) _render_hdaSummary : function(){ - var modelData = this.model.toJSON(); + var modelData = _.extend( this.model.toJSON(), { urls: this.urls } ); // if there's no dbkey and it's editable : pass a flag to the template to render a link to editing in the '?' if( this.model.get( 'metadata_dbkey' ) === '?' && this.model.isEditable() ){ _.extend( modelData, { dbkey_unknown_and_editable : true }); } - return HistoryItemView.templates.hdaSummary( modelData ); + return HDAView.templates.hdaSummary( modelData ); }, // ................................................................................ primary actions + // render the icon-buttons gen. placed underneath the hda summary _render_primaryActionButtons : function( buttonRenderingFuncs ){ var primaryActionButtons = $( '<div/>' ).attr( 'id', 'primary-actions-' + this.model.get( 'id' ) ), view = this; @@ -313,73 +714,124 @@ return primaryActionButtons; }, + // icon-button/popupmenu to down the data (and/or the associated meta files (bai, etc.)) for this hda _render_downloadButton : function(){ // don't show anything if the data's been purged if( this.model.get( 'purged' ) ){ return null; } // return either: a single download icon-button (if there are no meta files) // or a popupmenu with links to download assoc. meta files (if there are meta files) - var downloadLinkHTML = HistoryItemView.templates.downloadLinks( this.model.toJSON() ); + var downloadLinkHTML = HDAView.templates.downloadLinks( + _.extend( this.model.toJSON(), { urls: this.urls } ) + ); //this.log( this + '_render_downloadButton, downloadLinkHTML:', downloadLinkHTML ); return $( downloadLinkHTML ); }, - //NOTE: button renderers have the side effect of caching their IconButtonViews to this view + // icon-button to show the input and output (stdout/err) for the job that created this hda _render_errButton : function(){ - if( ( this.model.get( 'state' ) !== HistoryItem.STATES.ERROR ) + if( ( this.model.get( 'state' ) !== HistoryDatasetAssociation.STATES.ERROR ) || ( !this.model.get( 'for_editing' ) ) ){ return null; } this.errButton = new IconButtonView({ model : new IconButton({ title : 'View or report this error', - href : this.model.get( 'report_error_url' ), + href : this.urls.report_error, target : 'galaxy_main', icon_class : 'bug' })}); return this.errButton.render().$el; }, + // icon-button to show the input and output (stdout/err) for the job that created this hda _render_showParamsButton : function(){ // gen. safe to show in all cases this.showParamsButton = new IconButtonView({ model : new IconButton({ title : 'View details', - href : this.model.get( 'show_params_url' ), + href : this.urls.show_params, target : 'galaxy_main', icon_class : 'information' }) }); return this.showParamsButton.render().$el; }, + // icon-button to re run the job that created this hda _render_rerunButton : function(){ if( !this.model.get( 'for_editing' ) ){ return null; } this.rerunButton = new IconButtonView({ model : new IconButton({ title : 'Run this job again', - href : this.model.get( 'rerun_url' ), + href : this.urls.rerun, target : 'galaxy_main', icon_class : 'arrow-circle' }) }); return this.rerunButton.render().$el; }, - _render_tracksterButton : function(){ - var trackster_urls = this.model.get( 'trackster_urls' ); + // build an icon-button or popupmenu based on the number of applicable visualizations + // also map button/popup clicks to viz setup functions + _render_visualizationsButton : function(){ + var dbkey = this.model.get( 'dbkey' ), + visualizations = this.model.get( 'visualizations' ), + visualization_url = this.urls.visualization, + popup_menu_dict = {}, + params = { + dataset_id: this.model.get( 'id' ), + hda_ldda: 'hda' + }; + if( !( this.model.hasData() ) || !( this.model.get( 'for_editing' ) ) - || !( trackster_urls ) ){ return null; } + || !( visualizations && visualizations.length ) + || !( visualization_url ) ){ + //console.warn( 'NOT rendering visualization icon' ) + return null; + } - this.tracksterButton = new IconButtonView({ model : new IconButton({ - title : 'View in Trackster', + // render the icon from template + this.visualizationsButton = new IconButtonView({ model : new IconButton({ + title : 'Visualize', + href : visualization_url, icon_class : 'chart_curve' })}); - this.errButton.render(); //?? needed? - this.errButton.$el.addClass( 'trackster-add' ).attr({ - 'data-url' : trackster_urls[ 'data-url' ], - 'action-url': trackster_urls[ 'action-url' ], - 'new-url' : trackster_urls[ 'new-url' ] - }); - return this.errButton.$el; + var $icon = this.visualizationsButton.render().$el; + $icon.addClass( 'visualize-icon' ); // needed? + + //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; } + + function create_viz_action( visualization ) { + switch( visualization ){ + case 'trackster': + return create_trackster_action_fn( visualization_url, params, dbkey ); + case 'scatterplot': + return create_scatterplot_action_fn( visualization_url, params ); + default: + return function(){ + window.parent.location = visualization_url + '/' + visualization + '?' + $.param( params ); }; + } + } + + // No need for popup menu because there's a single visualization. + if ( visualizations.length === 1 ) { + $icon.attr( 'title', visualizations[0] ); + $icon.click( create_viz_action( visualizations[0] ) ); + + // >1: Populate menu dict with visualization fns, make the popupmenu + } else { + _.each( visualizations, function( visualization ) { + //TODO: move to utils + var titleCaseVisualization = visualization.charAt( 0 ).toUpperCase() + visualization.slice( 1 ); + popup_menu_dict[ titleCaseVisualization ] = create_viz_action( visualization ); + }); + make_popupmenu( $icon, popup_menu_dict ); + } + return $icon; }, // ................................................................................ secondary actions + // secondary actions: currently tagging and annotation (if user is allowed) _render_secondaryActionButtons : function( buttonRenderingFuncs ){ // move to the right (same level as primary) var secondaryActionButtons = $( '<div/>' ), @@ -394,68 +846,82 @@ return secondaryActionButtons; }, + // icon-button to load and display tagging html + //TODO: these should be a sub-MV _render_tagButton : function(){ if( !( this.model.hasData() ) || !( this.model.get( 'for_editing' ) ) - || ( !this.model.get( 'retag_url' ) ) ){ return null; } + || ( !this.urls.tags.get ) ){ return null; } this.tagButton = new IconButtonView({ model : new IconButton({ title : 'Edit dataset tags', target : 'galaxy_main', - href : this.model.get( 'retag_url' ), + href : this.urls.tags.get, icon_class : 'tags' })}); return this.tagButton.render().$el; }, + // icon-button to load and display annotation html + //TODO: these should be a sub-MV _render_annotateButton : function(){ if( !( this.model.hasData() ) || !( this.model.get( 'for_editing' ) ) - || ( !this.model.get( 'annotate_url' ) ) ){ return null; } + || ( !this.urls.annotation.get ) ){ return null; } this.annotateButton = new IconButtonView({ model : new IconButton({ title : 'Edit dataset annotation', target : 'galaxy_main', - href : this.model.get( 'annotate_url' ), icon_class : 'annotate' })}); return this.annotateButton.render().$el; }, // ................................................................................ other elements - _render_tagArea : function(){ - if( !this.model.get( 'retag_url' ) ){ return null; } - //TODO: move to mvc/tags.js - return $( HistoryItemView.templates.tagArea( this.model.toJSON() ) ); - }, - - _render_annotationArea : function(){ - if( !this.model.get( 'annotate_url' ) ){ return null; } - //TODO: move to mvc/annotations.js - return $( HistoryItemView.templates.annotationArea( this.model.toJSON() ) ); - }, - + // render links to external genome display applications (igb, gbrowse, etc.) + //TODO: not a fan of the style on these _render_displayApps : function(){ - // render links to external genome display applications (igb, gbrowse, etc.) if( !this.model.hasData() ){ return null; } var displayAppsDiv = $( '<div/>' ).addClass( 'display-apps' ); if( !_.isEmpty( this.model.get( 'display_types' ) ) ){ - //this.log( this + 'display_types:', this.model.get( 'display_types' ) ); + //this.log( this + 'display_types:', this.model.get( 'urls' ).display_types ); //TODO:?? does this ever get used? displayAppsDiv.append( - HistoryItemView.templates.displayApps({ displayApps : this.model.toJSON().display_types }) + HDAView.templates.displayApps({ displayApps : this.model.get( 'display_types' ) }) ); } if( !_.isEmpty( this.model.get( 'display_apps' ) ) ){ - //this.log( this + 'display_apps:', this.model.get( 'display_apps' ) ); + //this.log( this + 'display_apps:', this.model.get( 'urls' ).display_apps ); displayAppsDiv.append( - HistoryItemView.templates.displayApps({ displayApps : this.model.toJSON().display_apps }) + HDAView.templates.displayApps({ displayApps : this.model.get( 'display_apps' ) }) ); } return displayAppsDiv; }, + //TODO: into sub-MV + // render the area used to load tag display + _render_tagArea : function(){ + if( !this.urls.tags.set ){ return null; } + //TODO: move to mvc/tags.js + return $( HDAView.templates.tagArea( + _.extend( this.model.toJSON(), { urls: this.urls } ) + )); + }, + + //TODO: into sub-MV + // render the area used to load annotation display + _render_annotationArea : function(){ + if( !this.urls.annotation.get ){ return null; } + //TODO: move to mvc/annotations.js + return $( HDAView.templates.annotationArea( + _.extend( this.model.toJSON(), { urls: this.urls } ) + )); + }, + + // render the data peek + //TODO: curr. pre-formatted into table on the server side - may not be ideal/flexible _render_peek : function(){ if( !this.model.get( 'peek' ) ){ return null; } return $( '<div/>' ).append( @@ -468,6 +934,7 @@ // ................................................................................ state body renderers // _render_body fns for the various states + //TODO: only render these on expansion (or already expanded) _render_body_not_viewable : function( parent ){ //TODO: revisit - still showing display, edit, delete (as common) - that CAN'T be right parent.append( $( '<div>You do not have permission to view dataset.</div>' ) ); @@ -532,7 +999,7 @@ _render_body_failed_metadata : function( parent ){ //TODO: the css for this box is broken (unlike the others) // add a message box about the failure at the top of the body... - parent.append( $( HistoryItemView.templates.failedMetadata( this.model.toJSON() ) ) ); + parent.append( $( HDAView.templates.failedMetadata( this.model.toJSON() ) ) ); //...then render the remaining body as STATES.OK (only diff between these states is the box above) this._render_body_ok( parent ); }, @@ -540,12 +1007,25 @@ _render_body_ok : function( parent ){ // most common state renderer and the most complicated parent.append( this._render_hdaSummary() ); + + // return shortened form if del'd + //TODO: is this correct? maybe only on purged + if( this.model.isDeletedOrPurged() ){ + parent.append( this._render_primaryActionButtons([ + this._render_downloadButton, + this._render_showParamsButton, + this._render_rerunButton + ])); + return; + } + //NOTE: change the order here parent.append( this._render_primaryActionButtons([ this._render_downloadButton, this._render_errButton, this._render_showParamsButton, - this._render_rerunButton + this._render_rerunButton, + this._render_visualizationsButton ])); parent.append( this._render_secondaryActionButtons([ this._render_tagButton, @@ -570,7 +1050,6 @@ _render_body : function(){ //this.log( this + '_render_body' ); - var state = this.model.get( 'state' ); //this.log( 'state:', state, 'for_editing', for_editing ); //TODO: incorrect id (encoded - use hid?) @@ -579,48 +1058,45 @@ .addClass( 'historyItemBody' ) .attr( 'style', 'display: block' ); - //TODO: not a fan of this - switch( state ){ - case HistoryItem.STATES.NOT_VIEWABLE : - this._render_body_not_viewable( body ); + //TODO: not a fan of this dispatch + switch( this.model.get( 'state' ) ){ + case HistoryDatasetAssociation.STATES.NOT_VIEWABLE : + this._render_body_not_viewable( body ); break; - case HistoryItem.STATES.UPLOAD : - this._render_body_uploading( body ); + case HistoryDatasetAssociation.STATES.UPLOAD : + this._render_body_uploading( body ); break; - case HistoryItem.STATES.QUEUED : - this._render_body_queued( body ); + case HistoryDatasetAssociation.STATES.QUEUED : + this._render_body_queued( body ); break; - case HistoryItem.STATES.RUNNING : + case HistoryDatasetAssociation.STATES.RUNNING : this._render_body_running( body ); break; - case HistoryItem.STATES.ERROR : - this._render_body_error( body ); + case HistoryDatasetAssociation.STATES.ERROR : + this._render_body_error( body ); break; - case HistoryItem.STATES.DISCARDED : - this._render_body_discarded( body ); + case HistoryDatasetAssociation.STATES.DISCARDED : + this._render_body_discarded( body ); break; - case HistoryItem.STATES.SETTING_METADATA : - this._render_body_setting_metadata( body ); + case HistoryDatasetAssociation.STATES.SETTING_METADATA : + this._render_body_setting_metadata( body ); break; - case HistoryItem.STATES.EMPTY : - this._render_body_empty( body ); + case HistoryDatasetAssociation.STATES.EMPTY : + this._render_body_empty( body ); break; - case HistoryItem.STATES.FAILED_METADATA : - this._render_body_failed_metadata( body ); + case HistoryDatasetAssociation.STATES.FAILED_METADATA : + this._render_body_failed_metadata( body ); break; - case HistoryItem.STATES.OK : - this._render_body_ok( body ); + case HistoryDatasetAssociation.STATES.OK : + this._render_body_ok( body ); break; default: //??: no body? body.append( $( '<div>Error: unknown dataset state "' + state + '".</div>' ) ); } + body.append( '<div style="clear: both"></div>' ); - body.append( '<div style="clear: both"></div>' ); - if( this.model.get( 'bodyIsShown' ) === false ){ - body.hide(); - } - if( this.visible ){ + if( this.expanded ){ body.show(); } else { body.hide(); @@ -636,6 +1112,8 @@ }, // ................................................................................ STATE CHANGES / MANIPULATION + // find the tag area and, if initial: (via ajax) load the html for displaying them; otherwise, unhide/hide + //TODO: into sub-MV loadAndDisplayTags : function( event ){ //BUG: broken with latest //TODO: this is a drop in from history.mako - should use MV as well @@ -649,7 +1127,7 @@ // Need to fill tag element. $.ajax({ //TODO: the html from this breaks a couple of times - url: this.model.get( 'ajax_get_tag_url' ), + url: this.urls.tags.get, error: function() { alert( "Tagging failed" ); }, success: function(tag_elt_html) { tagElt.html(tag_elt_html); @@ -661,7 +1139,6 @@ // Tag element is filled; show. tagArea.slideDown("fast"); } - } else { // Hide. tagArea.slideUp("fast"); @@ -669,20 +1146,21 @@ return false; }, + // find the annotation area and, if initial: (via ajax) load the html for displaying it; otherwise, unhide/hide + //TODO: into sub-MV loadAndDisplayAnnotation : function( event ){ - //BUG: broken with latest //TODO: this is a drop in from history.mako - should use MV as well this.log( this + '.loadAndDisplayAnnotation', event ); var annotationArea = this.$el.find( '.annotation-area' ), annotationElem = annotationArea.find( '.annotation-elt' ), - setAnnotationUrl = this.model.get( 'ajax_set_annotation_url' ); + setAnnotationUrl = this.urls.annotation.set; // Show or hide annotation area; if showing annotation area and it's empty, fill it. if ( annotationArea.is( ":hidden" ) ){ if( !jQuery.trim( annotationElem.html() ) ){ // Need to fill annotation element. $.ajax({ - url: this.model.get( 'ajax_get_annotation_url' ), + url: this.urls.annotation.get, error: function(){ alert( "Annotations failed" ); }, success: function( htmlFromAjax ){ if( htmlFromAjax === "" ){ @@ -710,253 +1188,264 @@ return false; }, - toggleBodyVisibility : function( visible ){ + // expand/collapse body + //side effect: trigger event + toggleBodyVisibility : function( event, expanded ){ var $body = this.$el.find( '.historyItemBody' ); - if( visible === undefined ){ - $body.toggle(); - } else if( visible ){ - $body.show(); + expanded = ( expanded === undefined )?( !$body.is( ':visible' ) ):( expanded ); + //this.log( 'toggleBodyVisibility, expanded:', expanded, '$body:', $body ); + + if( expanded ){ + $body.slideDown( 'fast' ); } else { - $body.hide(); + $body.slideUp( 'fast' ); } - this.trigger( 'toggleBodyVisibility', this.model.get( 'id' ), $body.is( ':visible' ) ); + this.trigger( 'toggleBodyVisibility', this.model.get( 'id' ), expanded ); }, // ................................................................................ UTILTIY toString : function(){ var modelString = ( this.model )?( this.model + '' ):( '(no model)' ); - return 'HistoryItemView(' + modelString + ')'; + return 'HDAView(' + modelString + ')'; } }); //------------------------------------------------------------------------------ -HistoryItemView.templates = { - warningMsg : Handlebars.templates[ 'template-warningmessagesmall' ], +HDAView.templates = { + warningMsg : Handlebars.templates[ 'template-warningmessagesmall' ], - messages : Handlebars.templates[ 'template-history-warning-messages' ], - titleLink : Handlebars.templates[ 'template-history-titleLink' ], - hdaSummary : Handlebars.templates[ 'template-history-hdaSummary' ], - downloadLinks : Handlebars.templates[ 'template-history-downloadLinks' ], - failedMetadata : Handlebars.templates[ 'template-history-failedMetaData' ], - tagArea : Handlebars.templates[ 'template-history-tagArea' ], - annotationArea : Handlebars.templates[ 'template-history-annotationArea' ], - displayApps : Handlebars.templates[ 'template-history-displayApps' ] + messages : Handlebars.templates[ 'template-history-warning-messages' ], + titleLink : Handlebars.templates[ 'template-history-titleLink' ], + hdaSummary : Handlebars.templates[ 'template-history-hdaSummary' ], + downloadLinks : Handlebars.templates[ 'template-history-downloadLinks' ], + failedMetadata : Handlebars.templates[ 'template-history-failedMetaData' ], + tagArea : Handlebars.templates[ 'template-history-tagArea' ], + annotationArea : Handlebars.templates[ 'template-history-annotationArea' ], + displayApps : Handlebars.templates[ 'template-history-displayApps' ] }; //============================================================================== -var HistoryCollection = Backbone.Collection.extend({ - model : HistoryItem, - - toString : function(){ - return ( 'HistoryCollection()' ); - } -}); +//TODO: these belong somewhere else + +//TODO: should be imported from scatterplot.js +//TODO: OR abstracted to 'load this in the galaxy_main frame' +function create_scatterplot_action_fn( url, params ){ + action = function() { + var galaxy_main = $( window.parent.document ).find( 'iframe#galaxy_main' ), + final_url = url + '/scatterplot?' + $.param(params); + galaxy_main.attr( 'src', final_url ); + //TODO: this needs to go away + $( 'div.popmenu-wrapper' ).remove(); + return false; + }; + return action; +} + +// ----------------------------------------------------------------------------- +// Create trackster action function. +//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; } + $.ajax({ + url: vis_url + '/list_tracks?f-' + $.param(params), + dataType: "html", + error: function() { alert( "Could not add this dataset to browser." ); }, + success: function(table_html) { + var parent = window.parent; + + parent.show_modal("View Data in a New or Saved Visualization", "", { + "Cancel": function() { + parent.hide_modal(); + }, + "View in saved visualization": function() { + // Show new modal with saved visualizations. + parent.show_modal("Add Data to Saved Visualization", table_html, { + "Cancel": function() { + parent.hide_modal(); + }, + "Add to visualization": function() { + $(parent.document).find('input[name=id]:checked').each(function() { + var vis_id = $(this).val(); + dataset_params.id = vis_id; + parent.location = vis_url + "/trackster?" + $.param(dataset_params); + }); + } + }); + }, + "View in new visualization": function() { + parent.location = vis_url + "/trackster?" + $.param(dataset_params); + } + }); + } + }); + return false; + }; +} //============================================================================== -var History = BaseModel.extend( LoggableMixin ).extend({ - //TODO: bind change events from items and collection to this (itemLengths, states) - - // uncomment this out see log messages - //logger : console, - - // values from api (may need more) - defaults : { - id : '', - name : '', - state : '', - //TODO:?? change these to a list of encoded ids? - state_details : { - discarded : 0, - empty : 0, - error : 0, - failed_metadata : 0, - ok : 0, - queued : 0, - running : 0, - setting_metadata: 0, - upload : 0 - }, - - // maybe security issues... - userIsAdmin : false, - userRoles : [], - //TODO: hardcoded - - //TODO: wire this to items - itemsLength : 0, - showDeleted : false, - showHidden : false, - - diskSize : 0, - deleted : false, - - // tagging_common.mako: render_individual_tagging_element(user=trans.get_user(), - // tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20") - tags : [], - annotation : null, - message : null, - quotaMsg : false, - - baseURL : null, - hideDeletedURL : null, - hideHiddenURL : null, - tagURL : null, - annotateURL : null - }, - - initialize : function( data, history_datasets ){ - //this.log( this + '.initialize', data, history_datasets ); - this.items = new HistoryCollection(); - }, - - toJSON : function(){ - // unfortunately, bb doesn't call 'get' to form the JSON meaning computed vals from get aren't used, so... - // a simple example of override and super call - var json = Backbone.Model.prototype.toJSON.call( this ); - json.itemsLength = this.items.length; - //this.log( this + '.json:', json ); - return json; - }, - - loadDatasetsAsHistoryItems : function( datasets ){ - //TODO: add via ajax - multiple datasets at once - // adds the given dataset/Item data to historyItems - // and updates this.state based on their states - //pre: datasets is a list of objs - //this.log( this + '.loadDatasets', datasets ); - var self = this, - selfID = this.get( 'id' ), - stateDetails = this.get( 'state_details' ); - - _.each( datasets, function( dataset, index ){ - //self.log( 'loading dataset: ', dataset, index ); - - // create an item sending along the history_id as well - var historyItem = new HistoryItem( - _.extend( dataset, { history_id: selfID } ) ); - //self.log( 'as History:', historyItem ); - self.items.add( historyItem ); - - // add item's state to running totals in stateDetails - var itemState = dataset.state; - stateDetails[ itemState ] += 1; - }); - - // get overall History state from totals - this.set( 'state_details', stateDetails ); - this._stateFromStateDetails(); - return this; - }, - - _stateFromStateDetails : function(){ - // sets this.state based on current historyItems' states - // ported from api/histories.traverse - //pre: state_details is current counts of dataset/item states - this.set( 'state', '' ); - var stateDetails = this.get( 'state_details' ); - - //TODO: make this more concise - if( ( stateDetails.error > 0 ) - || ( stateDetails.failed_metadata > 0 ) ){ - this.set( 'state', HistoryItem.STATES.ERROR ); - - } else if( ( stateDetails.running > 0 ) - || ( stateDetails.setting_metadata > 0 ) ){ - this.set( 'state', HistoryItem.STATES.RUNNING ); - - } else if( stateDetails.queued > 0 ){ - this.set( 'state', HistoryItem.STATES.QUEUED ); - - } else if( stateDetails.ok === this.items.length ){ - this.set( 'state', HistoryItem.STATES.OK ); - - } else { - throw( '_stateFromStateDetails: unable to determine ' - + 'history state from state details: ' + this.state_details ); - } - return this; - }, - - toString : function(){ - var nameString = ( this.get( 'name' ) )? - ( ',' + this.get( 'name' ) ) : ( '' ); - return 'History(' + this.get( 'id' ) + nameString + ')'; - } -}); - -//------------------------------------------------------------------------------ -// view for the HistoryCollection (as per current right hand panel) +// view for the HDACollection (as per current right hand panel) var HistoryView = BaseView.extend( LoggableMixin ).extend({ // uncomment this out see log messages - //logger : console, + logger : console, // direct attachment to existing element el : 'body.historyPage', - //TODO: add id? - initialize : function(){ - this.log( this + '.initialize:', this ); + // init with the model, urlTemplates, set up storage, bind HDACollection events + //NOTE: this will create or load PersistantStorage keyed under 'HistoryView.<id>' + //pre: you'll need to pass in the urlTemplates (urlTemplates : { history : {...}, hda : {...} }) + initialize : function( attributes ){ + this.log( this + '.initialize:', attributes ); + + // set up url templates + //TODO: prob. better to put this in class scope (as the handlebars templates), but... + // they're added to GalaxyPaths on page load (after this file is loaded) + if( !attributes.urlTemplates ){ throw( 'HDAView needs urlTemplates on initialize' ); } + if( !attributes.urlTemplates.history ){ throw( 'HDAView needs urlTemplates.history on initialize' ); } + if( !attributes.urlTemplates.hda ){ throw( 'HDAView needs urlTemplates.hda on initialize' ); } + this.urlTemplates = attributes.urlTemplates.history; + this.hdaUrlTemplates = attributes.urlTemplates.hda; + // data that needs to be persistant over page refreshes + // (note the key function which uses the history id as well) this.storage = new PersistantStorage( 'HistoryView.' + this.model.get( 'id' ), - { visibleItems : {} } + { expandedHdas : {} } ); - // set up the individual history items/datasets - this.initializeItems(); + //this.model.bind( 'change', this.render, this ); + + // bind events from the model's hda collection + this.model.hdas.bind( 'add', this.add, this ); + this.model.hdas.bind( 'reset', this.addAll, this ); + this.model.hdas.bind( 'all', this.all, this ); + + // set up instance vars + this.hdaViews = {}; + this.urls = {}; }, - initializeItems : function(){ - this.itemViews = {}; - var historyPanel = this; - - // set up a view for each item, init with model and listeners, cache to map ( model.id : view ) - this.model.items.each( function( item ){ - var itemId = item.get( 'id' ), - visible = historyPanel.storage.get( 'visibleItems' ).get( itemId ), - itemView = new HistoryItemView({ - model: item, - visible: visible + add : function( hda ){ + //console.debug( 'add.' + this, hda ); + //TODO + }, + + addAll : function(){ + //console.debug( 'addAll.' + this ); + // re render when all hdas are reset + this.render(); + }, + + all : function( event ){ + //console.debug( 'allItemEvents.' + this, event ); + //...for which to do the debuggings + }, + + // render the urls for this view using urlTemplates and the model data + renderUrls : function( modelJson ){ + var historyView = this; + + historyView.urls = {}; + _.each( this.urlTemplates, function( urlTemplate, urlKey ){ + historyView.urls[ urlKey ] = _.template( urlTemplate, modelJson ); + }); + return historyView.urls; + }, + + // render urls, historyView body, and hdas (if any are shown), fade out, swap, fade in, set up behaviours + render : function(){ + var historyView = this, + setUpQueueName = historyView.toString() + '.set-up', + newRender = $( '<div/>' ), + modelJson = this.model.toJSON(); + + // render the urls and add them to the model json + modelJson.urls = this.renderUrls( modelJson ); + + // render the main template, tooltips + //NOTE: this is done before the items, since item views should handle theirs themselves + newRender.append( HistoryView.templates.historyPanel( modelJson ) ); + historyView.$el.find( '.tooltip' ).tooltip(); + + // render hda views (if any) + if( !this.model.hdas.length + || !this.renderItems( newRender.find( '#' + this.model.get( 'id' ) + '-datasets' ) ) ){ + // if history is empty or no hdas would be rendered, show the empty message + newRender.find( '#emptyHistoryMessage' ).show(); + } + + // fade out existing, swap with the new, fade in, set up behaviours + $( historyView ).queue( setUpQueueName, function( next ){ + historyView.$el.fadeOut( 'fast', function(){ next(); }); + }); + $( historyView ).queue( setUpQueueName, function( next ){ + // swap over from temp div newRender + historyView.$el.html( '' ); + historyView.$el.append( newRender.children() ); + + historyView.$el.fadeIn( 'fast', function(){ next(); }); + }); + $( historyView ).queue( setUpQueueName, function( next ){ + this.log( historyView + ' rendered:', historyView.$el ); + + //TODO: ideally, these would be set up before the fade in (can't because of async save text) + historyView.setUpBehaviours(); + historyView.trigger( 'rendered' ); + next(); + }); + $( historyView ).dequeue( setUpQueueName ); + return this; + }, + + // set up a view for each item to be shown, init with model and listeners, cache to map ( model.id : view ) + renderItems : function( $whereTo ){ + this.hdaViews = {}; + var historyView = this, + show_deleted = this.model.get( 'show_deleted' ), + show_hidden = this.model.get( 'show_hidden' ), + visibleHdas = this.model.hdas.getVisible( show_deleted, show_hidden ); + + // only render the shown hdas + visibleHdas.each( function( hda ){ + var hdaId = hda.get( 'id' ), + expanded = historyView.storage.get( 'expandedHdas' ).get( hdaId ); + historyView.hdaViews[ hdaId ] = new HDAView({ + model : hda, + expanded : expanded, + urlTemplates : historyView.hdaUrlTemplates }); - historyPanel.setUpItemListeners( itemView ); - historyPanel.itemViews[ itemId ] = itemView; + historyView.setUpHdaListeners( historyView.hdaViews[ hdaId ] ); + // render it (NOTE: reverse order, newest on top (prepend)) + //TODO: by default send a reverse order list (although this may be more efficient - it's more confusing) + $whereTo.prepend( historyView.hdaViews[ hdaId ].render().$el ); + }); + return visibleHdas.length; + }, + + // set up HistoryView->HDAView listeners + setUpHdaListeners : function( hdaView ){ + var history = this; + + // use storage to maintain a list of hdas whose bodies are expanded + hdaView.bind( 'toggleBodyVisibility', function( id, visible ){ + if( visible ){ + history.storage.get( 'expandedHdas' ).set( id, true ); + } else { + history.storage.get( 'expandedHdas' ).deleteKey( id ); + } }); }, - setUpItemListeners : function( itemView ){ - var HistoryPanel = this; - - // use storage to maintain a list of items whose bodies are visible - itemView.bind( 'toggleBodyVisibility', function( id, visible ){ - if( visible ){ - HistoryPanel.storage.get( 'visibleItems' ).set( id, true ); - } else { - HistoryPanel.storage.get( 'visibleItems' ).deleteKey( id ); - } - }); - }, - - render : function(){ - this.$el.append( HistoryView.templates.historyPanel( this.model.toJSON() ) ); - this.log( this + ' rendered from template:', this.$el ); - - // set up aliases - this.itemsDiv = this.$el.find( '#' + this.model.get( 'id' ) + '-datasets' ); - - //TODO: set up widgets, tooltips, etc. - async_save_text( - "history-name-container", - "history-name", - this.model.get( 'renameURL' ), - "new_name", - 18 - ); - this.$el.find( '.tooltip' ).tooltip(); - - var historyAnnotationArea = this.$el.find( '#history-annotation-area' ); - $( '#history-annotate' ).click( function() { + // set up js/widget behaviours: tooltips, + //TODO: these should be either sub-MVs, or handled by events + setUpBehaviours : function(){ + // annotation slide down + var historyAnnotationArea = this.$( '#history-annotation-area' ); + this.$( '#history-annotate' ).click( function() { if ( historyAnnotationArea.is( ":hidden" ) ) { historyAnnotationArea.slideDown( "fast" ); } else { @@ -964,77 +1453,60 @@ } return false; }); - async_save_text( - "history-annotation-container", - "history-annotation", - this.model.get( 'annotateURL' ), - "new_annotation", - 18, - true, - 4 - ); - if( this.model.items.length ){ - // render to temp, move all at once, remove temp holder - var tempDiv = this._render_items(); - this.itemsDiv.append( tempDiv.children() ); - tempDiv.remove(); - } - }, + // title and annotation editable text + //NOTE: these use page scoped selectors - so these need to be in the page DOM before they're applicable + async_save_text( "history-name-container", "history-name", + this.urls.rename, "new_name", 18 ); - _render_items : function(){ - var div = $( '<div/>' ), - view = this; - //NOTE!: render in reverse (newest on top) via prepend (instead of append) - _.each( this.itemViews, function( itemView, viewId ){ - view.log( view + '.render_items:', viewId, itemView ); - div.prepend( itemView.render() ); - }); - return div; + async_save_text( "history-annotation-container", "history-annotation", + this.urls.annotate, "new_annotation", 18, true, 4 ); }, events : { - 'click #history-collapse-all' : 'hideAllItemBodies', + 'click #history-collapse-all' : 'hideAllHdaBodies', 'click #history-tag' : 'loadAndDisplayTags' }, - hideAllItemBodies : function(){ + // collapse all hda bodies + hideAllHdaBodies : function(){ _.each( this.itemViews, function( item ){ - item.toggleBodyVisibility( false ); + item.toggleBodyVisibility( null, false ); }); + this.storage.set( 'expandedHdas', {} ); }, + // find the tag area and, if initial: (via ajax) load the html for displaying them; otherwise, unhide/hide + //TODO: into sub-MV loadAndDisplayTags : function( event ){ - //BUG: broken with latest - //TODO: this is a drop in from history.mako - should use MV as well this.log( this + '.loadAndDisplayTags', event ); var tagArea = this.$el.find( '#history-tag-area' ), tagElt = tagArea.find( '.tag-elt' ); this.log( '\t tagArea', tagArea, ' tagElt', tagElt ); - // Show or hide tag area; if showing tag area and it's empty, fill it. + // Show or hide tag area; if showing tag area and it's empty, fill it if( tagArea.is( ":hidden" ) ){ if( !jQuery.trim( tagElt.html() ) ){ var view = this; // Need to fill tag element. $.ajax({ //TODO: the html from this breaks a couple of times - url: this.model.get( 'tagURL' ), + url: view.urls.tag, error: function() { alert( "Tagging failed" ); }, success: function(tag_elt_html) { - view.log( view + ' tag elt html (ajax)', tag_elt_html ); + //view.log( view + ' tag elt html (ajax)', tag_elt_html ); tagElt.html(tag_elt_html); tagElt.find(".tooltip").tooltip(); tagArea.slideDown("fast"); } }); } else { - // Tag element is filled; show. + // Tag element already filled: show tagArea.slideDown("fast"); } } else { - // Hide. + // Currently shown: Hide tagArea.slideUp("fast"); } return false; @@ -1049,12 +1521,10 @@ historyPanel : Handlebars.templates[ 'template-history-historyPanel' ] }; - - //============================================================================== //return { // HistoryItem : HistoryItem, -// HitoryItemView : HistoryItemView, +// HDAView : HDAView, // HistoryCollection : HistoryCollection, // History : History, // HistoryView : HistoryView diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/templates/compiled/template-history-downloadLinks.js --- a/static/scripts/templates/compiled/template-history-downloadLinks.js +++ b/static/scripts/templates/compiled/template-history-downloadLinks.js @@ -7,16 +7,18 @@ function program1(depth0,data) { var buffer = "", stack1, foundHelper; + buffer += "\n"; buffer += "\n<div popupmenu=\"dataset-"; foundHelper = helpers.id; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } buffer += escapeExpression(stack1) + "-popup\">\n <a class=\"action-button\" href=\""; - foundHelper = helpers.download_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.download; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\">Download Dataset</a>\n <a>Additional Files</a>\n "; - stack1 = depth0.meta_files; + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.meta_download; stack1 = helpers.each.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n</div>\n<div style=\"float:left;\" class=\"menubutton split popup\" id=\"dataset-"; @@ -24,36 +26,38 @@ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } buffer += escapeExpression(stack1) + "-popup\">\n <a href=\""; - foundHelper = helpers.download_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.download; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n</div>\n"; return buffer;} function program2(depth0,data) { var buffer = "", stack1, foundHelper; buffer += "\n <a class=\"action-button\" href=\""; - foundHelper = helpers.meta_download_url; + foundHelper = helpers.url; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.meta_download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + else { stack1 = depth0.url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } buffer += escapeExpression(stack1) + "\">Download "; - foundHelper = helpers.meta_file_type; + foundHelper = helpers.file_type; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.meta_file_type; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + else { stack1 = depth0.file_type; stack1 = typeof stack1 === functionType ? stack1() : stack1; } buffer += escapeExpression(stack1) + "</a>\n "; return buffer;} function program4(depth0,data) { - var buffer = "", stack1, foundHelper; + var buffer = "", stack1; + buffer += "\n"; buffer += "\n<a href=\""; - foundHelper = helpers.download_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.download; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n"; return buffer;} - stack1 = depth0.meta_files; + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.meta_download; stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(4, program4, data),fn:self.program(1, program1, data)}); if(stack1 || stack1 === 0) { return stack1; } else { return ''; }}); diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/templates/compiled/template-history-failedMetaData.js --- a/static/scripts/templates/compiled/template-history-failedMetaData.js +++ b/static/scripts/templates/compiled/template-history-failedMetaData.js @@ -6,11 +6,11 @@ function program1(depth0,data) { - var buffer = "", stack1, foundHelper; + var buffer = "", stack1; buffer += "\nAn error occurred setting the metadata for this dataset.\nYou may be able to <a href=\""; - foundHelper = helpers.edit_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.edit_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.edit; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" target=\"galaxy_main\">set it manually or retry auto-detection</a>.\n"; return buffer;} diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/templates/compiled/template-history-hdaSummary.js --- a/static/scripts/templates/compiled/template-history-hdaSummary.js +++ b/static/scripts/templates/compiled/template-history-hdaSummary.js @@ -8,9 +8,9 @@ var buffer = "", stack1, foundHelper; buffer += "\n <a href=\""; - foundHelper = helpers.edit_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.edit_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.edit; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" target=\"galaxy_main\">"; foundHelper = helpers.metadata_dbkey; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/templates/compiled/template-history-historyPanel.js --- a/static/scripts/templates/compiled/template-history-historyPanel.js +++ b/static/scripts/templates/compiled/template-history-historyPanel.js @@ -2,148 +2,130 @@ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; templates['template-history-historyPanel'] = template(function (Handlebars,depth0,helpers,partials,data) { helpers = helpers || Handlebars.helpers; - var buffer = "", stack1, foundHelper, self=this, functionType="function", blockHelperMissing=helpers.blockHelperMissing, escapeExpression=this.escapeExpression; + var buffer = "", stack1, foundHelper, functionType="function", escapeExpression=this.escapeExpression, self=this, blockHelperMissing=helpers.blockHelperMissing; function program1(depth0,data) { + var buffer = "", stack1, foundHelper; + buffer += "\n <div id=\"history-name\" style=\"margin-right: 50px;\" class=\"tooltip editable-text\"\n title=\"Click to rename history\">"; + foundHelper = helpers.name; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "</div>\n "; + return buffer;} + +function program3(depth0,data) { + return "refresh";} -function program3(depth0,data) { +function program5(depth0,data) { return "collapse all";} -function program5(depth0,data) { +function program7(depth0,data) { var buffer = "", stack1, foundHelper; - buffer += "\n <div style=\"width: 40px; float: right; white-space: nowrap;\">\n <a id=\"history-tag\" title=\""; - foundHelper = helpers.local; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(6, program6, data)}); } - else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(6, program6, data)}); } - if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\"\n class=\"icon-button tags tooltip\" target=\"galaxy_main\" href=\"javascript:void(0)\"></a>\n <a id=\"history-annotate\" title=\""; + buffer += "\n <a id=\"history-tag\" title=\""; foundHelper = helpers.local; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(8, program8, data)}); } else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(8, program8, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\"\n class=\"icon-button annotate tooltip\" target=\"galaxy_main\" href=\"javascript:void(0)\"></a>\n </div>\n "; + buffer += "\"\n class=\"icon-button tags tooltip\" target=\"galaxy_main\" href=\"javascript:void(0)\"></a>\n <a id=\"history-annotate\" title=\""; + foundHelper = helpers.local; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)}); } + else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)}); } + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\"\n class=\"icon-button annotate tooltip\" target=\"galaxy_main\" href=\"javascript:void(0)\"></a>\n "; return buffer;} -function program6(depth0,data) { +function program8(depth0,data) { return "Edit history tags";} -function program8(depth0,data) { +function program10(depth0,data) { return "Edit history annotation";} -function program10(depth0,data) { +function program12(depth0,data) { var buffer = "", stack1, foundHelper; - buffer += "\n<div class=\"historyLinks\">\n <a href=\""; - foundHelper = helpers.hideDeletedURL; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.hideDeletedURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += "\n <a href=\""; + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.hide_deleted; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\">"; foundHelper = helpers.local; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); } + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)}); } else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); } + if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "</a>\n</div>\n"; + buffer += "</a>\n "; return buffer;} -function program11(depth0,data) { +function program13(depth0,data) { return "hide deleted";} -function program13(depth0,data) { +function program15(depth0,data) { var buffer = "", stack1, foundHelper; - buffer += "\n<div class=\"historyLinks\">\n <a href=\""; - foundHelper = helpers.hideHiddenURL; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.hideHiddenURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += "\n <a href=\""; + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.hide_hidden; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\">"; foundHelper = helpers.local; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); } + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(16, program16, data)}); } else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); } + if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(16, program16, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "</a>\n</div>\n"; + buffer += "</a>\n "; return buffer;} -function program14(depth0,data) { +function program16(depth0,data) { return "hide hidden";} -function program16(depth0,data) { - - var buffer = "", stack1, foundHelper; - buffer += "\n "; - buffer += "\n <div id=\"history-size\" style=\"position: absolute; top: 3px; right: 0px;\">"; - foundHelper = helpers.diskSize; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.diskSize; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "</div>\n <div id=\"history-name\" style=\"margin-right: 50px;\" class=\"tooltip editable-text\" title=\"Click to rename history\">"; - foundHelper = helpers.name; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "</div>\n \n "; - return buffer;} - function program18(depth0,data) { var buffer = "", stack1, foundHelper; - buffer += "\n <div id=\"history-size\">"; - foundHelper = helpers.diskSize; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.diskSize; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "</div>\n "; - return buffer;} - -function program20(depth0,data) { - - var buffer = "", stack1, foundHelper; buffer += "\n"; foundHelper = helpers.warningmessagesmall; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(21, program21, data)}); } + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(19, program19, data)}); } else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(21, program21, data)}); } + if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(19, program19, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n"; return buffer;} -function program21(depth0,data) { +function program19(depth0,data) { var stack1, foundHelper; foundHelper = helpers.local; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(22, program22, data)}); } + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(20, program20, data)}); } else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(22, program22, data)}); } + if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(20, program20, data)}); } if(stack1 || stack1 === 0) { return stack1; } else { return ''; }} -function program22(depth0,data) { +function program20(depth0,data) { return "You are currently viewing a deleted history!";} -function program24(depth0,data) { +function program22(depth0,data) { var buffer = "", stack1; - buffer += "\n"; - buffer += "\n<div style=\"margin: 0px 5px 10px 5px\">\n\n <div id=\"history-tag-area\" style=\"display: none\">\n "; - buffer += "\n "; - buffer += "\n <strong>Tags:</strong>\n <div class=\"tag-elt\"></div>\n </div>\n\n <div id=\"history-annotation-area\" style=\"display: none\">\n <strong>Annotation / Notes:</strong>\n <div id=\"history-annotation-container\">\n <div id=\"history-annotation\" class=\"tooltip editable-text\" title=\"Click to edit annotation\">\n "; + buffer += "\n <div id=\"history-tag-area\" style=\"display: none\">\n <strong>Tags:</strong>\n <div class=\"tag-elt\"></div>\n </div>\n\n <div id=\"history-annotation-area\" style=\"display: none\">\n <strong>Annotation / Notes:</strong>\n <div id=\"history-annotation-container\">\n <div id=\"history-annotation\" class=\"tooltip editable-text\" title=\"Click to edit annotation\">\n "; stack1 = depth0.annotation; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(27, program27, data),fn:self.program(25, program25, data)}); + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(25, program25, data),fn:self.program(23, program23, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n </div>\n </div>\n </div>\n</div>\n"; + buffer += "\n </div>\n </div>\n </div>\n "; return buffer;} -function program25(depth0,data) { +function program23(depth0,data) { var buffer = "", stack1, foundHelper; buffer += "\n "; @@ -153,12 +135,12 @@ buffer += escapeExpression(stack1) + "\n "; return buffer;} -function program27(depth0,data) { +function program25(depth0,data) { return "\n <em>Describe or add notes to history</em>\n ";} -function program29(depth0,data) { +function program27(depth0,data) { var buffer = "", stack1, foundHelper; buffer += "\n<div id=\"message-container\">\n <div class=\""; @@ -172,92 +154,82 @@ buffer += escapeExpression(stack1) + "\n </div><br />\n</div>\n"; return buffer;} -function program31(depth0,data) { +function program29(depth0,data) { return "\n <div id=\"quota-message\" class=\"errormessage\">\n You are over your disk quota. Tool execution is on hold until your disk usage drops below your allocated quota.\n </div>\n <br/>\n ";} -function program33(depth0,data) { - - var buffer = "", stack1, foundHelper; - buffer += "\n<div id=\""; - foundHelper = helpers.id; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "-datasets\" class=\"history-datasets-list\">\n "; - buffer += "\n</div>\n\n"; - return buffer;} - -function program35(depth0,data) { - - var buffer = "", stack1, foundHelper; - buffer += "\n<div class=\"infomessagesmall\" id=\"emptyHistoryMessage\">\n"; - foundHelper = helpers.local; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(36, program36, data)}); } - else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(36, program36, data)}); } - if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n</div>\n"; - return buffer;} -function program36(depth0,data) { +function program31(depth0,data) { return "Your history is empty. Click 'Get Data' on the left pane to start";} - buffer += "<div id=\"top-links\" class=\"historyLinks\">\n <a title=\""; - foundHelper = helpers.local; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); } - else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); } + buffer += "\n<div id=\"history-name-area\" class=\"historyLinks\">\n <div id=\"history-name-container\" style=\"position: relative;\">\n "; + buffer += "\n <div id=\"history-size\" style=\"position: absolute; top: 3px; right: 0px;\">"; + foundHelper = helpers.nice_size; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.nice_size; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "</div>\n "; + stack1 = depth0.user; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\" class=\"icon-button arrow-circle tooltip\" href=\""; - foundHelper = helpers.baseURL; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.baseURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - buffer += escapeExpression(stack1) + "\"></a>\n <a title='"; + buffer += "\n </div> \n</div>\n<div style=\"clear: both;\"></div>\n\n<div id=\"top-links\" class=\"historyLinks\">\n <a title=\""; foundHelper = helpers.local; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); } else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "' id=\"history-collapse-all\"\n class='icon-button toggle tooltip' href='javascript:void(0);'></a>\n "; - stack1 = depth0.userRoles; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(5, program5, data)}); + buffer += "\" class=\"icon-button arrow-circle tooltip\" href=\""; + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.base; + stack1 = typeof stack1 === functionType ? stack1() : stack1; + buffer += escapeExpression(stack1) + "\"></a>\n <a title='"; + foundHelper = helpers.local; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(5, program5, data)}); } + else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(5, program5, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n</div>\n<div class=\"clear\"></div>\n\n"; - buffer += "\n"; - stack1 = depth0.showDeleted; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)}); + buffer += "' id=\"history-collapse-all\"\n class='icon-button toggle tooltip' href='javascript:void(0);'></a>\n <div style=\"width: 40px; float: right; white-space: nowrap;\">\n "; + stack1 = depth0.user; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(7, program7, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n\n"; - stack1 = depth0.showHidden; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)}); + buffer += "\n </div>\n</div>\n<div style=\"clear: both;\"></div>\n\n"; + buffer += "\n<div class=\"historyLinks\">\n "; + stack1 = depth0.show_deleted; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(12, program12, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n\n"; - buffer += "\n<div id=\"history-name-area\" class=\"historyLinks\">\n <div id=\"history-name-container\" style=\"position: relative;\">\n "; - stack1 = depth0.userRoles; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(18, program18, data),fn:self.program(16, program16, data)}); + buffer += "\n "; + stack1 = depth0.show_hidden; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(15, program15, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n </div> \n</div>\n<div style=\"clear: both;\"></div>\n\n"; + buffer += "\n</div>\n\n"; stack1 = depth0.deleted; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(20, program20, data)}); + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(18, program18, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n\n"; buffer += "\n"; - stack1 = depth0.userRoles; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(24, program24, data)}); + buffer += "\n<div style=\"margin: 0px 5px 10px 5px\">\n\n "; + stack1 = depth0.user; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(22, program22, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n\n"; + buffer += "\n</div>\n\n"; stack1 = depth0.message; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(29, program29, data)}); + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(27, program27, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n\n<div id=\"quota-message-container\">\n "; stack1 = depth0.over_quota; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(31, program31, data)}); + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(29, program29, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } - buffer += "\n</div>\n\n"; - stack1 = depth0.itemsLength; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(35, program35, data),fn:self.program(33, program33, data)}); + buffer += "\n</div>\n\n<div id=\""; + foundHelper = helpers.id; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } + else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + buffer += escapeExpression(stack1) + "-datasets\" class=\"history-datasets-list\"></div>\n\n<div class=\"infomessagesmall\" id=\"emptyHistoryMessage\" style=\"display: none;\">\n "; + foundHelper = helpers.local; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(31, program31, data)}); } + else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(31, program31, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n</div>"; return buffer;}); })(); \ No newline at end of file diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/templates/compiled/template-history-warning-messages.js --- a/static/scripts/templates/compiled/template-history-warning-messages.js +++ b/static/scripts/templates/compiled/template-history-warning-messages.js @@ -6,46 +6,57 @@ function program1(depth0,data) { - var stack1, foundHelper; - foundHelper = helpers.warningmessagesmall; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); } - else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); } + var stack1; + stack1 = depth0.purged; + stack1 = helpers.unless.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(2, program2, data)}); if(stack1 || stack1 === 0) { return stack1; } else { return ''; }} function program2(depth0,data) { - var buffer = "", stack1; - buffer += "\n This dataset has been deleted.\n "; - stack1 = depth0.undelete_url; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); + var buffer = "", stack1, foundHelper; + buffer += "\n"; + foundHelper = helpers.warningmessagesmall; + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); } + else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); } if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n"; return buffer;} function program3(depth0,data) { + var buffer = "", stack1; + buffer += "\n This dataset has been deleted.\n "; + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.undelete; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(4, program4, data)}); + if(stack1 || stack1 === 0) { buffer += stack1; } + buffer += "\n"; + return buffer;} +function program4(depth0,data) { + var buffer = "", stack1, foundHelper; buffer += "\n Click <a href=\""; - foundHelper = helpers.undelete_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.undelete_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.undelete; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" class=\"historyItemUndelete\" id=\"historyItemUndeleter-"; foundHelper = helpers.id; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; } buffer += escapeExpression(stack1) + "\"\n target=\"galaxy_history\">here</a> to undelete it\n "; - stack1 = depth0.purge_url; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(4, program4, data)}); + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.purge; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(5, program5, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n "; return buffer;} -function program4(depth0,data) { +function program5(depth0,data) { var buffer = "", stack1, foundHelper; buffer += "\n or <a href=\""; - foundHelper = helpers.purge_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.purge_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.purge; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" class=\"historyItemPurge\" id=\"historyItemPurger-"; foundHelper = helpers.id; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } @@ -53,45 +64,46 @@ buffer += escapeExpression(stack1) + "\"\n target=\"galaxy_history\">here</a> to immediately remove it from disk\n "; return buffer;} -function program6(depth0,data) { +function program7(depth0,data) { var stack1, foundHelper; foundHelper = helpers.warningmessagesmall; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(7, program7, data)}); } + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(8, program8, data)}); } else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(7, program7, data)}); } + if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(8, program8, data)}); } if(stack1 || stack1 === 0) { return stack1; } else { return ''; }} -function program7(depth0,data) { +function program8(depth0,data) { return "\n This dataset has been deleted and removed from disk.\n";} -function program9(depth0,data) { +function program10(depth0,data) { var stack1, foundHelper; foundHelper = helpers.warningmessagesmall; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)}); } + if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); } else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; } - if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)}); } + if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); } if(stack1 || stack1 === 0) { return stack1; } else { return ''; }} -function program10(depth0,data) { +function program11(depth0,data) { var buffer = "", stack1; buffer += "\n This dataset has been hidden.\n "; - stack1 = depth0.unhide_url; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.unhide; + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(12, program12, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n"; return buffer;} -function program11(depth0,data) { +function program12(depth0,data) { var buffer = "", stack1, foundHelper; buffer += "\n Click <a href=\""; - foundHelper = helpers.unhide_url; - if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } - else { stack1 = depth0.unhide_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; } + stack1 = depth0.urls; + stack1 = stack1 == null || stack1 === false ? stack1 : stack1.unhide; + stack1 = typeof stack1 === functionType ? stack1() : stack1; buffer += escapeExpression(stack1) + "\" class=\"historyItemUnhide\" id=\"historyItemUnhider-"; foundHelper = helpers.id; if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); } @@ -104,11 +116,11 @@ if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n\n"; stack1 = depth0.purged; - stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(6, program6, data)}); + stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(7, program7, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } buffer += "\n\n"; stack1 = depth0.visible; - stack1 = helpers.unless.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(9, program9, data)}); + stack1 = helpers.unless.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)}); if(stack1 || stack1 === 0) { buffer += stack1; } return buffer;}); })(); \ No newline at end of file diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c static/scripts/templates/history-templates.html --- a/static/scripts/templates/history-templates.html +++ b/static/scripts/templates/history-templates.html @@ -1,15 +1,17 @@ <script type="text/template" class="template-history" id="template-history-warning-messages"> -{{#if deleted}}{{#warningmessagesmall}} +{{#if deleted}}{{#unless purged}} +{{#warningmessagesmall}} This dataset has been deleted. - {{#if undelete_url}} - Click <a href="{{ undelete_url }}" class="historyItemUndelete" id="historyItemUndeleter-{{ id }}" + {{#if urls.undelete}} + Click <a href="{{ urls.undelete }}" class="historyItemUndelete" id="historyItemUndeleter-{{ id }}" target="galaxy_history">here</a> to undelete it - {{#if purge_url}} - or <a href="{{ purge_url }}" class="historyItemPurge" id="historyItemPurger-{{ id }}" + {{#if urls.purge}} + or <a href="{{ urls.purge }}" class="historyItemPurge" id="historyItemPurger-{{ id }}" target="galaxy_history">here</a> to immediately remove it from disk {{/if}} {{/if}} -{{/warningmessagesmall}}{{/if}} +{{/warningmessagesmall}} +{{/unless}}{{/if}} {{#if purged}}{{#warningmessagesmall}} This dataset has been deleted and removed from disk. @@ -17,8 +19,8 @@ {{#unless visible}}{{#warningmessagesmall}} This dataset has been hidden. - {{#if unhide_url}} - Click <a href="{{ unhide_url }}" class="historyItemUnhide" id="historyItemUnhider-{{ id }}" + {{#if urls.unhide}} + Click <a href="{{ urls.unhide }}" class="historyItemUnhide" id="historyItemUnhider-{{ id }}" target="galaxy_history">here</a> to unhide it {{/if}} {{/warningmessagesmall}}{{/unless}} @@ -34,7 +36,7 @@ format: <span class="{{ data_type }}">{{ data_type }}</span>, database: {{#if dbkey_unknown_and_editable }} - <a href="{{ edit_url }}" target="galaxy_main">{{ metadata_dbkey }}</a> + <a href="{{ urls.edit }}" target="galaxy_main">{{ metadata_dbkey }}</a> {{else}} <span class="{{ metadata_dbkey }}">{{ metadata_dbkey }}</span> {{/if}} @@ -47,24 +49,26 @@ <script type="text/template" class="template-history" id="template-history-failedMetaData"> {{#warningmessagesmall}} An error occurred setting the metadata for this dataset. -You may be able to <a href="{{ edit_url }}" target="galaxy_main">set it manually or retry auto-detection</a>. +You may be able to <a href="{{ urls.edit }}" target="galaxy_main">set it manually or retry auto-detection</a>. {{/warningmessagesmall}} </script><script type="text/template" class="template-history" id="template-history-downloadLinks"> -{{#if meta_files}} -<div popupmenu="dataset-{{id}}-popup"> - <a class="action-button" href="{{download_url}}">Download Dataset</a> +{{#if urls.meta_download}} +{{! this will be built using a popupmenu }} +<div popupmenu="dataset-{{ id }}-popup"> + <a class="action-button" href="{{ urls.download }}">Download Dataset</a><a>Additional Files</a> - {{#each meta_files}} - <a class="action-button" href="{{meta_download_url}}">Download {{meta_file_type}}</a> + {{#each urls.meta_download}} + <a class="action-button" href="{{ url }}">Download {{ file_type }}</a> {{/each}} </div> -<div style="float:left;" class="menubutton split popup" id="dataset-{{id}}-popup"> - <a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a> +<div style="float:left;" class="menubutton split popup" id="dataset-{{ id }}-popup"> + <a href="{{ urls.download }}" title="Download" class="icon-button disk tooltip"></a></div> {{else}} -<a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a> +{{! otherwise a simple icon button }} +<a href="{{ urls.download }}" title="Download" class="icon-button disk tooltip"></a> {{/if}} </script> @@ -101,61 +105,54 @@ History panel/page - the main container for hdas (gen. on the left hand of the glx page) --><script type="text/template" class="template-history" id="template-history-historyPanel"> +{{! history name (if any) }} +<div id="history-name-area" class="historyLinks"> + <div id="history-name-container" style="position: relative;"> + {{! TODO: factor out conditional css }} + <div id="history-size" style="position: absolute; top: 3px; right: 0px;">{{nice_size}}</div> + {{#if user}} + <div id="history-name" style="margin-right: 50px;" class="tooltip editable-text" + title="Click to rename history">{{name}}</div> + {{/if}} + </div> +</div> +<div style="clear: both;"></div> + <div id="top-links" class="historyLinks"> - <a title="{{#local}}refresh{{/local}}" class="icon-button arrow-circle tooltip" href="{{baseURL}}"></a> + <a title="{{#local}}refresh{{/local}}" class="icon-button arrow-circle tooltip" href="{{urls.base}}"></a><a title='{{#local}}collapse all{{/local}}' id="history-collapse-all" class='icon-button toggle tooltip' href='javascript:void(0);'></a> - {{#if userRoles}} <div style="width: 40px; float: right; white-space: nowrap;"> + {{#if user}} <a id="history-tag" title="{{#local}}Edit history tags{{/local}}" class="icon-button tags tooltip" target="galaxy_main" href="javascript:void(0)"></a><a id="history-annotate" title="{{#local}}Edit history annotation{{/local}}" class="icon-button annotate tooltip" target="galaxy_main" href="javascript:void(0)"></a> + {{/if}} </div> +</div> +<div style="clear: both;"></div> + +{{! TODO: move to js with no reload - use each with historyLinks }} +<div class="historyLinks"> + {{#if show_deleted}} + <a href="{{urls.hide_deleted}}">{{#local}}hide deleted{{/local}}</a> + {{/if}} + {{#if show_hidden}} + <a href="{{urls.hide_hidden}}">{{#local}}hide hidden{{/local}}</a> {{/if}} </div> -<div class="clear"></div> - -{{! TODO: move to js with no reload - use each with historyLinks }} -{{#if showDeleted}} -<div class="historyLinks"> - <a href="{{hideDeletedURL}}">{{#local}}hide deleted{{/local}}</a> -</div> -{{/if}} - -{{#if showHidden}} -<div class="historyLinks"> - <a href="{{hideHiddenURL}}">{{#local}}hide hidden{{/local}}</a> -</div> -{{/if}} - -{{! history name (if any) }} -<div id="history-name-area" class="historyLinks"> - <div id="history-name-container" style="position: relative;"> - {{#if userRoles}} - {{! TODO: factor out conditional css }} - <div id="history-size" style="position: absolute; top: 3px; right: 0px;">{{diskSize}}</div> - <div id="history-name" style="margin-right: 50px;" class="tooltip editable-text" title="Click to rename history">{{name}}</div> - - {{else}} - <div id="history-size">{{diskSize}}</div> - {{/if}} - </div> -</div> -<div style="clear: both;"></div> {{#if deleted}} {{#warningmessagesmall}}{{#local}}You are currently viewing a deleted history!{{/local}}{{/warningmessagesmall}} {{/if}} {{! tags and annotations }} -{{#if userRoles}} {{! TODO: move inline styles out }} <div style="margin: 0px 5px 10px 5px"> + {{#if user}} <div id="history-tag-area" style="display: none"> - {{! load via js render_individual_tagging_element }} - {{! render_individual_tagging_element(user=trans.get_user(), tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20") }} <strong>Tags:</strong><div class="tag-elt"></div></div> @@ -172,8 +169,8 @@ </div></div></div> + {{/if}} </div> -{{/if}} {{#if message}} <div id="message-container"> @@ -192,14 +189,9 @@ {{/if}} </div> -{{#if itemsLength}} -<div id="{{id}}-datasets" class="history-datasets-list"> - {{! NOTE: HistoryItemViews will be appended here }} +<div id="{{id}}-datasets" class="history-datasets-list"></div> + +<div class="infomessagesmall" id="emptyHistoryMessage" style="display: none;"> + {{#local}}Your history is empty. Click 'Get Data' on the left pane to start{{/local}} </div> - -{{else}}{{! no history items }} -<div class="infomessagesmall" id="emptyHistoryMessage"> -{{#local}}Your history is empty. Click 'Get Data' on the left pane to start{{/local}} -</div> -{{/if}} </script> diff -r 0e2eb8ea274a1fedc2620f02adb6bbda81979f53 -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c templates/root/alternate_history.mako --- a/templates/root/alternate_history.mako +++ b/templates/root/alternate_history.mako @@ -1,5 +1,9 @@ <%inherit file="/base.mako"/> +<%def name="title()"> + ${_('Galaxy History')} +</%def> + ## --------------------------------------------------------------------------------------------------------------------- <%def name="create_localization_json( strings_to_localize )"> ## converts strings_to_localize (a list of strings) into a JSON dictionary of { string : localized string } @@ -49,369 +53,233 @@ %></%def> +## --------------------------------------------------------------------------------------------------------------------- +## all the possible history urls (primarily from web controllers at this point) +<%def name="get_history_url_templates()"> +<% + from urllib import unquote_plus + + history_class_name = history.__class__.__name__ + encoded_id_template = '<%= id %>' + + url_dict = { + # TODO:?? next 3 needed? + 'base' : h.url_for( controller="/history" ), + ##TODO: move these into the historyMV + 'hide_deleted' : h.url_for( controller="/history", show_deleted=False ), + 'hide_hidden' : h.url_for( controller="/history", show_hidden=False ), + + ##TODO: into their own MVs + 'rename' : h.url_for( controller="/history", action="rename_async", + id=encoded_id_template ), + 'tag' : h.url_for( controller='tag', action='get_tagging_elt_async', + item_class=history_class_name, item_id=encoded_id_template ), + 'annotate' : h.url_for( controller="/history", action="annotate_async", + id=encoded_id_template ) + } +%> +${ unquote_plus( h.to_json_string( url_dict ) ) } +</%def> ## --------------------------------------------------------------------------------------------------------------------- -<%def name="get_urls_for_hda( hda, encoded_data_id, for_editing )"> +## all the possible hda urls (primarily from web controllers at this point) - whether they should have them or not +##TODO: unify url_for btwn web, api +<%def name="get_hda_url_templates()"><% - from galaxy.datatypes.metadata import FileParameter - #print '\n', hda.name + from urllib import unquote_plus - data_dict = {} - def add_to_data( **kwargs ): - data_dict.update( kwargs ) - - #TODO??: better way to do urls (move into js galaxy_paths (decorate) - _not_ dataset specific) - deleted = hda.deleted - purged = hda.purged - - # ................................................................ link actions - #purged = purged or hda.dataset.purged //?? - # all of these urls are 'datasets/data_id/<action> - if not ( dataset_purged or purged ) and for_editing: - add_to_data( undelete_url=h.url_for( controller='dataset', action='undelete', dataset_id=encoded_data_id ) ) - # trans - if trans.app.config.allow_user_dataset_purge: - add_to_data( purge_url=h.url_for( controller='dataset', action='purge', dataset_id=encoded_data_id ) ) - - if not hda.visible: - add_to_data( unhide_url=h.url_for( controller='dataset', action='unhide', dataset_id=encoded_data_id ) ) - - - # ................................................................ title actions (display, edit, delete) - display_url = '' - if for_editing: - display_url = h.url_for( controller='dataset', action='display', dataset_id=encoded_data_id, preview=True, filename='' ) - else: - # Get URL for display only. - if hda.history.user and hda.history.user.username: - display_url = h.url_for( controller='dataset', action='display_by_username_and_slug', - username=hda.history.user.username, slug=encoded_data_id, filename='' ) - else: - # HACK: revert to for_editing display URL when there is no user/username. This should only happen when - # there's no user/username because dataset is being displayed by history/view after error reported. - # There are no security concerns here because both dataset/display and dataset/display_by_username_and_slug - # check user permissions (to the same degree) before displaying. - display_url = h.url_for( controller='dataset', action='display', dataset_id=encoded_data_id, preview=True, filename='' ) - add_to_data( display_url=display_url ) - - # edit attr button - if for_editing: - if not( hda.deleted or hda.purged ): - edit_url = h.url_for( controller='dataset', action='edit', - dataset_id=encoded_data_id ) - add_to_data( edit_url=edit_url ) - - # delete button - if for_editing and not ( deleted or dataset_purged or purged ): - delete_url = h.url_for( controller='dataset', action='delete', - dataset_id=encoded_data_id, - show_deleted_on_refresh=show_deleted ) - add_to_data( delete_url=delete_url ) - - # ................................................................ primary actions (error, info, download) - # download links (hda and associated meta files) - if not hda.purged: - add_to_data( download_url=h.url_for( controller='/dataset', action='display', - dataset_id=encoded_data_id, to_ext=hda.ext ) ) - - meta_files = [] - for k in hda.metadata.spec.keys(): - if isinstance( hda.metadata.spec[ k ].param, FileParameter ): - file_type = k - download_url = h.url_for( controller='/dataset', action='get_metadata_file', - hda_id=encoded_data_id, metadata_name=file_type ) - meta_files.append( dict( meta_file_type=file_type, meta_download_url=download_url ) ) - - if meta_files: - add_to_data( meta_files=meta_files ) - - # error report - if for_editing: - #NOTE: no state == 'error' check - ##TODO: has to have an _UN_ encoded id - #report_error_url = h.url_for( controller='dataset', action='errors', id=encoded_data_id ) - report_error_url = h.url_for( controller='dataset', action='errors', id=hda.id ) - add_to_data( report_error_url=report_error_url ) - - # info/params - show_params_url = h.url_for( controller='dataset', action='show_params', dataset_id=encoded_data_id ) - add_to_data( show_params_url=show_params_url ) - - # rerun - if for_editing: - ##TODO: has to have an _UN_ encoded id - #rerun_url = h.url_for( controller='tool_runner', action='rerun', id=encoded_data_id ) - rerun_url = h.url_for( controller='tool_runner', action='rerun', id=hda.id ) - add_to_data( rerun_url=rerun_url ) - - # visualizations - if hda.ext in app.datatypes_registry.get_available_tracks(): - # do these need _localized_ dbkeys? - trackster_urls = {} - if hda.dbkey != '?': - data_url = h.url_for( controller='visualization', action='list_tracks', dbkey=hda.dbkey ) - data_url = hda.replace( 'dbkey', 'f-dbkey' ) - else: - data_url = h.url_for( controller='visualization', action='list_tracks' ) - trackster_urls[ 'hda-url' ] = data_url - trackster_urls[ 'action-url' ] = h.url_for( controller='visualization', action='trackster', dataset_id=encoded_data_id ) - trackster_urls[ 'new-url' ] = h.url_for( controller='visualization', action='trackster', dataset_id=encoded_data_id, default_dbkey=hda.dbkey ) - add_to_data( trackster_url=trackster_urls ) - - # display apps (igv, uscs) - display_types = [] - display_apps = [] - if( hda.state in [ 'ok', 'failed_metadata' ] - and hda.has_data() ): - #NOTE: these two data share structures - #TODO: this doesn't seem to get called with the hda I'm using. What would call this? How can I spoof it? - for display_type in hda.datatype.get_display_types(): - display_label = hda.datatype.get_display_label( display_type ) - target_frame, display_links = hda.datatype.get_display_links( hda, display_type, app, request.base ) - if display_links: - display_links = [] - for display_name, display_href in display_links: - display_type_link = dict( - target = target_frame, - href = display_href, - text = display_name - ) - display_links.append( display_type_link ) - - # append the link list to the main map using the display_label - display_types.append( dict( label=display_label, links=display_links ) ) + hda_class_name = 'HistoryDatasetAssociation' + encoded_id_template = '<%= id %>' + username_template = '<%= username %>' + hda_ext_template = '<%= file_ext %>' + meta_type_template = '<%= file_type %>' - for display_app in hda.get_display_applications( trans ).itervalues(): - app_links = [] - for display_app_link in display_app.links.itervalues(): - app_link = dict( - target = display_app_link.url.get( 'target_frame', '_blank' ), - href = display_app_link.get_display_url( hda, trans ), - text = _( display_app_link.name ) - ) - app_links.append( app_link ) - - display_apps.append( dict( label=display_app.name, links=app_links ) ) - - # attach the display types and apps (if any) to the hda obj - #if display_types: print 'display_types:', display_types - #if display_apps: print 'display_apps:', display_apps - add_to_data( display_types=display_types ) - add_to_data( display_apps=display_apps ) + url_dict = { + # ................................................................ warning message links + 'purge' : h.url_for( controller='dataset', action='purge', + dataset_id=encoded_id_template ), + #TODO: hide (via api) + 'unhide' : h.url_for( controller='dataset', action='unhide', + dataset_id=encoded_id_template ), + #TODO: via api + 'undelete' : h.url_for( controller='dataset', action='undelete', + dataset_id=encoded_id_template ), - # ................................................................ secondary actions (tagging, annotation) - if trans.user: - add_to_data( ajax_get_tag_url=( h.url_for( - controller='tag', action='get_tagging_elt_async', - item_class=hda.__class__.__name__, item_id=encoded_data_id ) ) ) - add_to_data( retag_url=( h.url_for( - controller='tag', action='retag', - item_class=hda.__class__.__name__, item_id=encoded_data_id ) ) ) - - add_to_data( annotate_url=( h.url_for( controller='dataset', action='annotate', id=encoded_data_id ) ) ) - add_to_data( ajax_get_annotation_url=( h.url_for( - controller='dataset', action='get_annotation_async', id=encoded_data_id ) ) ) - add_to_data( ajax_set_annotation_url=( h.url_for( - controller='/dataset', action='annotate_async', id=encoded_data_id ) ) ) - - return data_dict + # ................................................................ title actions (display, edit, delete), + 'display' : h.url_for( controller='dataset', action='display', + dataset_id=encoded_id_template, preview=True, filename='' ), + #'user_display_url' : h.url_for( controller='dataset', action='display_by_username_and_slug', + # username=username_template, slug=encoded_id_template, filename='' ), + 'edit' : h.url_for( controller='dataset', action='edit', + dataset_id=encoded_id_template ), + + #TODO: via api + #TODO: show deleted handled by history + 'delete' : h.url_for( controller='dataset', action='delete', + dataset_id=encoded_id_template, show_deleted_on_refresh=show_deleted ), + + # ................................................................ download links (and associated meta files), + 'download' : h.url_for( controller='/dataset', action='display', + dataset_id=encoded_id_template, to_ext=hda_ext_template ), + 'meta_download' : h.url_for( controller='/dataset', action='get_metadata_file', + hda_id=encoded_id_template, metadata_name=meta_type_template ), + + # ................................................................ primary actions (errors, params, rerun), + 'report_error' : h.url_for( controller='dataset', action='errors', + id=encoded_id_template ), + 'show_params' : h.url_for( controller='dataset', action='show_params', + dataset_id=encoded_id_template ), + 'rerun' : h.url_for( controller='tool_runner', action='rerun', + id=encoded_id_template ), + 'visualization' : h.url_for( controller='visualization' ), + + # ................................................................ secondary actions (tagging, annotation), + 'tags' : { + 'get' : h.url_for( controller='tag', action='get_tagging_elt_async', + item_class=hda_class_name, item_id=encoded_id_template ), + 'set' : h.url_for( controller='tag', action='retag', + item_class=hda_class_name, item_id=encoded_id_template ), + }, + 'annotation' : { + #'annotate_url' : h.url_for( controller='dataset', action='annotate', + # id=encoded_id_template ), # doesn't look like this is used (unless graceful degradation) + 'get' : h.url_for( controller='dataset', action='get_annotation_async', + id=encoded_id_template ), + 'set' : h.url_for( controller='/dataset', action='annotate_async', + id=encoded_id_template ), + }, + } +%> +${ unquote_plus( h.to_json_string( url_dict ) ) } +</%def> + +## ----------------------------------------------------------------------------- +## get the history, hda, user data from the api (as opposed to the web controllers/mako) + +## I'd rather do without these (esp. the get_hdas which hits the db twice) +## but we'd need a common map producer (something like get_api_value but more complete) +##TODO: api/web controllers should use common code, and this section should call that code +<%def name="get_history( id )"> +<% + return trans.webapp.api_controllers[ 'histories' ].show( trans, trans.security.encode_id( id ) ) %></%def> -<%def name="prep_hda( data, for_editing )"> +<%def name="get_current_user()"><% - from pprint import pformat - ## 'datasets' passed from root.history are HistoryDatasetAssociations - ## these datas _have_ a Dataset (data.dataset) - #ported mostly from history_common - #post: return dictionary form - #??: move out of templates? - #??: gather data from model? - - DATASET_STATE = trans.app.model.Dataset.states - # {'OK': 'ok', 'FAILED_METADATA': 'failed_metadata', 'UPLOAD': 'upload', - # 'DISCARDED': 'discarded', 'RUNNING': 'running', 'SETTING_METADATA': 'setting_metadata', - # 'ERROR': 'error', 'NEW': 'new', 'QUEUED': 'queued', 'EMPTY': 'empty'} - #TODO: move to Dataset.states? how often are these used? - STATES_INTERPRETED_AS_QUEUED = [ 'no state', '', None ] - - #TODO: clean up magic strings - #TODO: format to 120 - data_dict = data.get_api_value() - - # convert/re-format api values as needed - #TODO: use data_dict.update to add these (instead of localvars) - def add_to_data( **kwargs ): - data_dict.update( kwargs ) - - # trans - add_to_data( hid=data.hid ) - encoded_data_id = trans.security.encode_id( data.id ) - add_to_data( id=encoded_data_id ) - - # localize dbkey - data_dict[ 'metadata_dbkey' ] = _( data_dict[ 'metadata_dbkey' ] ) - - add_to_data( state=data.state ) - if data_state in STATES_INTERPRETED_AS_QUEUED: - #TODO: magic string - add_to_data( state=DATASET_STATE.QUEUED ) - - # trans - current_user_roles = trans.get_current_user_roles() - add_to_data( can_edit=( not ( data.deleted or data.purged ) ) ) - - # considered accessible if user can access or user isn't admin - # trans - accessible = trans.app.security_agent.can_access_dataset( current_user_roles, data.dataset ) - accessible = trans.user_is_admin() or accessible - add_to_data( accessible=accessible ) - - url_dict = get_urls_for_hda( data, encoded_data_id, for_editing ) - data_dict.update( url_dict ) - #print 'url_dict:', pformat( url_dict, indent=2 ) - #print 'data_dict:', pformat( data_dict, indent=2 ), "\n" - #print data_dict - - if data.peek != "no peek": - add_to_data( peek=( _( h.to_unicode( data.display_peek() ) ) ) ) - - return data_dict + if not trans.user: + return '{}' + return trans.webapp.api_controllers[ 'users' ].show( + trans, trans.security.encode_id( trans.user.id ) ) %></%def> -##TODO: remove after filling tags.js -<%namespace file="../tagging_common.mako" import="render_individual_tagging_element" /> -<%def name="context_to_js()"> +<%def name="get_hdas( history_id, hdas )"><% - ##print 'context', context, dir( context ) - ##print 'context.kwargs', context.kwargs - ##print 'history:', history - - ##TODO: move to API - - for_editing = True - encoded_history_id = trans.security.encode_id( history.id ) - context_dict = { - 'history' : { - 'id' : encoded_history_id, - 'name' : history.name, - - 'status' : status, - 'showDeleted' : show_deleted, - 'showHidden' : show_hidden, - 'quotaMsg' : over_quota, - 'message' : message, ##'go outside' - - 'deleted' : history.deleted, - 'diskSize' : history.get_disk_size( nice_size=True ), - - ## maybe security issues... - 'userIsAdmin' : trans.user_is_admin(), - 'userRoles' : [ role.get_api_value() for role in trans.get_current_user_roles() ], - - ##tagging_common.mako: render_individual_tagging_element(user=trans.get_user(), - ## tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20") - 'tags' : [], - ##TODO: broken - of course - ##TODO: remove after filling tags.js - ##'tagHTML' : render_individual_tagging_element( - ## user=trans.get_user(), - ## tagged_item=history, - ## elt_context="history.mako", - ## use_toggle_link=False, - ## input_size="20"), - ##TODO:?? h.to_unicode( annotation ) | h - 'annotation' : h.to_unicode( annotation ), - - ##TODO: broken - 'baseURL' : h.url_for( controller="/history", show_deleted=show_deleted ), - 'hideDeletedURL' : h.url_for( controller="/history", show_deleted=False ), - 'hideHiddenURL' : h.url_for( controller="/history", show_hidden=False ), - 'renameURL' : h.url_for( controller="/history", action="rename_async", id=encoded_history_id ), - 'tagURL' : h.url_for( controller='tag', action='get_tagging_elt_async', - item_class=history.__class__.__name__, item_id=encoded_history_id ), - 'annotateURL' : h.url_for( controller="/history", action="annotate_async", id=encoded_history_id ) - }, - 'hdas' : [ prep_hda( hda, for_editing ) for hda in datasets ], - - # some of these may be unneeded when all is said and done... - 'hdaId' : hda_id, - 'forEditing' : for_editing, - } + if not hdas: + return '[]' + # rather just use the history.id (wo the datasets), but... + #BUG: one inaccessible dataset will error entire list + return trans.webapp.api_controllers[ 'history_contents' ].index( + trans, trans.security.encode_id( history_id ), + ids=( ','.join([ trans.security.encode_id( hda.id ) for hda in hdas ]) ) ) %> -${ h.to_json_string( context_dict ) } </%def> +<%def name="print_visualizations( datasets )"> +<% + for dataset in datasets: + print trans.security.encode_id( dataset.id ) + print dataset.get_visualizations() + +%> +</%def> + +## ----------------------------------------------------------------------------- <%def name="javascripts()"> - ${parent.javascripts()} +${parent.javascripts()} + +${h.js( + "libs/jquery/jstorage", + "libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging", + "libs/json2", + "libs/backbone/backbone-relational", + "mvc/base-mvc", "mvc/ui" +)} + +${h.templates( + "helpers-common-templates", + "template-warningmessagesmall", - ${h.js( - "libs/jquery/jstorage", - "libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging", - "libs/json2", - "mvc/base-mvc", "mvc/ui" - )} + "template-history-warning-messages", + "template-history-titleLink", + "template-history-failedMetadata", + "template-history-hdaSummary", + "template-history-downloadLinks", + "template-history-tagArea", + "template-history-annotationArea", + "template-history-displayApps", + + "template-history-historyPanel" +)} - ${h.templates( - "helpers-common-templates", - "template-warningmessagesmall", +##TODO: fix: curr hasta be _after_ h.templates - move somehow +${h.js( + "mvc/history" + ##"mvc/tags", "mvc/annotations" +)} + +<script type="text/javascript"> +// set js localizable strings +GalaxyLocalization.setLocalizedString( ${ create_localization_json( get_page_localized_strings() ) } ); + +// add needed controller urls to GalaxyPaths +galaxy_paths.set( 'hda', ${get_hda_url_templates()} ); +galaxy_paths.set( 'history', ${get_history_url_templates()} ); + +$(function(){ + + // ostensibly, this is the App + if( console && console.debug ){ + //if( console.clear ){ console.clear(); } + console.debug( 'using backbone.js in history panel' ); + } + + // Navigate to a dataset. + console.debug( 'getting data' ); + var user = ${ get_current_user() }, + history = ${ get_history( history.id ) }, + hdas = ${ get_hdas( history.id, datasets ) }; + //console.debug( 'user:', user ); + //console.debug( 'history:', history ); + //console.debug( 'hdas:', hdas ); + + // i don't like this, but user authentication changes views/behaviour + history.user = user; + history.show_deleted = ${ 'true' if show_deleted else 'false' }; + history.show_hidden = ${ 'true' if show_hidden else 'false' }; - "template-history-warning-messages", - "template-history-titleLink", - "template-history-failedMetadata", - "template-history-hdaSummary", - "template-history-downloadLinks", - "template-history-tagArea", - "template-history-annotationArea", - "template-history-displayApps", - - "template-history-historyPanel" - )} + //console.debug( 'galaxy_paths:', galaxy_paths ); + var glx_history = new History( history, hdas ); + var glx_history_view = new HistoryView({ model: glx_history, urlTemplates: galaxy_paths.attributes }).render(); + + //var glx_history = new History().setPaths( galaxy_paths ), + // glx_history_view = new HistoryView({ model: glx_history }); + //console.warn( 'fetching' ); + //glx_history.loadFromAPI( pageData.history.id ); - ##TODO: fix: curr hasta be _after_ h.templates - move somehow - ${h.js( - "mvc/history" - ##"mvc/tags", "mvc/annotations" - )} - - <script type="text/javascript"> - GalaxyLocalization.setLocalizedString( ${ create_localization_json( get_page_localized_strings() ) } ); - // add needed controller urls to GalaxyPaths - galaxy_paths.set( 'dataset_path', "${h.url_for( controller='dataset' )}" ) - - // Init. on document load. - var pageData = ${context_to_js()}; - if( console && console.debug ){ - window.pageData = pageData; - - ##_.each( pageData.hdas, function( hda ){ - ## console.debug( hda ); - ##}); - } - - // on ready - USE_CURR_DATA = true; - $(function(){ - if( console && console.debug ){ console.debug( 'using backbone.js in history panel' ); } - - if ( window.USE_CURR_DATA ){ - // Navigate to a dataset. - if( pageData.hdaId ){ - self.location = "#" + pageData.hdaId; - } - var glx_history = new History( pageData.history ).loadDatasetsAsHistoryItems( pageData.hdas ), - glx_history_view = new HistoryView({ model: glx_history }); - glx_history_view.render(); - window.glx_history = glx_history; window.glx_history_view = glx_history_view; - - return; - - } else { - // sandbox - } - }); - </script> + if( console && console.debug ){ + window.user = top.user = user; + window._history = top._history = history; + window.hdas = top.hdas = hdas; + window.glx_history = top.glx_history = glx_history; + window.glx_history_view = top.glx_history_view = glx_history_view; + top.storage = jQuery.jStorage + } + + return; +}); +</script></%def> @@ -453,8 +321,4 @@ </noscript></%def> -<%def name="title()"> - ${_('Galaxy History')} -</%def> - <body class="historyPage"></body> https://bitbucket.org/galaxy/galaxy-central/changeset/2e70816299e4/ changeset: 2e70816299e4 user: carlfeberhard date: 2012-10-30 21:42:11 summary: pack scripts affected #: 6 files diff -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c -r 2e70816299e40fecc4902adda54126bb00316588 static/scripts/packed/mvc/history.js --- a/static/scripts/packed/mvc/history.js +++ b/static/scripts/packed/mvc/history.js @@ -1,1 +1,1 @@ -var HistoryItem=BaseModel.extend(LoggableMixin).extend({defaults:{id:null,name:"",data_type:null,file_size:0,genome_build:null,metadata_data_lines:0,metadata_dbkey:null,metadata_sequences:0,misc_blurb:"",misc_info:"",model_class:"",state:"",deleted:false,purged:false,visible:true,for_editing:true,bodyIsShown:false},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryItem.STATES.NOT_VIEWABLE)}},isEditable:function(){return(!(this.get("deleted")||this.get("purged")))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryItem("+a+")"}});HistoryItem.STATES={NOT_VIEWABLE:"not_viewable",NEW:"new",UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",OK:"ok",EMPTY:"empty",ERROR:"error",DISCARDED:"discarded",SETTING_METADATA:"setting_metadata",FAILED_METADATA:"failed_metadata"};var HistoryItemView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(a){this.log(this+".initialize:",this,this.model);this.visible=a.visible},render:function(){var c=this.model.get("id"),b=this.model.get("state");this.clearReferences();this.$el.attr("id","historyItemContainer-"+c);var a=$("<div/>").attr("id","historyItem-"+c).addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+b);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);a.find(".tooltip").tooltip({placement:"bottom"});make_popup_menus(a);this.$el.children().remove();return this.$el.append(a)},clearReferences:function(){this.displayButton=null;this.editButton=null;this.deleteButton=null;this.errButton=null},_render_warnings:function(){return $(jQuery.trim(HistoryItemView.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());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_displayButton:function(){if(this.model.get("state")===HistoryItem.STATES.UPLOAD){return null}displayBtnData=(this.model.get("purged"))?({title:"Cannot display datasets removed from disk",enabled:false,icon_class:"display"}):({title:"Display data in browser",href:this.model.get("display_url"),target:(this.model.get("for_editing"))?("galaxy_main"):(null),icon_class:"display"});this.displayButton=new IconButtonView({model:new IconButton(displayBtnData)});return this.displayButton.render().$el},_render_editButton:function(){if((this.model.get("state")===HistoryItem.STATES.UPLOAD)||(!this.model.get("for_editing"))){return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:"Edit attributes",href:this.model.get("edit_url"),target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false}if(a){b.title="Undelete dataset to edit attributes"}else{if(c){b.title="Cannot edit attributes of datasets removed from disk"}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if(!this.model.get("for_editing")){return null}var a={title:"Delete",href:this.model.get("delete_url"),id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if((this.model.get("deleted")||this.model.get("purged"))&&(!this.model.get("delete_url"))){a={title:"Dataset is already deleted",icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HistoryItemView.templates.titleLink(this.model.toJSON())))},_render_hdaSummary:function(){var a=this.model.toJSON();if(this.model.get("metadata_dbkey")==="?"&&this.model.isEditable()){_.extend(a,{dbkey_unknown_and_editable:true})}return HistoryItemView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var b=$("<div/>").attr("id","primary-actions-"+this.model.get("id")),a=this;_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")){return null}var a=HistoryItemView.templates.downloadLinks(this.model.toJSON());return $(a)},_render_errButton:function(){if((this.model.get("state")!==HistoryItem.STATES.ERROR)||(!this.model.get("for_editing"))){return null}this.errButton=new IconButtonView({model:new IconButton({title:"View or report this error",href:this.model.get("report_error_url"),target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:"View details",href:this.model.get("show_params_url"),target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_rerunButton:function(){if(!this.model.get("for_editing")){return null}this.rerunButton=new IconButtonView({model:new IconButton({title:"Run this job again",href:this.model.get("rerun_url"),target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_tracksterButton:function(){var a=this.model.get("trackster_urls");if(!(this.model.hasData())||!(this.model.get("for_editing"))||!(a)){return null}this.tracksterButton=new IconButtonView({model:new IconButton({title:"View in Trackster",icon_class:"chart_curve"})});this.errButton.render();this.errButton.$el.addClass("trackster-add").attr({"data-url":a["data-url"],"action-url":a["action-url"],"new-url":a["new-url"]});return this.errButton.$el},_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.model.get("for_editing"))||(!this.model.get("retag_url"))){return null}this.tagButton=new IconButtonView({model:new IconButton({title:"Edit dataset tags",target:"galaxy_main",href:this.model.get("retag_url"),icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("annotate_url"))){return null}this.annotateButton=new IconButtonView({model:new IconButton({title:"Edit dataset annotation",target:"galaxy_main",href:this.model.get("annotate_url"),icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.model.get("retag_url")){return null}return $(HistoryItemView.templates.tagArea(this.model.toJSON()))},_render_annotationArea:function(){if(!this.model.get("annotate_url")){return null}return $(HistoryItemView.templates.annotationArea(this.model.toJSON()))},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_types}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().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_not_viewable:function(a){a.append($("<div>You do not have permission to view dataset.</div>"))},_render_body_uploading:function(a){a.append($("<div>Dataset is uploading</div>"))},_render_body_queued:function(a){a.append($("<div>Job is waiting to run.</div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_running:function(a){a.append("<div>Job is currently running.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append(("An error occurred running this job: <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]))},_render_body_discarded:function(a){a.append("<div>The job creating this dataset was cancelled before completion.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_setting_metadata:function(a){a.append($("<div>Metadata is being auto-detected.</div>"))},_render_body_empty:function(a){a.append($("<div>No data: <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_failed_metadata:function(a){a.append($(HistoryItemView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]));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())},_render_body:function(){var b=this.model.get("state");var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(b){case HistoryItem.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryItem.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryItem.STATES.QUEUED:this._render_body_queued(a);break;case HistoryItem.STATES.RUNNING:this._render_body_running(a);break;case HistoryItem.STATES.ERROR:this._render_body_error(a);break;case HistoryItem.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryItem.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryItem.STATES.EMPTY:this._render_body_empty(a);break;case HistoryItem.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryItem.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+b+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.model.get("bodyIsShown")===false){a.hide()}if(this.visible){a.show()}else{a.hide()}return a},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.model.get("ajax_get_tag_url"),error:function(){alert("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.model.get("ajax_set_annotation_url");if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.model.get("ajax_get_annotation_url"),error:function(){alert("Annotations failed")},success:function(e){if(e===""){e="<em>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},toggleBodyVisibility:function(b){var a=this.$el.find(".historyItemBody");if(b===undefined){a.toggle()}else{if(b){a.show()}else{a.hide()}}this.trigger("toggleBodyVisibility",this.model.get("id"),a.is(":visible"))},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HistoryItemView("+a+")"}});HistoryItemView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-history-warning-messages"],titleLink:Handlebars.templates["template-history-titleLink"],hdaSummary:Handlebars.templates["template-history-hdaSummary"],downloadLinks:Handlebars.templates["template-history-downloadLinks"],failedMetadata:Handlebars.templates["template-history-failedMetaData"],tagArea:Handlebars.templates["template-history-tagArea"],annotationArea:Handlebars.templates["template-history-annotationArea"],displayApps:Handlebars.templates["template-history-displayApps"]};var HistoryCollection=Backbone.Collection.extend({model:HistoryItem,toString:function(){return("HistoryCollection()")}});var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",state_details:{discarded:0,empty:0,error:0,failed_metadata:0,ok:0,queued:0,running:0,setting_metadata:0,upload:0},userIsAdmin:false,userRoles:[],itemsLength:0,showDeleted:false,showHidden:false,diskSize:0,deleted:false,tags:[],annotation:null,message:null,quotaMsg:false,baseURL:null,hideDeletedURL:null,hideHiddenURL:null,tagURL:null,annotateURL:null},initialize:function(b,a){this.items=new HistoryCollection()},toJSON:function(){var a=Backbone.Model.prototype.toJSON.call(this);a.itemsLength=this.items.length;return a},loadDatasetsAsHistoryItems:function(c){var a=this,b=this.get("id"),d=this.get("state_details");_.each(c,function(f,e){var h=new HistoryItem(_.extend(f,{history_id:b}));a.items.add(h);var g=f.state;d[g]+=1});this.set("state_details",d);this._stateFromStateDetails();return this},_stateFromStateDetails:function(){this.set("state","");var a=this.get("state_details");if((a.error>0)||(a.failed_metadata>0)){this.set("state",HistoryItem.STATES.ERROR)}else{if((a.running>0)||(a.setting_metadata>0)){this.set("state",HistoryItem.STATES.RUNNING)}else{if(a.queued>0){this.set("state",HistoryItem.STATES.QUEUED)}else{if(a.ok===this.items.length){this.set("state",HistoryItem.STATES.OK)}else{throw ("_stateFromStateDetails: unable to determine history state from state details: "+this.state_details)}}}}return this},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});var HistoryView=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",initialize:function(){this.log(this+".initialize:",this);this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{visibleItems:{}});this.initializeItems()},initializeItems:function(){this.itemViews={};var a=this;this.model.items.each(function(c){var e=c.get("id"),d=a.storage.get("visibleItems").get(e),b=new HistoryItemView({model:c,visible:d});a.setUpItemListeners(b);a.itemViews[e]=b})},setUpItemListeners:function(b){var a=this;b.bind("toggleBodyVisibility",function(d,c){if(c){a.storage.get("visibleItems").set(d,true)}else{a.storage.get("visibleItems").deleteKey(d)}})},render:function(){this.$el.append(HistoryView.templates.historyPanel(this.model.toJSON()));this.log(this+" rendered from template:",this.$el);this.itemsDiv=this.$el.find("#"+this.model.get("id")+"-datasets");async_save_text("history-name-container","history-name",this.model.get("renameURL"),"new_name",18);this.$el.find(".tooltip").tooltip();var b=this.$el.find("#history-annotation-area");$("#history-annotate").click(function(){if(b.is(":hidden")){b.slideDown("fast")}else{b.slideUp("fast")}return false});async_save_text("history-annotation-container","history-annotation",this.model.get("annotateURL"),"new_annotation",18,true,4);if(this.model.items.length){var a=this._render_items();this.itemsDiv.append(a.children());a.remove()}},_render_items:function(){var b=$("<div/>"),a=this;_.each(this.itemViews,function(d,c){a.log(a+".render_items:",c,d);b.prepend(d.render())});return b},events:{"click #history-collapse-all":"hideAllItemBodies","click #history-tag":"loadAndDisplayTags"},hideAllItemBodies:function(){_.each(this.itemViews,function(a){a.toggleBodyVisibility(false)})},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:this.model.get("tagURL"),error:function(){alert("Tagging failed")},success:function(e){a.log(a+" tag elt html (ajax)",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"HistoryView("+a+")"}});HistoryView.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]}; \ No newline at end of file +var HistoryDatasetAssociation=BaseModel.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"",state:"",data_type:null,file_size:0,meta_files:[],misc_blurb:"",misc_info:"",deleted:false,purged:false,visible:false,accessible:false,for_editing:true},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",function(b,a,d,c){this.log(this+" has changed:",b,a,d,c)})},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isEditable:function(){return(!this.isDeletedOrPurged())},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},inFinalState:function(){return((this.get("state")===HistoryDatasetAssociation.STATES.OK)||(this.get("state")===HistoryDatasetAssociation.STATES.FAILED_METADATA)||(this.get("state")===HistoryDatasetAssociation.STATES.EMPTY)||(this.get("state")===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={NOT_VIEWABLE:"noPermission",NEW:"new",UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",OK:"ok",EMPTY:"empty",ERROR:"error",DISCARDED:"discarded",SETTING_METADATA:"setting_metadata",FAILED_METADATA:"failed_metadata"};var HDACollection=Backbone.Collection.extend(LoggableMixin).extend({model:HistoryDatasetAssociation,logger:console,ids:function(){return this.map(function(a){return a.id})},getVisible:function(a,b){return new HDACollection(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},update:function(a){this.log(this+"update:",a);if(!(a&&a.length)){return}var b=this;_.each(a,function(e,c){var d=b.get(e);d.fetch()})},toString:function(){return("HDACollection("+this.ids().join(",")+")")}});var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",show_deleted:false,show_hidden:false,diskSize:0,deleted:false,tags:[],annotation:null,message:null,quotaMsg:false},url:function(){return"api/histories/"+this.get("id")},initialize:function(a,b){this.log(this+".initialize:",a,b);this.hdas=new HDACollection();if(b&&b.length){this.hdas.reset(b);this.checkForUpdates()}this.on("change",function(d,c,f,e){this.log(this+" has changed:",d,c,f,e)})},loadFromAPI:function(a,c){var b=this;b.attributes.id=a;jQuery.when(jQuery.ajax("api/users/current"),b.fetch()).then(function(e,d){b.attributes.user=e[0];b.log(b)}).then(function(){jQuery.ajax(b.url()+"/contents?"+jQuery.param({ids:b.itemIdsFromStateIds().join(",")})).success(function(d){b.hdas.reset(d);b.checkForUpdates();c()})})},hdaIdsFromStateIds:function(){return _.reduce(_.values(this.get("state_ids")),function(b,a){return b.concat(a)})},checkForUpdates:function(a){this.stateFromStateIds();if((this.get("state")===HistoryDatasetAssociation.STATES.RUNNING)||(this.get("state")===HistoryDatasetAssociation.STATES.QUEUED)){this.stateUpdater()}return this},stateFromStateIds:function(){var a=this.hdas.getStateLists();this.attributes.state_ids=a;if((a.running.length>0)||(a.upload.length>0)||(a.setting_metadata.length>0)){this.set("state",HistoryDatasetAssociation.STATES.RUNNING)}else{if(a.queued.length>0){this.set("state",HistoryDatasetAssociation.STATES.QUEUED)}else{if((a.error.length>0)||(a.failed_metadata.length>0)){this.set("state",HistoryDatasetAssociation.STATES.ERROR)}else{if(a.ok.length===this.hdas.length){this.set("state",HistoryDatasetAssociation.STATES.OK)}else{throw (this+".stateFromStateDetails: unable to determine history state from hda states: "+this.get("state_ids"))}}}}return this},stateUpdater:function(){var c=this,a=this.get("state"),b=this.get("state_ids");jQuery.ajax("api/histories/"+this.get("id")).success(function(d){c.set(d);c.log("current history state:",c.get("state"),"(was)",a);var e=[];_.each(_.keys(d.state_ids),function(g){var f=_.difference(d.state_ids[g],b[g]);e=e.concat(f)});if(e.length){c.hdas.update(e)}if((c.get("state")===HistoryDatasetAssociation.STATES.RUNNING)||(c.get("state")===HistoryDatasetAssociation.STATES.QUEUED)){setTimeout(function(){c.stateUpdater()},4000)}}).error(function(f,d,e){if(console&&console.warn){console.warn("Error getting history updates from the server:",f,d,e)}alert("Error getting history updates from the server.\n"+e)})},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});var HDAView=BaseView.extend(LoggableMixin).extend({logger:console,tagName:"div",className:"historyItemContainer",initialize:function(a){this.log(this+".initialize:",a);if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}this.urls=this.renderUrls(a.urlTemplates,this.model.toJSON());this.expanded=a.expanded||false;this.model.bind("change",this.render,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{c[f]=_.template(e,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:function(){var b=this,d=this.model.get("id"),c=this.model.get("state"),a=$("<div/>").attr("id","historyItem-"+d);this._clearReferences();this.$el.attr("id","historyItemContainer-"+d);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);b.trigger("rendered")})});return this},_clearReferences:function(){this.displayButton=null;this.editButton=null;this.deleteButton=null;this.errButton=null;this.showParamsButton=null;this.rerunButton=null;this.visualizationsButton=null;this.tagButton=null;this.annotateButton=null},_render_warnings:function(){return $(jQuery.trim(HDAView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_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());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_displayButton:function(){if((!this.model.inFinalState())||(this.model.get("state")===HistoryDatasetAssociation.STATES.ERROR)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var a={icon_class:"display"};if(this.model.get("purged")){a.enabled=false;a.title="Cannot display datasets removed from disk"}else{a.title="Display data in browser";a.href=this.urls.display}if(this.model.get("for_editing")){a.target="galaxy_main"}this.displayButton=new IconButtonView({model:new IconButton(a)});return this.displayButton.render().$el},_render_editButton:function(){if((this.model.get("state")===HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===HistoryDatasetAssociation.STATES.ERROR)||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))||(!this.model.get("for_editing"))){return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:"Edit attributes",href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false;if(c){b.title="Cannot edit attributes of datasets removed from disk"}else{if(a){b.title="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("for_editing"))||(this.model.get("state")===HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var a={title:"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:"Dataset is already deleted",icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HDAView.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var a=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&this.model.isEditable()){_.extend(a,{dbkey_unknown_and_editable:true})}return HDAView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var b=$("<div/>").attr("id","primary-actions-"+this.model.get("id")),a=this;_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")){return null}var a=HDAView.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(a)},_render_errButton:function(){if((this.model.get("state")!==HistoryDatasetAssociation.STATES.ERROR)||(!this.model.get("for_editing"))){return null}this.errButton=new IconButtonView({model:new IconButton({title:"View or report this error",href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:"View details",href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_rerunButton:function(){if(!this.model.get("for_editing")){return null}this.rerunButton=new IconButtonView({model:new IconButton({title:"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())||!(this.model.get("for_editing"))||!(a&&a.length)||!(f)){return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:"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[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.model.get("for_editing"))||(!this.urls.tags.get)){return null}this.tagButton=new IconButtonView({model:new IconButton({title:"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.model.get("for_editing"))||(!this.urls.annotation.get)){return null}this.annotateButton=new IconButtonView({model:new IconButton({title:"Edit dataset annotation",target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.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(HDAView.templates.displayApps({displayApps:this.model.get("display_types")}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HDAView.templates.displayApps({displayApps:this.model.get("display_apps")}))}return a},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(HDAView.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(HDAView.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})))},_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_not_viewable:function(a){a.append($("<div>You do not have permission to view dataset.</div>"))},_render_body_uploading:function(a){a.append($("<div>Dataset is uploading</div>"))},_render_body_queued:function(a){a.append($("<div>Job is waiting to run.</div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_running:function(a){a.append("<div>Job is currently running.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append(("An error occurred running this job: <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]))},_render_body_discarded:function(a){a.append("<div>The job creating this dataset was cancelled before completion.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_setting_metadata:function(a){a.append($("<div>Metadata is being auto-detected.</div>"))},_render_body_empty:function(a){a.append($("<div>No data: <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_failed_metadata:function(a){a.append($(HDAView.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,this._render_rerunButton]));return}a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,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())},_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.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 "'+state+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.expanded){a.show()}else{a.hide()}return a},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("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("Annotations failed")},success:function(e){if(e===""){e="<em>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},toggleBodyVisibility:function(b,a){var c=this.$el.find(".historyItemBody");a=(a===undefined)?(!c.is(":visible")):(a);if(a){c.slideDown("fast")}else{c.slideUp("fast")}this.trigger("toggleBodyVisibility",this.model.get("id"),a)},toString:function(){var a=(this.model)?(this.model+""):("(no model)");return"HDAView("+a+")"}});HDAView.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-history-warning-messages"],titleLink:Handlebars.templates["template-history-titleLink"],hdaSummary:Handlebars.templates["template-history-hdaSummary"],downloadLinks:Handlebars.templates["template-history-downloadLinks"],failedMetadata:Handlebars.templates["template-history-failedMetaData"],tagArea:Handlebars.templates["template-history-tagArea"],annotationArea:Handlebars.templates["template-history-annotationArea"],displayApps:Handlebars.templates["template-history-displayApps"]};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("Could not add this dataset to browser.")},success:function(e){var f=window.parent;f.show_modal("View Data in a New or Saved Visualization","",{Cancel:function(){f.hide_modal()},"View in saved visualization":function(){f.show_modal("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}}var HistoryView=BaseView.extend(LoggableMixin).extend({logger:console,el:"body.historyPage",initialize:function(a){this.log(this+".initialize:",a);if(!a.urlTemplates){throw ("HDAView needs urlTemplates on initialize")}if(!a.urlTemplates.history){throw ("HDAView needs urlTemplates.history on initialize")}if(!a.urlTemplates.hda){throw ("HDAView needs urlTemplates.hda on initialize")}this.urlTemplates=a.urlTemplates.history;this.hdaUrlTemplates=a.urlTemplates.hda;this.storage=new PersistantStorage("HistoryView."+this.model.get("id"),{expandedHdas:{}});this.model.hdas.bind("add",this.add,this);this.model.hdas.bind("reset",this.addAll,this);this.model.hdas.bind("all",this.all,this);this.hdaViews={};this.urls={}},add:function(a){},addAll:function(){this.render()},all:function(a){},renderUrls:function(a){var b=this;b.urls={};_.each(this.urlTemplates,function(d,c){b.urls[c]=_.template(d,a)});return b.urls},render:function(){var b=this,d=b.toString()+".set-up",c=$("<div/>"),a=this.model.toJSON();a.urls=this.renderUrls(a);c.append(HistoryView.templates.historyPanel(a));b.$el.find(".tooltip").tooltip();if(!this.model.hdas.length||!this.renderItems(c.find("#"+this.model.get("id")+"-datasets"))){c.find("#emptyHistoryMessage").show()}$(b).queue(d,function(e){b.$el.fadeOut("fast",function(){e()})});$(b).queue(d,function(e){b.$el.html("");b.$el.append(c.children());b.$el.fadeIn("fast",function(){e()})});$(b).queue(d,function(e){this.log(b+" rendered:",b.$el);b.setUpBehaviours();b.trigger("rendered");e()});$(b).dequeue(d);return this},renderItems:function(c){this.hdaViews={};var b=this,a=this.model.get("show_deleted"),e=this.model.get("show_hidden"),d=this.model.hdas.getVisible(a,e);d.each(function(h){var g=h.get("id"),f=b.storage.get("expandedHdas").get(g);b.hdaViews[g]=new HDAView({model:h,expanded:f,urlTemplates:b.hdaUrlTemplates});b.setUpHdaListeners(b.hdaViews[g]);c.prepend(b.hdaViews[g].render().$el)});return d.length},setUpHdaListeners:function(a){var b=this;a.bind("toggleBodyVisibility",function(d,c){if(c){b.storage.get("expandedHdas").set(d,true)}else{b.storage.get("expandedHdas").deleteKey(d)}})},setUpBehaviours:function(){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)},events:{"click #history-collapse-all":"hideAllHdaBodies","click #history-tag":"loadAndDisplayTags"},hideAllHdaBodies:function(){_.each(this.itemViews,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("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"HistoryView("+a+")"}});HistoryView.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]}; \ No newline at end of file diff -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c -r 2e70816299e40fecc4902adda54126bb00316588 static/scripts/packed/templates/compiled/template-history-downloadLinks.js --- a/static/scripts/packed/templates/compiled/template-history-downloadLinks.js +++ b/static/scripts/packed/templates/compiled/template-history-downloadLinks.js @@ -1,1 +1,1 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-downloadLinks"]=b(function(g,l,f,k,j){f=f||g.helpers;var c,h="function",i=this.escapeExpression,m=this;function e(s,r){var p="",q,o;p+='\n<div popupmenu="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a class="action-button" href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'">Download Dataset</a>\n <a>Additional Files</a>\n ';q=s.meta_files;q=f.each.call(s,q,{hash:{},inverse:m.noop,fn:m.program(2,d,r)});if(q||q===0){p+=q}p+='\n</div>\n<div style="float:left;" class="menubutton split popup" id="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n</div>\n';return p}function d(s,r){var p="",q,o;p+='\n <a class="action-button" href="';o=f.meta_download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_download_url;q=typeof q===h?q():q}p+=i(q)+'">Download ';o=f.meta_file_type;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_file_type;q=typeof q===h?q():q}p+=i(q)+"</a>\n ";return p}function n(s,r){var p="",q,o;p+='\n<a href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n';return p}c=l.meta_files;c=f["if"].call(l,c,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j)});if(c||c===0){return c}else{return""}})})(); \ No newline at end of file +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-downloadLinks"]=b(function(g,l,f,k,j){f=f||g.helpers;var c,h="function",i=this.escapeExpression,m=this;function e(s,r){var p="",q,o;p+="\n";p+='\n<div popupmenu="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a class="action-button" href="';q=s.urls;q=q==null||q===false?q:q.download;q=typeof q===h?q():q;p+=i(q)+'">Download Dataset</a>\n <a>Additional Files</a>\n ';q=s.urls;q=q==null||q===false?q:q.meta_download;q=f.each.call(s,q,{hash:{},inverse:m.noop,fn:m.program(2,d,r)});if(q||q===0){p+=q}p+='\n</div>\n<div style="float:left;" class="menubutton split popup" id="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a href="';q=s.urls;q=q==null||q===false?q:q.download;q=typeof q===h?q():q;p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n</div>\n';return p}function d(s,r){var p="",q,o;p+='\n <a class="action-button" href="';o=f.url;if(o){q=o.call(s,{hash:{}})}else{q=s.url;q=typeof q===h?q():q}p+=i(q)+'">Download ';o=f.file_type;if(o){q=o.call(s,{hash:{}})}else{q=s.file_type;q=typeof q===h?q():q}p+=i(q)+"</a>\n ";return p}function n(r,q){var o="",p;o+="\n";o+='\n<a href="';p=r.urls;p=p==null||p===false?p:p.download;p=typeof p===h?p():p;o+=i(p)+'" title="Download" class="icon-button disk tooltip"></a>\n';return o}c=l.urls;c=c==null||c===false?c:c.meta_download;c=f["if"].call(l,c,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j)});if(c||c===0){return c}else{return""}})})(); \ No newline at end of file diff -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c -r 2e70816299e40fecc4902adda54126bb00316588 static/scripts/packed/templates/compiled/template-history-failedMetaData.js --- a/static/scripts/packed/templates/compiled/template-history-failedMetaData.js +++ b/static/scripts/packed/templates/compiled/template-history-failedMetaData.js @@ -1,1 +1,1 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-failedMetaData"]=b(function(f,l,e,k,j){e=e||f.helpers;var c,h,g="function",i=this.escapeExpression,n=this,m=e.blockHelperMissing;function d(s,r){var p="",q,o;p+='\nAn error occurred setting the metadata for this dataset.\nYou may be able to <a href="';o=e.edit_url;if(o){q=o.call(s,{hash:{}})}else{q=s.edit_url;q=typeof q===g?q():q}p+=i(q)+'" target="galaxy_main">set it manually or retry auto-detection</a>.\n';return p}h=e.warningmessagesmall;if(h){c=h.call(l,{hash:{},inverse:n.noop,fn:n.program(1,d,j)})}else{c=l.warningmessagesmall;c=typeof c===g?c():c}if(!e.warningmessagesmall){c=m.call(l,c,{hash:{},inverse:n.noop,fn:n.program(1,d,j)})}if(c||c===0){return c}else{return""}})})(); \ No newline at end of file +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-failedMetaData"]=b(function(f,l,e,k,j){e=e||f.helpers;var c,h,g="function",i=this.escapeExpression,n=this,m=e.blockHelperMissing;function d(r,q){var o="",p;o+='\nAn error occurred setting the metadata for this dataset.\nYou may be able to <a href="';p=r.urls;p=p==null||p===false?p:p.edit;p=typeof p===g?p():p;o+=i(p)+'" target="galaxy_main">set it manually or retry auto-detection</a>.\n';return o}h=e.warningmessagesmall;if(h){c=h.call(l,{hash:{},inverse:n.noop,fn:n.program(1,d,j)})}else{c=l.warningmessagesmall;c=typeof c===g?c():c}if(!e.warningmessagesmall){c=m.call(l,c,{hash:{},inverse:n.noop,fn:n.program(1,d,j)})}if(c||c===0){return c}else{return""}})})(); \ No newline at end of file diff -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c -r 2e70816299e40fecc4902adda54126bb00316588 static/scripts/packed/templates/compiled/template-history-hdaSummary.js --- a/static/scripts/packed/templates/compiled/template-history-hdaSummary.js +++ b/static/scripts/packed/templates/compiled/template-history-hdaSummary.js @@ -1,1 +1,1 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-hdaSummary"]=b(function(g,n,f,m,l){f=f||g.helpers;var j="",d,i,h="function",k=this.escapeExpression,p=this;function e(u,t){var r="",s,q;r+='\n <a href="';q=f.edit_url;if(q){s=q.call(u,{hash:{}})}else{s=u.edit_url;s=typeof s===h?s():s}r+=k(s)+'" target="galaxy_main">';q=f.metadata_dbkey;if(q){s=q.call(u,{hash:{}})}else{s=u.metadata_dbkey;s=typeof s===h?s():s}r+=k(s)+"</a>\n ";return r}function c(u,t){var r="",s,q;r+='\n <span class="';q=f.metadata_dbkey;if(q){s=q.call(u,{hash:{}})}else{s=u.metadata_dbkey;s=typeof s===h?s():s}r+=k(s)+'">';q=f.metadata_dbkey;if(q){s=q.call(u,{hash:{}})}else{s=u.metadata_dbkey;s=typeof s===h?s():s}r+=k(s)+"</span>\n ";return r}function o(u,t){var r="",s,q;r+='\n<div class="hda-info">';q=f.misc_info;if(q){s=q.call(u,{hash:{}})}else{s=u.misc_info;s=typeof s===h?s():s}r+=k(s)+"</div>\n";return r}j+='<div class="hda-summary">\n ';i=f.misc_blurb;if(i){d=i.call(n,{hash:{}})}else{d=n.misc_blurb;d=typeof d===h?d():d}j+=k(d)+'<br />\n format: <span class="';i=f.data_type;if(i){d=i.call(n,{hash:{}})}else{d=n.data_type;d=typeof d===h?d():d}j+=k(d)+'">';i=f.data_type;if(i){d=i.call(n,{hash:{}})}else{d=n.data_type;d=typeof d===h?d():d}j+=k(d)+"</span>,\n database:\n ";d=n.dbkey_unknown_and_editable;d=f["if"].call(n,d,{hash:{},inverse:p.program(3,c,l),fn:p.program(1,e,l)});if(d||d===0){j+=d}j+="\n</div>\n";d=n.misc_info;d=f["if"].call(n,d,{hash:{},inverse:p.noop,fn:p.program(5,o,l)});if(d||d===0){j+=d}return j})})(); \ No newline at end of file +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-hdaSummary"]=b(function(g,n,f,m,l){f=f||g.helpers;var j="",d,i,h="function",k=this.escapeExpression,p=this;function e(u,t){var r="",s,q;r+='\n <a href="';s=u.urls;s=s==null||s===false?s:s.edit;s=typeof s===h?s():s;r+=k(s)+'" target="galaxy_main">';q=f.metadata_dbkey;if(q){s=q.call(u,{hash:{}})}else{s=u.metadata_dbkey;s=typeof s===h?s():s}r+=k(s)+"</a>\n ";return r}function c(u,t){var r="",s,q;r+='\n <span class="';q=f.metadata_dbkey;if(q){s=q.call(u,{hash:{}})}else{s=u.metadata_dbkey;s=typeof s===h?s():s}r+=k(s)+'">';q=f.metadata_dbkey;if(q){s=q.call(u,{hash:{}})}else{s=u.metadata_dbkey;s=typeof s===h?s():s}r+=k(s)+"</span>\n ";return r}function o(u,t){var r="",s,q;r+='\n<div class="hda-info">';q=f.misc_info;if(q){s=q.call(u,{hash:{}})}else{s=u.misc_info;s=typeof s===h?s():s}r+=k(s)+"</div>\n";return r}j+='<div class="hda-summary">\n ';i=f.misc_blurb;if(i){d=i.call(n,{hash:{}})}else{d=n.misc_blurb;d=typeof d===h?d():d}j+=k(d)+'<br />\n format: <span class="';i=f.data_type;if(i){d=i.call(n,{hash:{}})}else{d=n.data_type;d=typeof d===h?d():d}j+=k(d)+'">';i=f.data_type;if(i){d=i.call(n,{hash:{}})}else{d=n.data_type;d=typeof d===h?d():d}j+=k(d)+"</span>,\n database:\n ";d=n.dbkey_unknown_and_editable;d=f["if"].call(n,d,{hash:{},inverse:p.program(3,c,l),fn:p.program(1,e,l)});if(d||d===0){j+=d}j+="\n</div>\n";d=n.misc_info;d=f["if"].call(n,d,{hash:{},inverse:p.noop,fn:p.program(5,o,l)});if(d||d===0){j+=d}return j})})(); \ No newline at end of file diff -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c -r 2e70816299e40fecc4902adda54126bb00316588 static/scripts/packed/templates/compiled/template-history-historyPanel.js --- a/static/scripts/packed/templates/compiled/template-history-historyPanel.js +++ b/static/scripts/packed/templates/compiled/template-history-historyPanel.js @@ -1,1 +1,1 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(k,C,A,s,J){A=A||k.helpers;var B="",o,n,y=this,f="function",c=A.blockHelperMissing,e=this.escapeExpression;function u(L,K){return"refresh"}function t(L,K){return"collapse all"}function r(O,N){var L="",M,K;L+='\n <div style="width: 40px; float: right; white-space: nowrap;">\n <a id="history-tag" title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(6,q,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(6,q,N)})}if(M||M===0){L+=M}L+='"\n class="icon-button tags tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n <a id="history-annotate" title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(8,m,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(8,m,N)})}if(M||M===0){L+=M}L+='"\n class="icon-button annotate tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n </div>\n ';return L}function q(L,K){return"Edit history tags"}function m(L,K){return"Edit history annotation"}function I(O,N){var L="",M,K;L+='\n<div class="historyLinks">\n <a href="';K=A.hideDeletedURL;if(K){M=K.call(O,{hash:{}})}else{M=O.hideDeletedURL;M=typeof M===f?M():M}L+=e(M)+'">';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(11,H,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(11,H,N)})}if(M||M===0){L+=M}L+="</a>\n</div>\n";return L}function H(L,K){return"hide deleted"}function G(O,N){var L="",M,K;L+='\n<div class="historyLinks">\n <a href="';K=A.hideHiddenURL;if(K){M=K.call(O,{hash:{}})}else{M=O.hideHiddenURL;M=typeof M===f?M():M}L+=e(M)+'">';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(14,F,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(14,F,N)})}if(M||M===0){L+=M}L+="</a>\n</div>\n";return L}function F(L,K){return"hide hidden"}function E(O,N){var L="",M,K;L+="\n ";L+='\n <div id="history-size" style="position: absolute; top: 3px; right: 0px;">';K=A.diskSize;if(K){M=K.call(O,{hash:{}})}else{M=O.diskSize;M=typeof M===f?M():M}L+=e(M)+'</div>\n <div id="history-name" style="margin-right: 50px;" class="tooltip editable-text" title="Click to rename history">';K=A.name;if(K){M=K.call(O,{hash:{}})}else{M=O.name;M=typeof M===f?M():M}L+=e(M)+"</div>\n \n ";return L}function D(O,N){var L="",M,K;L+='\n <div id="history-size">';K=A.diskSize;if(K){M=K.call(O,{hash:{}})}else{M=O.diskSize;M=typeof M===f?M():M}L+=e(M)+"</div>\n ";return L}function p(O,N){var L="",M,K;L+="\n";K=A.warningmessagesmall;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(21,l,N)})}else{M=O.warningmessagesmall;M=typeof M===f?M():M}if(!A.warningmessagesmall){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(21,l,N)})}if(M||M===0){L+=M}L+="\n";return L}function l(N,M){var L,K;K=A.local;if(K){L=K.call(N,{hash:{},inverse:y.noop,fn:y.program(22,j,M)})}else{L=N.local;L=typeof L===f?L():L}if(!A.local){L=c.call(N,L,{hash:{},inverse:y.noop,fn:y.program(22,j,M)})}if(L||L===0){return L}else{return""}}function j(L,K){return"You are currently viewing a deleted history!"}function i(N,M){var K="",L;K+="\n";K+='\n<div style="margin: 0px 5px 10px 5px">\n\n <div id="history-tag-area" style="display: none">\n ';K+="\n ";K+='\n <strong>Tags:</strong>\n <div class="tag-elt"></div>\n </div>\n\n <div id="history-annotation-area" style="display: none">\n <strong>Annotation / Notes:</strong>\n <div id="history-annotation-container">\n <div id="history-annotation" class="tooltip editable-text" title="Click to edit annotation">\n ';L=N.annotation;L=A["if"].call(N,L,{hash:{},inverse:y.program(27,g,M),fn:y.program(25,h,M)});if(L||L===0){K+=L}K+="\n </div>\n </div>\n </div>\n</div>\n";return K}function h(O,N){var L="",M,K;L+="\n ";K=A.annotation;if(K){M=K.call(O,{hash:{}})}else{M=O.annotation;M=typeof M===f?M():M}L+=e(M)+"\n ";return L}function g(L,K){return"\n <em>Describe or add notes to history</em>\n "}function d(O,N){var L="",M,K;L+='\n<div id="message-container">\n <div class="';K=A.status;if(K){M=K.call(O,{hash:{}})}else{M=O.status;M=typeof M===f?M():M}L+=e(M)+'message">\n ';K=A.message;if(K){M=K.call(O,{hash:{}})}else{M=O.message;M=typeof M===f?M():M}L+=e(M)+"\n </div><br />\n</div>\n";return L}function z(L,K){return'\n <div id="quota-message" class="errormessage">\n You are over your disk quota. Tool execution is on hold until your disk usage drops below your allocated quota.\n </div>\n <br/>\n '}function x(O,N){var L="",M,K;L+='\n<div id="';K=A.id;if(K){M=K.call(O,{hash:{}})}else{M=O.id;M=typeof M===f?M():M}L+=e(M)+'-datasets" class="history-datasets-list">\n ';L+="\n</div>\n\n";return L}function w(O,N){var L="",M,K;L+='\n<div class="infomessagesmall" id="emptyHistoryMessage">\n';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(36,v,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(36,v,N)})}if(M||M===0){L+=M}L+="\n</div>\n";return L}function v(L,K){return"Your history is empty. Click 'Get Data' on the left pane to start"}B+='<div id="top-links" class="historyLinks">\n <a title="';n=A.local;if(n){o=n.call(C,{hash:{},inverse:y.noop,fn:y.program(1,u,J)})}else{o=C.local;o=typeof o===f?o():o}if(!A.local){o=c.call(C,o,{hash:{},inverse:y.noop,fn:y.program(1,u,J)})}if(o||o===0){B+=o}B+='" class="icon-button arrow-circle tooltip" href="';n=A.baseURL;if(n){o=n.call(C,{hash:{}})}else{o=C.baseURL;o=typeof o===f?o():o}B+=e(o)+"\"></a>\n <a title='";n=A.local;if(n){o=n.call(C,{hash:{},inverse:y.noop,fn:y.program(3,t,J)})}else{o=C.local;o=typeof o===f?o():o}if(!A.local){o=c.call(C,o,{hash:{},inverse:y.noop,fn:y.program(3,t,J)})}if(o||o===0){B+=o}B+="' id=\"history-collapse-all\"\n class='icon-button toggle tooltip' href='javascript:void(0);'></a>\n ";o=C.userRoles;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(5,r,J)});if(o||o===0){B+=o}B+='\n</div>\n<div class="clear"></div>\n\n';B+="\n";o=C.showDeleted;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(10,I,J)});if(o||o===0){B+=o}B+="\n\n";o=C.showHidden;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(13,G,J)});if(o||o===0){B+=o}B+="\n\n";B+='\n<div id="history-name-area" class="historyLinks">\n <div id="history-name-container" style="position: relative;">\n ';o=C.userRoles;o=A["if"].call(C,o,{hash:{},inverse:y.program(18,D,J),fn:y.program(16,E,J)});if(o||o===0){B+=o}B+='\n </div> \n</div>\n<div style="clear: both;"></div>\n\n';o=C.deleted;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(20,p,J)});if(o||o===0){B+=o}B+="\n\n";B+="\n";o=C.userRoles;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(24,i,J)});if(o||o===0){B+=o}B+="\n\n";o=C.message;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(29,d,J)});if(o||o===0){B+=o}B+='\n\n<div id="quota-message-container">\n ';o=C.over_quota;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(31,z,J)});if(o||o===0){B+=o}B+="\n</div>\n\n";o=C.itemsLength;o=A["if"].call(C,o,{hash:{},inverse:y.program(35,w,J),fn:y.program(33,x,J)});if(o||o===0){B+=o}return B})})(); \ No newline at end of file +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(k,y,w,r,G){w=w||k.helpers;var x="",n,m,f="function",e=this.escapeExpression,u=this,c=w.blockHelperMissing;function t(L,K){var I="",J,H;I+='\n <div id="history-name" style="margin-right: 50px;" class="tooltip editable-text"\n title="Click to rename history">';H=w.name;if(H){J=H.call(L,{hash:{}})}else{J=L.name;J=typeof J===f?J():J}I+=e(J)+"</div>\n ";return I}function s(I,H){return"refresh"}function q(I,H){return"collapse all"}function p(L,K){var I="",J,H;I+='\n <a id="history-tag" title="';H=w.local;if(H){J=H.call(L,{hash:{},inverse:u.noop,fn:u.program(8,l,K)})}else{J=L.local;J=typeof J===f?J():J}if(!w.local){J=c.call(L,J,{hash:{},inverse:u.noop,fn:u.program(8,l,K)})}if(J||J===0){I+=J}I+='"\n class="icon-button tags tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n <a id="history-annotate" title="';H=w.local;if(H){J=H.call(L,{hash:{},inverse:u.noop,fn:u.program(10,F,K)})}else{J=L.local;J=typeof J===f?J():J}if(!w.local){J=c.call(L,J,{hash:{},inverse:u.noop,fn:u.program(10,F,K)})}if(J||J===0){I+=J}I+='"\n class="icon-button annotate tooltip" target="galaxy_main" href="javascript:void(0)"></a>\n ';return I}function l(I,H){return"Edit history tags"}function F(I,H){return"Edit history annotation"}function E(L,K){var I="",J,H;I+='\n <a href="';J=L.urls;J=J==null||J===false?J:J.hide_deleted;J=typeof J===f?J():J;I+=e(J)+'">';H=w.local;if(H){J=H.call(L,{hash:{},inverse:u.noop,fn:u.program(13,D,K)})}else{J=L.local;J=typeof J===f?J():J}if(!w.local){J=c.call(L,J,{hash:{},inverse:u.noop,fn:u.program(13,D,K)})}if(J||J===0){I+=J}I+="</a>\n ";return I}function D(I,H){return"hide deleted"}function C(L,K){var I="",J,H;I+='\n <a href="';J=L.urls;J=J==null||J===false?J:J.hide_hidden;J=typeof J===f?J():J;I+=e(J)+'">';H=w.local;if(H){J=H.call(L,{hash:{},inverse:u.noop,fn:u.program(16,B,K)})}else{J=L.local;J=typeof J===f?J():J}if(!w.local){J=c.call(L,J,{hash:{},inverse:u.noop,fn:u.program(16,B,K)})}if(J||J===0){I+=J}I+="</a>\n ";return I}function B(I,H){return"hide hidden"}function A(L,K){var I="",J,H;I+="\n";H=w.warningmessagesmall;if(H){J=H.call(L,{hash:{},inverse:u.noop,fn:u.program(19,z,K)})}else{J=L.warningmessagesmall;J=typeof J===f?J():J}if(!w.warningmessagesmall){J=c.call(L,J,{hash:{},inverse:u.noop,fn:u.program(19,z,K)})}if(J||J===0){I+=J}I+="\n";return I}function z(K,J){var I,H;H=w.local;if(H){I=H.call(K,{hash:{},inverse:u.noop,fn:u.program(20,o,J)})}else{I=K.local;I=typeof I===f?I():I}if(!w.local){I=c.call(K,I,{hash:{},inverse:u.noop,fn:u.program(20,o,J)})}if(I||I===0){return I}else{return""}}function o(I,H){return"You are currently viewing a deleted history!"}function j(K,J){var H="",I;H+='\n <div id="history-tag-area" style="display: none">\n <strong>Tags:</strong>\n <div class="tag-elt"></div>\n </div>\n\n <div id="history-annotation-area" style="display: none">\n <strong>Annotation / Notes:</strong>\n <div id="history-annotation-container">\n <div id="history-annotation" class="tooltip editable-text" title="Click to edit annotation">\n ';I=K.annotation;I=w["if"].call(K,I,{hash:{},inverse:u.program(25,h,J),fn:u.program(23,i,J)});if(I||I===0){H+=I}H+="\n </div>\n </div>\n </div>\n ";return H}function i(L,K){var I="",J,H;I+="\n ";H=w.annotation;if(H){J=H.call(L,{hash:{}})}else{J=L.annotation;J=typeof J===f?J():J}I+=e(J)+"\n ";return I}function h(I,H){return"\n <em>Describe or add notes to history</em>\n "}function g(L,K){var I="",J,H;I+='\n<div id="message-container">\n <div class="';H=w.status;if(H){J=H.call(L,{hash:{}})}else{J=L.status;J=typeof J===f?J():J}I+=e(J)+'message">\n ';H=w.message;if(H){J=H.call(L,{hash:{}})}else{J=L.message;J=typeof J===f?J():J}I+=e(J)+"\n </div><br />\n</div>\n";return I}function d(I,H){return'\n <div id="quota-message" class="errormessage">\n You are over your disk quota. Tool execution is on hold until your disk usage drops below your allocated quota.\n </div>\n <br/>\n '}function v(I,H){return"Your history is empty. Click 'Get Data' on the left pane to start"}x+='\n<div id="history-name-area" class="historyLinks">\n <div id="history-name-container" style="position: relative;">\n ';x+='\n <div id="history-size" style="position: absolute; top: 3px; right: 0px;">';m=w.nice_size;if(m){n=m.call(y,{hash:{}})}else{n=y.nice_size;n=typeof n===f?n():n}x+=e(n)+"</div>\n ";n=y.user;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(1,t,G)});if(n||n===0){x+=n}x+='\n </div> \n</div>\n<div style="clear: both;"></div>\n\n<div id="top-links" class="historyLinks">\n <a title="';m=w.local;if(m){n=m.call(y,{hash:{},inverse:u.noop,fn:u.program(3,s,G)})}else{n=y.local;n=typeof n===f?n():n}if(!w.local){n=c.call(y,n,{hash:{},inverse:u.noop,fn:u.program(3,s,G)})}if(n||n===0){x+=n}x+='" class="icon-button arrow-circle tooltip" href="';n=y.urls;n=n==null||n===false?n:n.base;n=typeof n===f?n():n;x+=e(n)+"\"></a>\n <a title='";m=w.local;if(m){n=m.call(y,{hash:{},inverse:u.noop,fn:u.program(5,q,G)})}else{n=y.local;n=typeof n===f?n():n}if(!w.local){n=c.call(y,n,{hash:{},inverse:u.noop,fn:u.program(5,q,G)})}if(n||n===0){x+=n}x+="' id=\"history-collapse-all\"\n class='icon-button toggle tooltip' href='javascript:void(0);'></a>\n <div style=\"width: 40px; float: right; white-space: nowrap;\">\n ";n=y.user;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(7,p,G)});if(n||n===0){x+=n}x+='\n </div>\n</div>\n<div style="clear: both;"></div>\n\n';x+='\n<div class="historyLinks">\n ';n=y.show_deleted;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(12,E,G)});if(n||n===0){x+=n}x+="\n ";n=y.show_hidden;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(15,C,G)});if(n||n===0){x+=n}x+="\n</div>\n\n";n=y.deleted;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(18,A,G)});if(n||n===0){x+=n}x+="\n\n";x+="\n";x+='\n<div style="margin: 0px 5px 10px 5px">\n\n ';n=y.user;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(22,j,G)});if(n||n===0){x+=n}x+="\n</div>\n\n";n=y.message;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(27,g,G)});if(n||n===0){x+=n}x+='\n\n<div id="quota-message-container">\n ';n=y.over_quota;n=w["if"].call(y,n,{hash:{},inverse:u.noop,fn:u.program(29,d,G)});if(n||n===0){x+=n}x+='\n</div>\n\n<div id="';m=w.id;if(m){n=m.call(y,{hash:{}})}else{n=y.id;n=typeof n===f?n():n}x+=e(n)+'-datasets" class="history-datasets-list"></div>\n\n<div class="infomessagesmall" id="emptyHistoryMessage" style="display: none;">\n ';m=w.local;if(m){n=m.call(y,{hash:{},inverse:u.noop,fn:u.program(31,v,G)})}else{n=y.local;n=typeof n===f?n():n}if(!w.local){n=c.call(y,n,{hash:{},inverse:u.noop,fn:u.program(31,v,G)})}if(n||n===0){x+=n}x+="\n</div>";return x})})(); \ No newline at end of file diff -r e825b868a31f4b2cdbeb951e73c34bc95eacd84c -r 2e70816299e40fecc4902adda54126bb00316588 static/scripts/packed/templates/compiled/template-history-warning-messages.js --- a/static/scripts/packed/templates/compiled/template-history-warning-messages.js +++ b/static/scripts/packed/templates/compiled/template-history-warning-messages.js @@ -1,1 +1,1 @@ -(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-warning-messages"]=b(function(g,s,q,k,v){q=q||g.helpers;var r="",h,e="function",d=this.escapeExpression,p=this,c=q.blockHelperMissing;function o(z,y){var x,w;w=q.warningmessagesmall;if(w){x=w.call(z,{hash:{},inverse:p.noop,fn:p.program(2,n,y)})}else{x=z.warningmessagesmall;x=typeof x===e?x():x}if(!q.warningmessagesmall){x=c.call(z,x,{hash:{},inverse:p.noop,fn:p.program(2,n,y)})}if(x||x===0){return x}else{return""}}function n(z,y){var w="",x;w+="\n This dataset has been deleted.\n ";x=z.undelete_url;x=q["if"].call(z,x,{hash:{},inverse:p.noop,fn:p.program(3,m,y)});if(x||x===0){w+=x}w+="\n";return w}function m(A,z){var x="",y,w;x+='\n Click <a href="';w=q.undelete_url;if(w){y=w.call(A,{hash:{}})}else{y=A.undelete_url;y=typeof y===e?y():y}x+=d(y)+'" class="historyItemUndelete" id="historyItemUndeleter-';w=q.id;if(w){y=w.call(A,{hash:{}})}else{y=A.id;y=typeof y===e?y():y}x+=d(y)+'"\n target="galaxy_history">here</a> to undelete it\n ';y=A.purge_url;y=q["if"].call(A,y,{hash:{},inverse:p.noop,fn:p.program(4,l,z)});if(y||y===0){x+=y}x+="\n ";return x}function l(A,z){var x="",y,w;x+='\n or <a href="';w=q.purge_url;if(w){y=w.call(A,{hash:{}})}else{y=A.purge_url;y=typeof y===e?y():y}x+=d(y)+'" class="historyItemPurge" id="historyItemPurger-';w=q.id;if(w){y=w.call(A,{hash:{}})}else{y=A.id;y=typeof y===e?y():y}x+=d(y)+'"\n target="galaxy_history">here</a> to immediately remove it from disk\n ';return x}function j(z,y){var x,w;w=q.warningmessagesmall;if(w){x=w.call(z,{hash:{},inverse:p.noop,fn:p.program(7,i,y)})}else{x=z.warningmessagesmall;x=typeof x===e?x():x}if(!q.warningmessagesmall){x=c.call(z,x,{hash:{},inverse:p.noop,fn:p.program(7,i,y)})}if(x||x===0){return x}else{return""}}function i(x,w){return"\n This dataset has been deleted and removed from disk.\n"}function f(z,y){var x,w;w=q.warningmessagesmall;if(w){x=w.call(z,{hash:{},inverse:p.noop,fn:p.program(10,u,y)})}else{x=z.warningmessagesmall;x=typeof x===e?x():x}if(!q.warningmessagesmall){x=c.call(z,x,{hash:{},inverse:p.noop,fn:p.program(10,u,y)})}if(x||x===0){return x}else{return""}}function u(z,y){var w="",x;w+="\n This dataset has been hidden.\n ";x=z.unhide_url;x=q["if"].call(z,x,{hash:{},inverse:p.noop,fn:p.program(11,t,y)});if(x||x===0){w+=x}w+="\n";return w}function t(A,z){var x="",y,w;x+='\n Click <a href="';w=q.unhide_url;if(w){y=w.call(A,{hash:{}})}else{y=A.unhide_url;y=typeof y===e?y():y}x+=d(y)+'" class="historyItemUnhide" id="historyItemUnhider-';w=q.id;if(w){y=w.call(A,{hash:{}})}else{y=A.id;y=typeof y===e?y():y}x+=d(y)+'"\n target="galaxy_history">here</a> to unhide it\n ';return x}h=s.deleted;h=q["if"].call(s,h,{hash:{},inverse:p.noop,fn:p.program(1,o,v)});if(h||h===0){r+=h}r+="\n\n";h=s.purged;h=q["if"].call(s,h,{hash:{},inverse:p.noop,fn:p.program(6,j,v)});if(h||h===0){r+=h}r+="\n\n";h=s.visible;h=q.unless.call(s,h,{hash:{},inverse:p.noop,fn:p.program(9,f,v)});if(h||h===0){r+=h}return r})})(); \ No newline at end of file +(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-warning-messages"]=b(function(f,s,q,k,w){q=q||f.helpers;var r="",h,e="function",d=this.escapeExpression,p=this,c=q.blockHelperMissing;function o(z,y){var x;x=z.purged;x=q.unless.call(z,x,{hash:{},inverse:p.noop,fn:p.program(2,n,y)});if(x||x===0){return x}else{return""}}function n(B,A){var y="",z,x;y+="\n";x=q.warningmessagesmall;if(x){z=x.call(B,{hash:{},inverse:p.noop,fn:p.program(3,m,A)})}else{z=B.warningmessagesmall;z=typeof z===e?z():z}if(!q.warningmessagesmall){z=c.call(B,z,{hash:{},inverse:p.noop,fn:p.program(3,m,A)})}if(z||z===0){y+=z}y+="\n";return y}function m(A,z){var x="",y;x+="\n This dataset has been deleted.\n ";y=A.urls;y=y==null||y===false?y:y.undelete;y=q["if"].call(A,y,{hash:{},inverse:p.noop,fn:p.program(4,l,z)});if(y||y===0){x+=y}x+="\n";return x}function l(B,A){var y="",z,x;y+='\n Click <a href="';z=B.urls;z=z==null||z===false?z:z.undelete;z=typeof z===e?z():z;y+=d(z)+'" class="historyItemUndelete" id="historyItemUndeleter-';x=q.id;if(x){z=x.call(B,{hash:{}})}else{z=B.id;z=typeof z===e?z():z}y+=d(z)+'"\n target="galaxy_history">here</a> to undelete it\n ';z=B.urls;z=z==null||z===false?z:z.purge;z=q["if"].call(B,z,{hash:{},inverse:p.noop,fn:p.program(5,j,A)});if(z||z===0){y+=z}y+="\n ";return y}function j(B,A){var y="",z,x;y+='\n or <a href="';z=B.urls;z=z==null||z===false?z:z.purge;z=typeof z===e?z():z;y+=d(z)+'" class="historyItemPurge" id="historyItemPurger-';x=q.id;if(x){z=x.call(B,{hash:{}})}else{z=B.id;z=typeof z===e?z():z}y+=d(z)+'"\n target="galaxy_history">here</a> to immediately remove it from disk\n ';return y}function i(A,z){var y,x;x=q.warningmessagesmall;if(x){y=x.call(A,{hash:{},inverse:p.noop,fn:p.program(8,g,z)})}else{y=A.warningmessagesmall;y=typeof y===e?y():y}if(!q.warningmessagesmall){y=c.call(A,y,{hash:{},inverse:p.noop,fn:p.program(8,g,z)})}if(y||y===0){return y}else{return""}}function g(y,x){return"\n This dataset has been deleted and removed from disk.\n"}function v(A,z){var y,x;x=q.warningmessagesmall;if(x){y=x.call(A,{hash:{},inverse:p.noop,fn:p.program(11,u,z)})}else{y=A.warningmessagesmall;y=typeof y===e?y():y}if(!q.warningmessagesmall){y=c.call(A,y,{hash:{},inverse:p.noop,fn:p.program(11,u,z)})}if(y||y===0){return y}else{return""}}function u(A,z){var x="",y;x+="\n This dataset has been hidden.\n ";y=A.urls;y=y==null||y===false?y:y.unhide;y=q["if"].call(A,y,{hash:{},inverse:p.noop,fn:p.program(12,t,z)});if(y||y===0){x+=y}x+="\n";return x}function t(B,A){var y="",z,x;y+='\n Click <a href="';z=B.urls;z=z==null||z===false?z:z.unhide;z=typeof z===e?z():z;y+=d(z)+'" class="historyItemUnhide" id="historyItemUnhider-';x=q.id;if(x){z=x.call(B,{hash:{}})}else{z=B.id;z=typeof z===e?z():z}y+=d(z)+'"\n target="galaxy_history">here</a> to unhide it\n ';return y}h=s.deleted;h=q["if"].call(s,h,{hash:{},inverse:p.noop,fn:p.program(1,o,w)});if(h||h===0){r+=h}r+="\n\n";h=s.purged;h=q["if"].call(s,h,{hash:{},inverse:p.noop,fn:p.program(7,i,w)});if(h||h===0){r+=h}r+="\n\n";h=s.visible;h=q.unless.call(s,h,{hash:{},inverse:p.noop,fn:p.program(10,v,w)});if(h||h===0){r+=h}return r})})(); \ 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.
participants (1)
-
Bitbucket