commit/galaxy-central: carlfeberhard: History panel: cleanup, todo list, docs; pack scripts
1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/e66076ed4678/ Changeset: e66076ed4678 User: carlfeberhard Date: 2013-10-23 19:03:59 Summary: History panel: cleanup, todo list, docs; pack scripts Affected #: 10 files diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/mvc/dataset/hda-base.js --- a/static/scripts/mvc/dataset/hda-base.js +++ b/static/scripts/mvc/dataset/hda-base.js @@ -5,7 +5,7 @@ //============================================================================== /** @class Read only view for HistoryDatasetAssociation. * @name HDABaseView - * + * * @augments Backbone.View * @borrows LoggableMixin#logger as #logger * @borrows LoggableMixin#log as #log @@ -23,7 +23,7 @@ fxSpeed : 'fast', - // ......................................................................... SET UP + // ......................................................................... set up /** Set up the view, cache url templates, bind listeners * @param {Object} attributes * @config {Object} urlTemplates nested object containing url templates for this view @@ -44,13 +44,17 @@ this._setUpListeners(); }, + /** event listeners */ _setUpListeners : function(){ + // re-rendering on any model changes this.model.on( 'change', function( model, options ){ - // if the model moved into the ready state and is expanded without details, fetch those details + + // if the model moved into the ready state and is expanded without details, fetch those details now if( this.model.changedAttributes().state && this.model.inReadyState() && this.expanded && !this.model.hasDetails() ){ this.model.fetch(); // will render automatically (due to lines below) + } else { this.render(); } @@ -61,7 +65,7 @@ //}, this ); }, - // ......................................................................... RENDER MAIN + // ......................................................................... render main /** Render this HDA, set up ui. * @fires rendered:ready when rendered and NO running HDAs * @fires rendered when rendered and running HDAs @@ -122,7 +126,6 @@ _setUpBehaviors : function( $container ){ $container = $container || this.$el; // set up canned behavior on children (bootstrap, popupmenus, editable_text, etc.) - //TODO: we can potentially skip this step and call popupmenu directly on the download button make_popup_menus( $container ); $container.find( '[title]' ).tooltip({ placement : 'bottom' }); }, @@ -213,13 +216,10 @@ * @returns {jQuery} rendered DOM */ _render_titleLink : function(){ - return $( jQuery.trim( HDABaseView.templates.titleLink( - //TODO?? does this need urls? - _.extend( this.model.toJSON(), { urls: this.urls } ) - ))); + return $( jQuery.trim( HDABaseView.templates.titleLink( this.model.toJSON() ))); }, - // ......................................................................... RENDER BODY + // ......................................................................... body /** Render the data/metadata summary (format, size, misc info, etc.). * @returns {jQuery} rendered DOM */ @@ -283,7 +283,7 @@ /** Render links to external genome display applications (igb, gbrowse, etc.). * @param {jQuery} $parent the jq node to search for .display-apps and render into to (defaults to this.$el) */ - //TODO: not a fan of the style on these +//TODO: move into visualization button _render_displayApps : function( $parent ){ $parent = $parent || this.$el; var $displayAppsDiv = $parent.find( 'div.display-apps' ), @@ -310,7 +310,6 @@ /** Render the data peek. * @returns {jQuery} rendered DOM */ - //TODO: curr. pre-formatted into table on the server side - may not be ideal/flexible _render_peek : function(){ var peek = this.model.get( 'peek' ); if( !peek ){ return null; } @@ -326,74 +325,38 @@ /** Render the enclosing div of the hda body and, if expanded, the html in the body * @returns {jQuery} rendered DOM */ - //TODO: only render these on expansion (or already expanded) _render_body : function(){ - var body = $( '<div/>' ) + var $body = $( '<div/>' ) .attr( 'id', 'info-' + this.model.get( 'id' ) ) .addClass( 'historyItemBody' ) .attr( 'style', 'display: none' ); if( this.expanded ){ // only render the body html if it's being shown - this._render_body_html( body ); - //TODO: switch back when jq -> 1.9 - //body.show(); - body.css( 'display', 'block' ); + this._render_body_html( $body ); + $body.show(); } - return body; + return $body; }, /** Render the (expanded) body of an HDA, dispatching to other functions based on the HDA state * @param {jQuery} body the body element to append the html to */ - //TODO: only render these on expansion (or already expanded) - _render_body_html : function( body ){ + _render_body_html : function( $body ){ //this.log( this + '_render_body' ); - body.html( '' ); - //TODO: not a fan of this dispatch - switch( this.model.get( 'state' ) ){ - case hdaModel.HistoryDatasetAssociation.STATES.NEW : - this._render_body_new( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE : - this._render_body_not_viewable( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.UPLOAD : - this._render_body_uploading( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.PAUSED: - this._render_body_paused( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.QUEUED : - this._render_body_queued( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.RUNNING : - this._render_body_running( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.ERROR : - this._render_body_error( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.DISCARDED : - this._render_body_discarded( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.SETTING_METADATA : - this._render_body_setting_metadata( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.EMPTY : - this._render_body_empty( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.FAILED_METADATA : - this._render_body_failed_metadata( body ); - break; - case hdaModel.HistoryDatasetAssociation.STATES.OK : - this._render_body_ok( body ); - break; - default: - //??: no body? - body.append( $( '<div>Error: unknown dataset state "' + this.model.get( 'state' ) + '".</div>' ) ); + $body.empty(); + + var modelState = this.model.get( 'state' ); + // cheesy get function by assumed matching name + var renderFnName = '_render_body_' + modelState, + renderFn = this[ renderFnName ]; + if( _.isFunction( renderFn ) ){ + this[ renderFnName ]( $body ); + } else { + $body.append( $( '<div>Error: unknown dataset state "' + this.model.get( 'state' ) + '".</div>' ) ); } - body.append( '<div style="clear: both"></div>' ); - this._setUpBehaviors( body ); + $body.append( '<div style="clear: both"></div>' ); + this._setUpBehaviors( $body ); }, /** Render a new dataset - this should be a transient state that's never shown @@ -408,15 +371,14 @@ /** Render inaccessible, not-owned by curr user. * @param {jQuery} parent DOM to which to append this body */ - _render_body_not_viewable : function( parent ){ - //TODO: revisit - still showing display, edit, delete (as common) - that CAN'T be right - parent.append( $( '<div>' + _l( 'You do not have permission to view dataset' ) + '</div>' ) ); + _render_body_noPermission : function( parent ){ + parent.append( $( '<div>' + _l( 'You do not have permission to view this dataset' ) + '</div>' ) ); }, /** Render an HDA still being uploaded. * @param {jQuery} parent DOM to which to append this body */ - _render_body_uploading : function( parent ){ + _render_body_upload : function( parent ){ parent.append( $( '<div>' + _l( 'Dataset is uploading' ) + '</div>' ) ); }, @@ -432,7 +394,8 @@ * @param {jQuery} parent DOM to which to append this body */ _render_body_paused: function( parent ){ - parent.append( $( '<div>' + _l( 'Job is paused. Use the history menu to resume' ) + '</div>' ) ); + parent.append( $( '<div>' + _l( 'Job is paused. ' + + 'Use the "Resume Paused Jobs" in the history menu to resume' ) + '</div>' ) ); parent.append( this._render_primaryActionButtons( this.defaultPrimaryActionButtonRenderers )); }, @@ -477,8 +440,6 @@ * @param {jQuery} parent DOM to which to append this body */ _render_body_empty : function( parent ){ - //TODO: replace i with dataset-misc-info class - //?? why are we showing the file size when we know it's zero?? parent.append( $( '<div>' + _l( 'No data' ) + ': <i>' + this.model.get( 'misc_blurb' ) + '</i></div>' ) ); parent.append( this._render_primaryActionButtons( this.defaultPrimaryActionButtonRenderers )); }, @@ -487,7 +448,6 @@ * @param {jQuery} parent DOM to which to append this body */ _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( $( HDABaseView.templates.failedMetadata( _.extend( this.model.toJSON(), { urls: this.urls } ) @@ -504,7 +464,6 @@ 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, @@ -525,44 +484,55 @@ parent.append( this._render_peek() ); }, - // ......................................................................... EVENTS + // ......................................................................... events /** event map */ events : { + // expand the body when the title is clicked 'click .historyItemTitle' : 'toggleBodyVisibility' }, - /** Render an HDA that's done running and where everything worked. + /** Show or hide the body/details of an HDA. + * note: if the model does not have detailed data, fetch that data before showing the body * @param {Event} event the event that triggered this (@link HDABaseView#events) * @param {Boolean} expanded if true, expand; if false, collapse * @fires body-expanded when a body has been expanded * @fires body-collapsed when a body has been collapsed */ toggleBodyVisibility : function( event, expand ){ - var hdaView = this; expand = ( expand === undefined )?( !this.body.is( ':visible' ) ):( expand ); if( expand ){ - if( this.model.inReadyState() && !this.model.hasDetails() ){ - var xhr = this.model.fetch(); - xhr.done( function( model ){ - hdaView.expandBody(); - }); - } else { - this.expandBody(); - } + this.expandBody(); } else { this.collapseBody(); } }, + /** Render and show the full, detailed body of this view including extra data and controls. + * @fires body-expanded when a body has been expanded + */ expandBody : function(){ var hdaView = this; - hdaView._render_body_html( hdaView.body ); - this.body.slideDown( hdaView.fxSpeed, function(){ - hdaView.expanded = true; - hdaView.trigger( 'body-expanded', hdaView.model.get( 'id' ) ); - }); + + function _renderBodyAndExpand(){ + hdaView._render_body_html( hdaView.body ); + hdaView.body.slideDown( hdaView.fxSpeed, function(){ + hdaView.expanded = true; + hdaView.trigger( 'body-expanded', hdaView.model.get( 'id' ) ); + }); + } + // fetch first if no details in the model + if( this.model.inReadyState() && !this.model.hasDetails() ){ + this.model.fetch().done( function( model ){ + _renderBodyAndExpand(); + }); + } else { + _renderBodyAndExpand(); + } }, + /** Hide the body/details of an HDA. + * @fires body-collapsed when a body has been collapsed + */ collapseBody : function(){ var hdaView = this; this.body.slideUp( hdaView.fxSpeed, function(){ @@ -571,7 +541,10 @@ }); }, - // ......................................................................... DELETION + // ......................................................................... removal + /** Remove this view's html from the DOM and remove all event listeners. + * @param {Function} callback an optional function called when removal is done + */ remove : function( callback ){ var hdaView = this; this.$el.fadeOut( hdaView.fxSpeed, function(){ @@ -581,7 +554,8 @@ }); }, - // ......................................................................... MISC + // ......................................................................... misc + /** String representation */ toString : function(){ var modelString = ( this.model )?( this.model + '' ):( '(no model)' ); return 'HDABaseView(' + modelString + ')'; @@ -602,5 +576,5 @@ //============================================================================== return { - HDABaseView : HDABaseView, + HDABaseView : HDABaseView };}); diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/mvc/dataset/hda-edit.js --- a/static/scripts/mvc/dataset/hda-edit.js +++ b/static/scripts/mvc/dataset/hda-edit.js @@ -14,7 +14,7 @@ var HDAEditView = hdaBase.HDABaseView.extend( LoggableMixin ).extend( /** @lends HDAEditView.prototype */{ - // ......................................................................... SET UP + // ......................................................................... set up /** Set up the view, cache url templates, bind listeners. * Overrides HDABaseView.initialize to change default actions (adding re-run). * @param {Object} attributes @@ -43,7 +43,7 @@ //var hdaView = this; }, - // ......................................................................... RENDER WARNINGS + // ......................................................................... render warnings /** Render any hda warnings including: is deleted, is purged, is hidden. * Overrides _render_warnings to include links to further actions (undelete, etc.)). * @returns {Object} the templated urls @@ -71,13 +71,14 @@ return buttonDiv; }, +//TODO: move titleButtons into state renderers, remove state checks in the buttons + /** Render icon-button to edit the attributes (format, permissions, etc.) this hda. * @returns {jQuery} rendered DOM */ _render_editButton : function(){ // don't show edit while uploading, in-accessible // DO show if in error (ala previous history panel) - //TODO??: not viewable/accessible are essentially the same (not viewable set from accessible) if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW ) || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.UPLOAD ) || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE ) @@ -114,7 +115,6 @@ */ _render_deleteButton : function(){ // don't show delete if... - //TODO??: not viewable/accessible are essentially the same (not viewable set from accessible) if( ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NEW ) || ( this.model.get( 'state' ) === hdaModel.HistoryDatasetAssociation.STATES.NOT_VIEWABLE ) || ( !this.model.get( 'accessible' ) ) ){ @@ -147,7 +147,7 @@ return this.deleteButton.render().$el; }, - // ......................................................................... RENDER BODY + // ......................................................................... render body /** Render the data/metadata summary (format, size, misc info, etc.). * Overrides _render_hdaSummary to include edit link in dbkey. * @see HDABaseView#_render_hdaSummary @@ -158,7 +158,6 @@ // 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.isDeletedOrPurged() ){ - //TODO: use HDABaseView and select/replace base on this switch _.extend( modelData, { dbkey_unknown_and_editable : true }); } return hdaBase.HDABaseView.templates.hdaSummary( modelData ); @@ -238,10 +237,8 @@ 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 - /** @inner */ function create_viz_action( visualization ) { switch( visualization ){ @@ -269,7 +266,6 @@ // >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[ _l( titleCaseVisualization ) ] = create_viz_action( visualization ); }); @@ -334,9 +330,7 @@ /** Render icon-button to load and display tagging html. * @returns {jQuery} rendered DOM */ - //TODO: these should be a sub-MV _render_tagButton : function(){ - //TODO: check for User if( !this.hasUser || !this.urls.tags.get ){ this.tagButton = null; return null; @@ -354,9 +348,7 @@ /** Render icon-button to load and display annotation html. * @returns {jQuery} rendered DOM */ - //TODO: these should be a sub-MV _render_annotateButton : function(){ - //TODO: check for User if( !this.hasUser || !this.urls.annotation.get ){ this.annotateButton = null; return null; @@ -370,33 +362,6 @@ return this.annotateButton.render().$el; }, - // ......................................................................... other elements - /** Render area to display tags. - * @returns {jQuery} rendered DOM - */ -//TODO: into sub-MV -//TODO: check for User - _render_tagArea : function(){ - if( !this.urls.tags.set ){ return null; } - //TODO: move to mvc/tags.js - return $( HDAEditView.templates.tagArea( - _.extend( this.model.toJSON(), { urls: this.urls } ) - ).trim() ); - }, - - /** Render area to display annotation. - * @returns {jQuery} rendered DOM - */ -//TODO: into sub-MV -//TODO: check for User - _render_annotationArea : function(){ - if( !this.urls.annotation.get ){ return null; } - //TODO: move to mvc/annotations.js - return $( HDAEditView.templates.annotationArea( - _.extend( this.model.toJSON(), { urls: this.urls } ) - ).trim() ); - }, - // ......................................................................... state body renderers /** Render an HDA whose job has failed. * Overrides _render_body_error to prepend error report button to primary actions strip. @@ -415,7 +380,6 @@ * @see HDABaseView#_render_body_ok */ _render_body_ok : function( parent ){ - //TODO: should call super somehow and insert the needed... // most common state renderer and the most complicated parent.append( this._render_hdaSummary() ); @@ -451,7 +415,7 @@ parent.append( this._render_peek() ); }, - // ......................................................................... EVENTS + // ......................................................................... events /** event map */ events : { 'click .historyItemTitle' : 'toggleBodyVisibility', @@ -463,16 +427,28 @@ 'click a.icon-button.annotate' : 'loadAndDisplayAnnotation' }, - // ......................................................................... STATE CHANGES / MANIPULATION + /** listener for item purge */ confirmPurge : function _confirmPurge( ev ){ - //TODO: confirm dialog +//TODO: confirm dialog this.model.purge({ url: this.urls.purge }); return false; }, + // ......................................................................... tags + /** Render area to display tags. + * @returns {jQuery} rendered DOM + */ +//TODO: into sub-MV + _render_tagArea : function(){ + if( !this.hasUser || !this.urls.tags.set ){ return null; } + return $( HDAEditView.templates.tagArea( + _.extend( this.model.toJSON(), { urls: this.urls } ) + ).trim() ); + }, + /** Find the tag area and, if initial: load the html (via ajax) for displaying them; otherwise, unhide/hide */ - //TODO: into sub-MV +//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 @@ -508,6 +484,18 @@ } return false; }, + + // ......................................................................... annotations + /** Render area to display annotation. + * @returns {jQuery} rendered DOM + */ +//TODO: into sub-MV + _render_annotationArea : function(){ + if( !this.hasUser || !this.urls.annotation.get ){ return null; } + return $( HDAEditView.templates.annotationArea( + _.extend( this.model.toJSON(), { urls: this.urls } ) + ).trim() ); + }, /** Find the annotation area and, if initial: load the html (via ajax) for displaying them; otherwise, unhide/hide */ @@ -555,7 +543,7 @@ return false; }, - // ......................................................................... UTILTIY + // ......................................................................... misc /** string rep */ toString : function(){ var modelString = ( this.model )?( this.model + '' ):( '(no model)' ); @@ -678,5 +666,5 @@ //============================================================================== return { - HDAEditView : HDAEditView, + HDAEditView : HDAEditView };}); diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/mvc/dataset/hda-model.js --- a/static/scripts/mvc/dataset/hda-model.js +++ b/static/scripts/mvc/dataset/hda-model.js @@ -53,41 +53,42 @@ misc_info : '' }, - /** fetch location of this history in the api */ + /** fetch location of this HDA's history in the api */ urlRoot: 'api/histories/', + /** full url spec. for this HDA */ url : function(){ return this.urlRoot + this.get( 'history_id' ) + '/contents/' + this.get( 'id' ); }, + /** controller urls assoc. with this HDA */ urls : function(){ var id = this.get( 'id' ); if( !id ){ return {}; } var urls = { - 'delete' : galaxy_config.root + 'datasets/' + id + '/delete_async', - 'purge' : galaxy_config.root + 'datasets/' + id + '/purge_async', - 'unhide' : galaxy_config.root + 'datasets/' + id + '/unhide', - 'undelete' : galaxy_config.root + 'datasets/' + id + '/undelete', + 'purge' : galaxy_config.root + 'datasets/' + id + '/purge_async', - 'display' : galaxy_config.root + 'datasets/' + id + '/display/?preview=True', - 'download' : galaxy_config.root + 'datasets/' + id + '/display?to_ext=' + this.get( 'file_ext' ), - 'edit' : galaxy_config.root + 'datasets/' + id + '/edit', - 'report_error': galaxy_config.root + 'dataset/errors?id=' + id, - 'rerun' : galaxy_config.root + 'tool_runner/rerun?id=' + id, - 'show_params': galaxy_config.root + 'datasets/' + id + '/show_params', - 'visualization': galaxy_config.root + 'visualization', + 'display' : galaxy_config.root + 'datasets/' + id + '/display/?preview=True', + 'download' : galaxy_config.root + 'datasets/' + id + '/display?to_ext=' + this.get( 'file_ext' ), + 'edit' : galaxy_config.root + 'datasets/' + id + '/edit', + 'report_error' : galaxy_config.root + 'dataset/errors?id=' + id, + 'rerun' : galaxy_config.root + 'tool_runner/rerun?id=' + id, + 'show_params' : galaxy_config.root + 'datasets/' + id + '/show_params', + 'visualization' : galaxy_config.root + 'visualization', 'annotation': { 'get': galaxy_config.root + 'dataset/get_annotation_async?id=' + id, 'set': galaxy_config.root + 'dataset/annotate_async?id=' + id }, - 'tags' : { 'get': galaxy_config.root + 'tag/get_tagging_elt_async?item_id=' + id + '&item_class=HistoryDatasetAssociation', - 'set': galaxy_config.root + 'tag/retag?item_id=' + id + '&item_class=HistoryDatasetAssociation' } + 'tags' : { 'get': galaxy_config.root + 'tag/get_tagging_elt_async?item_id=' + + id + '&item_class=HistoryDatasetAssociation', + 'set': galaxy_config.root + 'tag/retag?item_id=' + + id + '&item_class=HistoryDatasetAssociation' } }; - //'meta_download': '/dataset/get_metadata_file?hda_id=%3C%25%3D+id+%25%3E&metadata_name=%3C%25%3D+file_type+%25%3E', + // download links to assoc. metadata files (bam indeces, etc.) var meta_files = this.get( 'meta_files' ); if( meta_files ){ urls.meta_download = _.map( meta_files, function( meta_file ){ return { - //url : _.template( urlTemplate, { id: modelJson.id, file_type: meta_file.file_type }), - url : galaxy_config.root + 'dataset/get_metadata_file?hda_id=' + id + '&metadata_name=' + meta_file.file_type, + url : galaxy_config.root + 'dataset/get_metadata_file?hda_id=' + + id + '&metadata_name=' + meta_file.file_type, file_type : meta_file.file_type }; }); @@ -110,6 +111,9 @@ this._setUpListeners(); }, + /** set up any event listeners + * event: state:ready fired when this HDA moves into a ready state + */ _setUpListeners : function(){ // if the state has changed and the new state is a ready state, fire an event this.on( 'change:state', function( currModel, newState ){ @@ -121,8 +125,7 @@ }, // ........................................................................ common queries - /** Is this hda deleted or purged? - */ + /** Is this hda deleted or purged? */ isDeletedOrPurged : function(){ return ( this.get( 'deleted' ) || this.get( 'purged' ) ); }, @@ -132,7 +135,6 @@ * @param {Boolean} show_deleted are we showing deleted hdas? * @param {Boolean} show_hidden are we showing hidden hdas? */ - //TODO: too many 'visible's isVisible : function( show_deleted, show_hidden ){ var isVisible = true; if( ( !show_deleted ) @@ -146,6 +148,7 @@ return isVisible; }, + /** the more common alias of visible */ hidden : function(){ return !this.get( 'visible' ); }, @@ -158,33 +161,37 @@ return ( this.isDeletedOrPurged() || ready ); }, + /** Does this model already contain detailed data (as opposed to just summary level data)? */ hasDetails : function(){ //?? this may not be reliable return _.has( this.attributes, 'genome_build' ); }, - /** Convenience function to match hda.has_data. - */ + /** Convenience function to match hda.has_data. */ hasData : function(){ - //TODO:?? is this equivalent to all possible hda.has_data calls? return ( this.get( 'file_size' ) > 0 ); }, // ........................................................................ ajax + /** save this HDA, _Mark_ing it as deleted (just a flag) */ 'delete' : function _delete( options ){ return this.save( { deleted: true }, options ); }, + /** save this HDA, _Mark_ing it as undeleted */ undelete : function _undelete( options ){ return this.save( { deleted: false }, options ); }, + /** save this HDA as not visible */ hide : function _hide( options ){ return this.save( { visible: false }, options ); }, + /** save this HDA as visible */ unhide : function _uhide( options ){ return this.save( { visible: true }, options ); }, + /** purge this HDA and remove the underlying dataset file from the server's fs */ purge : function _purge( options ){ //TODO: ideally this would be a DELETE call to the api // using purge async for now @@ -210,10 +217,15 @@ }, // ........................................................................ sorting/filtering + /** what attributes of an HDA will be used in a search */ searchKeys : [ 'name', 'file_ext', 'genome_build', 'misc_blurb', 'misc_info', 'annotation', 'tags' ], + /** search this HDA for the string searchFor + * @param {String} searchFor look for this string in all attributes listed in searchKeys (above) using indexOf + * @returns {Array} an array of attribute keys where searchFor was found + */ search : function( searchFor ){ var model = this; searchFor = searchFor.toLowerCase(); @@ -223,13 +235,16 @@ }); }, + /** alias of search, but returns a boolean + * @param {String} matchesWhat look for this string in all attributes listed in searchKeys (above) using indexOf + * @returns {Boolean} was matchesWhat found in any attributes + */ matches : function( matchesWhat ){ return !!this.search( matchesWhat ).length; }, // ........................................................................ misc - /** String representation - */ + /** String representation */ toString : function(){ var nameAndId = this.get( 'id' ) || ''; if( this.get( 'name' ) ){ @@ -274,6 +289,7 @@ ERROR : 'error' }; +/** states that are in a final state (the underlying job is complete) */ HistoryDatasetAssociation.READY_STATES = [ HistoryDatasetAssociation.STATES.NEW, HistoryDatasetAssociation.STATES.OK, @@ -285,6 +301,7 @@ HistoryDatasetAssociation.STATES.ERROR ]; +/** states that will change (the underlying job is not finished) */ HistoryDatasetAssociation.NOT_READY_STATES = [ HistoryDatasetAssociation.STATES.UPLOAD, HistoryDatasetAssociation.STATES.QUEUED, @@ -306,7 +323,10 @@ ///** logger used to record this.log messages, commonly set to console */ //// comment this out to suppress log output //logger : console, + + /** root api url */ urlRoot : galaxy_config.root + 'api/histories', + /** complete api url */ url : function(){ return this.urlRoot + '/' + this.historyId + '/contents'; }, @@ -331,6 +351,9 @@ return this.map( function( hda ){ return hda.id; }); }, + /** Get hdas that are not ready + * @returns array of HDAs + */ notReady : function(){ return this.filter( function( hda ){ return !hda.inReadyState(); @@ -370,11 +393,13 @@ }, // ........................................................................ ajax + /** fetch detailed model data for all HDAs in this collection */ fetchAllDetails : function(){ return this.fetch({ data : { details : 'all' } }); }, // ........................................................................ sorting/filtering + /** return a new collection of HDAs whose attributes contain the substring matchesWhat */ matches : function( matchesWhat ){ return this.filter( function( hda ){ return hda.matches( matchesWhat ); diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/mvc/history/history-model.js --- a/static/scripts/mvc/history/history-model.js +++ b/static/scripts/mvc/history/history-model.js @@ -13,7 +13,6 @@ */ var History = Backbone.Model.extend( LoggableMixin ).extend( /** @lends History.prototype */{ - //TODO: bind change events from items and collection to this (itemLengths, states) ///** logger used to record this.log messages, commonly set to console */ //// comment this out to suppress log output @@ -33,17 +32,20 @@ // ........................................................................ urls urlRoot: galaxy_config.root + 'api/histories', + /** url for changing the name of the history */ renameUrl : function(){ //TODO: just use this.save() var id = this.get( 'id' ); if( !id ){ return undefined; } return galaxy_config.root + 'history/rename_async?id=' + this.get( 'id' ); }, + /** url for changing the annotation of the history */ annotateUrl : function(){ var id = this.get( 'id' ); if( !id ){ return undefined; } return galaxy_config.root + 'history/annotate_async?id=' + this.get( 'id' ); }, + /** url for changing the tags of the history */ tagUrl : function(){ var id = this.get( 'id' ); if( !id ){ return undefined; } @@ -51,9 +53,10 @@ }, // ........................................................................ set up/tear down - /** Set up the hdas collection + /** Set up the model * @param {Object} historyJSON model data for this History * @param {Object[]} hdaJSON array of model data for this History's HDAs + * @param {Object} options any extra settings including logger * @see BaseModel#initialize */ initialize : function( historyJSON, hdaJSON, options ){ @@ -70,10 +73,15 @@ this._setUpListeners(); + /** cached timeout id for the HDA updater */ + this.updateTimeoutId = null; // set up update timeout if needed this.checkForUpdates(); }, + /** set up any event listeners for this history including those to the contained HDAs + * events: error:hdas if an error occurred with the HDA collection + */ _setUpListeners : function(){ this.on( 'error', function( model, xhr, options, msg, details ){ this.errorHandler( model, xhr, options, msg, details ); @@ -107,25 +115,29 @@ // } //}, + /** event listener for errors. Generally errors are handled outside this model */ errorHandler : function( model, xhr, options, msg, details ){ // clear update timeout on model err this.clearUpdateTimeout(); }, // ........................................................................ common queries + /** is this model already associated with a user? */ hasUser : function(){ var user = this.get( 'user' ); return !!( user && user.id ); }, // ........................................................................ ajax - // get the history's state from it's cummulative ds states, delay + update if needed - // events: ready + /** does the HDA collection indicate they're still running and need to be updated later? delay + update if needed + * @param {Function} onReadyCallback function to run when all HDAs are in the ready state + * events: ready + */ checkForUpdates : function( onReadyCallback ){ //console.info( 'checkForUpdates' ) // get overall History state from collection, run updater if History has running/queued hdas - // boiling it down on the client to running/not + // boiling it down on the client to running/not if( this.hdas.running().length ){ this.setUpdateTimeout(); @@ -138,8 +150,8 @@ return this; }, + /** create a timeout (after UPDATE_DELAY or delay ms) to refetch the HDA collection. Clear any prev. timeout */ setUpdateTimeout : function( delay ){ - //TODO: callbacks? delay = delay || History.UPDATE_DELAY; var history = this; @@ -151,6 +163,7 @@ return this.updateTimeoutId; }, + /** clear the timeout and the cached timeout id */ clearUpdateTimeout : function(){ if( this.updateTimeoutId ){ clearTimeout( this.updateTimeoutId ); @@ -158,25 +171,26 @@ } }, - // 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 - // events: ready + /* update the HDA collection getting full detailed model data for any hda whose id is in detailIds + * set up to run this again in some interval of time + * @param {String[]} detailIds list of HDA ids to get detailed model data for + * @param {Object} options std. backbone fetch options map + */ refresh : function( detailIds, options ){ //console.info( 'refresh:', detailIds, this.hdas ); detailIds = detailIds || []; options = options || {}; var history = this; + // add detailIds to options as CSV string options.data = options.data || {}; if( detailIds.length ){ options.data.details = detailIds.join( ',' ); } var xhr = this.hdas.fetch( options ); xhr.done( function( hdaModels ){ - //this.trigger( 'hdas-refreshed', this, hdaModels ); - history.checkForUpdates(function(){ - // fetch the history after an update in order to recalc history size - //TODO: move to event? + history.checkForUpdates( function(){ + // fetch the history inside onReadyCallback in order to recalc history size this.fetch(); }); }); diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/mvc/history/history-panel.js --- a/static/scripts/mvc/history/history-panel.js +++ b/static/scripts/mvc/history/history-panel.js @@ -16,20 +16,14 @@ meta: css/html class/id 'item' -> hda add classes, ids on empty divs - events (local/ui and otherwise) - list in docs as well - require.js convert function comments to jsDoc style, complete comments move inline styles into base.less - watch the magic strings - watch your globals feature creep: 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 @@ -58,13 +52,14 @@ tagName : 'div', className : 'history-panel', - //fxSpeed : 'fast', + /** (in ms) that jquery effects will use */ fxSpeed : 300, - /** event map - */ + /** event map */ events : { 'click #history-tag' : 'loadAndDisplayTags', + // allow (error) messages to be clicked away +//TODO: switch to common close (X) idiom 'click #message-container' : 'clearMessages' }, @@ -107,6 +102,10 @@ } }, + /** create any event listeners for the panel + * @fires: rendered:initial on the first render + * @fires: empty-history when switching to a history with no HDAs or creating a new history + */ _setUpListeners : function(){ // ---- event handlers for self this.on( 'error', function( model, xhr, options, msg, details ){ @@ -154,13 +153,24 @@ //}, // ........................................................................ error handling + /** Event listener to handle errors (from the panel, the history, or the history's HDAs) + * @param {Model or View} model the (Backbone) source of the error + * @param {XMLHTTPRequest} xhr any ajax obj. assoc. with the error + * @param {Object} options the options map commonly used with bbone ajax + * @param {String} msg optional message passed to ease error location + * @param {Object} msg optional object containing error details + */ errorHandler : function( model, xhr, options, msg, details ){ var parsed = this._parseErrorMessage( model, xhr, options, msg, details ); + // interrupted ajax if( xhr && xhr.status === 0 && xhr.readyState === 0 ){ + // bad gateway } else if( xhr && xhr.status === 502 ){ +//TODO: gmail style 'reconnecting in Ns' + // otherwise, show an error message inside the panel } else { // it's possible to have a triggered error before the message container is rendered - wait for it to show if( !this.$el.find( '#message-container' ).is( ':visible' ) ){ @@ -173,6 +183,9 @@ } }, + /** Parse an error event into an Object usable by displayMessage based on the parameters + * note: see errorHandler for more info on params + */ _parseErrorMessage : function( model, xhr, options, msg, details ){ var user = Galaxy.currUser, // add the args (w/ some extra info) into an obj @@ -199,12 +212,92 @@ return parsed; }, + /** Modify an error message to be fancy and wear a monocle. */ _bePolite : function( msg ){ msg = msg || _l( 'An error occurred while getting updates from the server' ); return msg + '. ' + _l( 'Please contact a Galaxy administrator if the problem persists.' ); }, // ------------------------------------------------------------------------ loading history/hda models + + //NOTE: all the following fns replace the existing history model with a new model + // (in the following 'details' refers to the full set of hda api data (urls, display_apps, misc_info, etc.) + // - hdas w/o details will have summary data only (name, hid, deleted, visible, state, etc.)) + + /** (re-)loads the user's current history & hdas w/ details */ + // implemented as a 'fresh start' or for when there is no model (intial panel render) + loadCurrentHistory : function( attributes ){ + var panel = this; + return this.loadHistoryWithHDADetails( 'current', attributes ) + .then(function( historyData, hdaData ){ + panel.trigger( 'current-history', panel ); + }); + }, + + /** loads a history & hdas w/ details and makes them the current history */ + switchToHistory : function( historyId, attributes ){ + //console.info( 'switchToHistory:', historyId, attributes ); + var panel = this, + historyFn = function(){ + // make this current and get history data with one call + return jQuery.post( galaxy_config.root + 'api/histories/' + historyId + '/set_as_current' ); + }; + return this.loadHistoryWithHDADetails( historyId, attributes, historyFn ) + .then(function( historyData, hdaData ){ + panel.trigger( 'switched-history', panel ); + }); + }, + + /** creates a new history on the server and sets it as the user's current history */ + createNewHistory : function( attributes ){ + var panel = this, + historyFn = function(){ + // get history data from posting a new history (and setting it to current) + return jQuery.post( galaxy_config.root + 'api/histories', { current: true }); + }; + // id undefined bc there is no historyId yet - the server will provide + // (no need for details - nothing expanded in new history) + return this.loadHistory( undefined, attributes, historyFn ) + .then(function( historyData, hdaData ){ + panel.trigger( 'new-history', panel ); + }); + }, + + /** loads a history & hdas w/ details (but does not make them the current history) */ + loadHistoryWithHDADetails : function( historyId, attributes, historyFn, hdaFn ){ + //console.info( 'loadHistoryWithHDADetails:', historyId, attributes, historyFn, hdaFn ); + var panel = this, + // will be called to get hda ids that need details from the api + hdaDetailIds = function( historyData ){ + return panel.getExpandedHdaIds( historyData.id ); + }; + return this.loadHistory( historyId, attributes, historyFn, hdaFn, hdaDetailIds ); + }, + + /** loads a history & hdas w/ NO details (but does not make them the current history) */ + loadHistory : function( historyId, attributes, historyFn, hdaFn, hdaDetailIds ){ + this.trigger( 'loading-history', this ); + attributes = attributes || {}; + var panel = this; + //console.info( 'loadHistory:', historyId, attributes, historyFn, hdaFn, hdaDetailIds ); + var xhr = historyModel.History.getHistoryData( historyId, { + historyFn : historyFn, + hdaFn : hdaFn, + hdaDetailIds : attributes.initiallyExpanded || hdaDetailIds + }); + //console.debug( 'xhr:', xhr ); + return this._loadHistoryFromXHR( xhr, attributes ) + .fail( function( xhr, where, history ){ + // throw an error up for the error handler + panel.trigger( 'error', panel, xhr, attributes, _l( 'An error was encountered while ' + where ), + { historyId: historyId, history: history || {} }); + }) + .always( function(){ + // bc hideLoadingIndicator relies on this firing + panel.trigger( 'loading-done', panel ); + }); + }, + /** given an xhr that will provide both history and hda data, pass data to set model or handle xhr errors */ _loadHistoryFromXHR : function( xhr, attributes ){ var panel = this; @@ -246,84 +339,6 @@ return this; }, - //NOTE: all the following fns replace the existing history model with a new model - // (in the following 'details' refers to the full set of hda api data (urls, display_apps, misc_info, etc.) - // - hdas w/o details will have summary data only (name, hid, deleted, visible, state, etc.)) - - /** loads a history & hdas w/ NO details (but does not make them the current history) */ - loadHistory : function( historyId, attributes, historyFn, hdaFn, hdaDetailIds ){ - this.trigger( 'loading-history', this ); - attributes = attributes || {}; - var panel = this; - //console.info( 'loadHistory:', historyId, attributes, historyFn, hdaFn, hdaDetailIds ); - var xhr = historyModel.History.getHistoryData( historyId, { - historyFn : historyFn, - hdaFn : hdaFn, - hdaDetailIds : attributes.initiallyExpanded || hdaDetailIds - }); - //console.debug( 'xhr:', xhr ); - return this._loadHistoryFromXHR( xhr, attributes ) - .fail( function( xhr, where, history ){ - // throw an error up for the error handler - panel.trigger( 'error', panel, xhr, attributes, _l( 'An error was encountered while ' + where ), - { historyId: historyId, history: history || {} }); - }) - .always( function(){ - // bc hideLoadingIndicator relies on this firing - panel.trigger( 'loading-done', panel ); - }); - }, - - /** loads a history & hdas w/ details (but does not make them the current history) */ - loadHistoryWithHDADetails : function( historyId, attributes, historyFn, hdaFn ){ - //console.info( 'loadHistoryWithHDADetails:', historyId, attributes, historyFn, hdaFn ); - var panel = this, - // will be called to get hda ids that need details from the api - hdaDetailIds = function( historyData ){ - return panel.getExpandedHdaIds( historyData.id ); - }; - return this.loadHistory( historyId, attributes, historyFn, hdaFn, hdaDetailIds ); - }, - - /** loads a history & hdas w/ details and makes them the current history */ - switchToHistory : function( historyId, attributes ){ - //console.info( 'switchToHistory:', historyId, attributes ); - var panel = this, - historyFn = function(){ - // make this current and get history data with one call - return jQuery.post( galaxy_config.root + 'api/histories/' + historyId + '/set_as_current' ); - }; - return this.loadHistoryWithHDADetails( historyId, attributes, historyFn ) - .then(function( historyData, hdaData ){ - panel.trigger( 'switched-history', panel ); - }); - }, - - /** (re-)loads the user's current history & hdas w/ details */ - // implemented as a 'fresh start' or for when there is no model (intial panel render) - loadCurrentHistory : function( attributes ){ - var panel = this; - return this.loadHistoryWithHDADetails( 'current', attributes ) - .then(function( historyData, hdaData ){ - panel.trigger( 'current-history', panel ); - }); - }, - - /** creates a new history on the server and sets it as the user's current history */ - createNewHistory : function( attributes ){ - var panel = this, - historyFn = function(){ - // get history data from posting a new history (and setting it to current) - return jQuery.post( galaxy_config.root + 'api/histories', { current: true }); - }; - // id undefined bc there is no historyId yet - the server will provide - // (no need for details - nothing expanded in new history) - return this.loadHistory( undefined, attributes, historyFn ) - .then(function( historyData, hdaData ){ - panel.trigger( 'new-history', panel ); - }); - }, - // alias to the model. Updates the hda list only (not the history) refreshHdas : function( detailIds, options ){ if( this.model ){ @@ -334,15 +349,7 @@ }, // ------------------------------------------------------------------------ browser stored prefs - //TODO: simplify - - /** key string to store each histories settings under */ - _getStorageKey : function( id ){ - if( !id ){ - throw new Error( '_getStorageKey needs valid id: ' + id ); - } - return ( 'history:' + id ); - }, +//TODO: simplify /** Set up client side storage. Currently PersistanStorage keyed under 'HistoryPanel.<id>' * @param {Object} initiallyExpanded @@ -359,7 +366,6 @@ // data that needs to be persistent over page refreshes // (note the key function which uses the history id as well) this.storage = new PersistentStorage( this._getStorageKey( this.model.get( 'id' ) ), { - //TODO: initiallyExpanded only works on first load right now expandedHdas : {}, show_deleted : false, show_hidden : false @@ -393,6 +399,15 @@ this.log( this + ' (init\'d) storage:', this.storage.get() ); }, + /** key string to store each histories settings under */ + _getStorageKey : function( id ){ + if( !id ){ + throw new Error( '_getStorageKey needs valid id: ' + id ); + } + return ( 'history:' + id ); + }, + + /** clear all stored history panel data */ clearWebStorage : function(){ for( var key in sessionStorage ){ if( key.indexOf( 'HistoryView.' ) === 0 ){ @@ -401,6 +416,7 @@ } }, + /** get all stored data as an Object for a history with the given id */ getStoredOptions : function( historyId ){ if( !historyId || historyId === 'current' ){ return ( this.storage )?( this.storage.get() ):( {} ); @@ -410,12 +426,14 @@ return ( item === null )?( {} ):( JSON.parse( item ) ); }, + /** get all the map of expaneded hda ids for the given history id */ getExpandedHdaIds : function( historyId ){ var expandedHdas = this.getStoredOptions( historyId ).expandedHdas; return (( _.isEmpty( expandedHdas ) )?( [] ):( _.keys( expandedHdas ) )); }, // ------------------------------------------------------------------------ history/hda event listening + /** listening for history and HDA events */ _setUpModelEventHandlers : function(){ // ---- history // on a model error - bounce it up to the panel and remove it from the model @@ -454,7 +472,7 @@ this.model.hdas.on( 'state:ready', function( hda, newState, oldState ){ if( ( !hda.get( 'visible' ) ) && ( !this.storage.get( 'show_hidden' ) ) ){ - this.removeHdaView( hda.get( 'id' ) ); + this.removeHdaView( this.hdaViews[ hda.id ] ); } }, this ); @@ -491,7 +509,9 @@ ]); }, -//TODO: use this below in renderItems + /** Create an HDA view for the given HDA (but leave attachment for addHdaView above) + * @param {HistoryDatasetAssociation} hda + */ createHdaView : function( hda ){ var hdaId = hda.get( 'id' ), expanded = this.storage.get( 'expandedHdas' ).get( hdaId ), @@ -506,12 +526,31 @@ return hdaView.render(); }, + /** Set up HistoryPanel listeners for HDAView events. Currently binds: + * HDAView#body-visible, HDAView#body-hidden to store expanded states + * @param {HDAView} hdaView HDAView (base or edit) to listen to + */ + _setUpHdaListeners : function( hdaView ){ + var historyView = this; + // maintain a list of hdas whose bodies are expanded + hdaView.on( 'body-expanded', function( id ){ + historyView.storage.get( 'expandedHdas' ).set( id, true ); + }); + hdaView.on( 'body-collapsed', function( id ){ + historyView.storage.get( 'expandedHdas' ).deleteKey( id ); + }); +//TODO: remove? + hdaView.on( 'error', function( model, xhr, options, msg ){ + historyView.errorHandler( model, xhr, options, msg ); + }); + }, + /** If this hda is deleted and we're not showing deleted hdas, remove the view * @param {HistoryDataAssociation} the hda to check */ handleHdaDeletionChange : function( hda ){ if( hda.get( 'deleted' ) && !this.storage.get( 'show_deleted' ) ){ - this.removeHdaView( hda.get( 'id' ) ); + this.removeHdaView( this.hdaViews[ hda.id ] ); } // otherwise, the hdaView rendering should handle it }, @@ -520,22 +559,21 @@ */ handleHdaVisibleChange : function( hda ){ if( hda.hidden() && !this.storage.get( 'show_hidden' ) ){ - this.removeHdaView( hda.get( 'id' ) ); + this.removeHdaView( this.hdaViews[ hda.id ] ); } // otherwise, the hdaView rendering should handle it }, /** Remove a view from the panel and if the panel is now empty, re-render * @param {Int} the id of the hdaView to remove */ - removeHdaView : function( id ){ - //console.debug( 'removeHdaView' ); - var panel = this, - hdaView = this.hdaViews[ id ]; + removeHdaView : function( hdaView ){ if( !hdaView ){ return; } + var panel = this; hdaView.$el.fadeOut( panel.fxSpeed, function(){ + hdaView.off(); hdaView.remove(); - delete panel.hdaViews[ id ]; + delete panel.hdaViews[ hdaView.model.id ]; if( _.isEmpty( panel.hdaViews ) ){ panel.$el.find( '#emptyHistoryMessage' ).fadeIn( panel.fxSpeed ); } @@ -544,10 +582,9 @@ // ------------------------------------------------------------------------ panel rendering /** Render urls, historyPanel body, and hdas (if any are shown) + * @fires: rendered when the panel is attached and fully visible * @see Backbone.View#render */ - /** event rendered triggered when the panel rendering is complete */ - /** event rendered:initial triggered when the FIRST panel rendering is complete */ render : function( callback ){ var panel = this, $newRender; @@ -579,11 +616,13 @@ //TODO: ideally, these would be set up before the fade in (can't because of async save text) panel._setUpBehaviours(); if( callback ){ callback.call( this ); } + panel.trigger( 'rendered', this ); } ]); return this; }, + /** render with history data */ renderModel : function( ){ var $newRender = $( '<div/>' ); // render the main template, tooltips @@ -601,7 +640,9 @@ return $newRender; }, + /** render with no history data */ renderWithoutModel : function( ){ + // we'll always need the message container var $newRender = $( '<div/>' ), $msgContainer = $( '<div/>' ).attr( 'id', 'message-container' ) .css({ 'margin-left': '4px', 'margin-right': '4px' }); @@ -624,44 +665,12 @@ ); _.each( visibleHdas, function( hda ){ - var hdaId = hda.get( 'id' ), - expanded = historyView.storage.get( 'expandedHdas' ).get( hdaId ); - - historyView.hdaViews[ hdaId ] = new historyView.HDAView({ - model : hda, - expanded : expanded, - hasUser : historyView.model.hasUser(), - logger : historyView.logger - }); - 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 ); + $whereTo.prepend( historyView.createHdaView( hda ).$el ); }); return visibleHdas.length; }, - /** Set up HistoryPanel listeners for HDAView events. Currently binds: - * HDAView#body-visible, HDAView#body-hidden to store expanded states - * @param {HDAView} hdaView HDAView (base or edit) to listen to - */ - _setUpHdaListeners : function( hdaView ){ - var historyView = this; - // maintain a list of hdas whose bodies are expanded - hdaView.on( 'body-expanded', function( id ){ - historyView.storage.get( 'expandedHdas' ).set( id, true ); - }); - hdaView.on( 'body-collapsed', function( id ){ - historyView.storage.get( 'expandedHdas' ).deleteKey( id ); - }); -//TODO: remove? - hdaView.on( 'error', function( model, xhr, options, msg ){ -//TODO: change to modal? - historyView.errorHandler( model, xhr, options, msg ); - }); - }, - /** Set up HistoryPanel js/widget behaviours */ //TODO: these should be either sub-MVs, or handled by events @@ -770,6 +779,7 @@ }, // ........................................................................ loading indicator + /** hide the panel and display a loading indicator (in the panel's parent) when history model's are switched */ showLoadingIndicator : function( msg, speed, callback ){ speed = ( speed !== undefined )?( speed ):( this.fxSpeed ); if( !this.indicator ){ @@ -783,6 +793,7 @@ } }, + /** hide the loading indicator */ hideLoadingIndicator : function( speed, callback ){ speed = ( speed !== undefined )?( speed ):( this.fxSpeed ); if( this.indicator ){ @@ -816,6 +827,7 @@ return $msgContainer.html( $msg ); }, + /** convert msg and details into modal options usable by Galaxy.modal */ messageToModalOptions : function( type, msg, details ){ // only error is fleshed out here var panel = this, @@ -860,10 +872,12 @@ }, // ........................................................................ scrolling + /** get the current scroll position of the panel in its parent */ scrollPosition : function(){ return this.$el.parent().scrollTop(); }, + /** set the current scroll position of the panel in its parent */ scrollTo : function( pos ){ this.$el.parent().scrollTop( pos ); }, @@ -925,6 +939,7 @@ // ........................................................................ external objects/MVC //TODO: remove quota meter from panel and remove this + /** add listeners to an external quota meter (mvc/user/user-quotameter.js) */ connectToQuotaMeter : function( quotaMeter ){ if( !quotaMeter ){ return this; @@ -942,25 +957,26 @@ return this; }, +//TODO: this seems more like a per user message than a history message; IOW, this doesn't belong here /** Show the over quota message (which happens to be in the history panel). */ -//TODO: this seems more like a per user message than a history message; IOW, this doesn't belong here showQuotaMessage : function(){ var msg = this.$el.find( '#quota-message-container' ); //this.log( this + ' showing quota message:', msg, userData ); if( msg.is( ':hidden' ) ){ msg.slideDown( this.fxSpeed ); } }, +//TODO: this seems more like a per user message than a history message /** Hide the over quota message (which happens to be in the history panel). */ -//TODO: this seems more like a per user message than a history message hideQuotaMessage : function(){ var msg = this.$el.find( '#quota-message-container' ); //this.log( this + ' hiding quota message:', msg, userData ); if( !msg.is( ':hidden' ) ){ msg.slideUp( this.fxSpeed ); } }, - //TODO: move show_deleted/hidden into panel from opt menu and remove this +//TODO: move show_deleted/hidden into panel from opt menu and remove this + /** add listeners to an external options menu (templates/webapps/galaxy/root/index.mako) */ connectToOptionsMenu : function( optionsMenu ){ if( !optionsMenu ){ return this; diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/packed/mvc/dataset/hda-base.js --- a/static/scripts/packed/mvc/dataset/hda-base.js +++ b/static/scripts/packed/mvc/dataset/hda-base.js @@ -1,1 +1,1 @@ -define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.expanded=c.expanded||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(){var d=this,g=this.model.get("id"),e=this.model.get("state"),c=$("<div/>").attr("id","historyItem-"+g),f=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+g);this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();c.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+e);c.append(this._render_warnings());c.append(this._render_titleBar());this._setUpBehaviors(c);this.body=$(this._render_body());c.append(this.body);this.$el.fadeOut(this.fxSpeed,function(){d.$el.children().remove();d.$el.append(c).fadeIn(d.fxSpeed,function(){d.log(d+" rendered:",d.$el);var h="rendered";if(f){h+=":initial"}else{if(d.model.inReadyState()){h+=":ready"}}d.trigger(h)})});return this},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(a.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var c=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');c.append(this._render_titleButtons());c.append('<span class="state-icon"></span>');c.append(this._render_titleLink());return c},_render_titleButtons:function(){var c=$('<div class="historyItemButtons"></div>');c.append(this._render_displayButton());return c},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){this.displayButton=null;return null}var d={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){d.enabled=false;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.enabled=false;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.on_click=function(){Galaxy.frame_manager.frame_new({title:"Data Viewer: "+c.model.get("name"),type:"url",location:"center",content:c.urls.display})}}}this.displayButton=new IconButtonView({model:new IconButton(d)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(a.templates.titleLink(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_hdaSummary:function(){var c=_.extend(this.model.toJSON(),{urls:this.urls});return a.templates.hdaSummary(c)},_render_primaryActionButtons:function(e){var c=this,d=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(e,function(f){d.append(f.call(c))});return d},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var c=a.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(c.trim())},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayAppArea:function(){return $("<div/>").addClass("display-apps")},_render_displayApps:function(e){e=e||this.$el;var f=e.find("div.display-apps"),c=this.model.get("display_types"),d=this.model.get("display_apps");if((!this.model.hasData())||(!e||!e.length)||(!f.length)){return}f.html(null);if(!_.isEmpty(c)){f.append(a.templates.displayApps({displayApps:c}))}if(!_.isEmpty(d)){f.append(a.templates.displayApps({displayApps:d}))}},_render_peek:function(){var c=this.model.get("peek");if(!c){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(c))},_render_body:function(){var c=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(c);c.css("display","block")}return c},_render_body_html:function(c){c.html("");switch(this.model.get("state")){case b.HistoryDatasetAssociation.STATES.NEW:this._render_body_new(c);break;case b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE:this._render_body_not_viewable(c);break;case b.HistoryDatasetAssociation.STATES.UPLOAD:this._render_body_uploading(c);break;case b.HistoryDatasetAssociation.STATES.PAUSED:this._render_body_paused(c);break;case b.HistoryDatasetAssociation.STATES.QUEUED:this._render_body_queued(c);break;case b.HistoryDatasetAssociation.STATES.RUNNING:this._render_body_running(c);break;case b.HistoryDatasetAssociation.STATES.ERROR:this._render_body_error(c);break;case b.HistoryDatasetAssociation.STATES.DISCARDED:this._render_body_discarded(c);break;case b.HistoryDatasetAssociation.STATES.SETTING_METADATA:this._render_body_setting_metadata(c);break;case b.HistoryDatasetAssociation.STATES.EMPTY:this._render_body_empty(c);break;case b.HistoryDatasetAssociation.STATES.FAILED_METADATA:this._render_body_failed_metadata(c);break;case b.HistoryDatasetAssociation.STATES.OK:this._render_body_ok(c);break;default:c.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}c.append('<div style="clear: both"></div>');this._setUpBehaviors(c)},_render_body_new:function(d){var c=_l("This is a new dataset and not all of its data are available yet");d.append($("<div>"+_l(c)+"</div>"))},_render_body_not_viewable:function(c){c.append($("<div>"+_l("You do not have permission to view dataset")+"</div>"))},_render_body_uploading:function(c){c.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(c){c.append($("<div>"+_l("Job is waiting to run")+"</div>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(c){c.append($("<div>"+_l("Job is paused. Use the history menu to resume")+"</div>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(c){c.append("<div>"+_l("Job is currently running")+"</div>");c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(c){if(!this.model.get("purged")){c.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}c.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(c){c.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(c){c.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(c){c.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(c){c.append($(a.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(c)},_render_body_ok:function(c){c.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){c.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}c.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));c.append('<div class="clear"/>');c.append(this._render_displayAppArea());this._render_displayApps(c);c.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(e,c){var d=this;c=(c===undefined)?(!this.body.is(":visible")):(c);if(c){if(this.model.inReadyState()&&!this.model.hasDetails()){var f=this.model.fetch();f.done(function(g){d.expandBody()})}else{this.expandBody()}}else{this.collapseBody()}},expandBody:function(){var c=this;c._render_body_html(c.body);this.body.slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})},collapseBody:function(){var c=this;this.body.slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};return{HDABaseView:a,}}); \ No newline at end of file +define(["mvc/dataset/hda-model"],function(b){var a=Backbone.View.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",fxSpeed:"fast",initialize:function(c){if(c.logger){this.logger=this.model.logger=c.logger}this.log(this+".initialize:",c);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.expanded=c.expanded||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(d,c){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(){var d=this,g=this.model.get("id"),e=this.model.get("state"),c=$("<div/>").attr("id","historyItem-"+g),f=(this.$el.children().size()===0);this.$el.attr("id","historyItemContainer-"+g);this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();c.addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+e);c.append(this._render_warnings());c.append(this._render_titleBar());this._setUpBehaviors(c);this.body=$(this._render_body());c.append(this.body);this.$el.fadeOut(this.fxSpeed,function(){d.$el.children().remove();d.$el.append(c).fadeIn(d.fxSpeed,function(){d.log(d+" rendered:",d.$el);var h="rendered";if(f){h+=":initial"}else{if(d.model.inReadyState()){h+=":ready"}}d.trigger(h)})});return this},_setUpBehaviors:function(c){c=c||this.$el;make_popup_menus(c);c.find("[title]").tooltip({placement:"bottom"})},_render_warnings:function(){return $(jQuery.trim(a.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var c=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');c.append(this._render_titleButtons());c.append('<span class="state-icon"></span>');c.append(this._render_titleLink());return c},_render_titleButtons:function(){var c=$('<div class="historyItemButtons"></div>');c.append(this._render_displayButton());return c},_render_displayButton:function(){if((this.model.get("state")===b.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===b.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){this.displayButton=null;return null}var d={icon_class:"display",target:"galaxy_main"};if(this.model.get("purged")){d.enabled=false;d.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===b.HistoryDatasetAssociation.STATES.UPLOAD){d.enabled=false;d.title=_l("This dataset must finish uploading before it can be viewed")}else{d.title=_l("View data");d.href=this.urls.display;var c=this;d.on_click=function(){Galaxy.frame_manager.frame_new({title:"Data Viewer: "+c.model.get("name"),type:"url",location:"center",content:c.urls.display})}}}this.displayButton=new IconButtonView({model:new IconButton(d)});return this.displayButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(a.templates.titleLink(this.model.toJSON())))},_render_hdaSummary:function(){var c=_.extend(this.model.toJSON(),{urls:this.urls});return a.templates.hdaSummary(c)},_render_primaryActionButtons:function(e){var c=this,d=$("<div/>").attr("id","primary-actions-"+this.model.get("id"));_.each(e,function(f){d.append(f.call(c))});return d},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var c=a.templates.downloadLinks(_.extend(this.model.toJSON(),{urls:this.urls}));return $(c.trim())},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:_l("View details"),href:this.urls.show_params,target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_displayAppArea:function(){return $("<div/>").addClass("display-apps")},_render_displayApps:function(e){e=e||this.$el;var f=e.find("div.display-apps"),c=this.model.get("display_types"),d=this.model.get("display_apps");if((!this.model.hasData())||(!e||!e.length)||(!f.length)){return}f.html(null);if(!_.isEmpty(c)){f.append(a.templates.displayApps({displayApps:c}))}if(!_.isEmpty(d)){f.append(a.templates.displayApps({displayApps:d}))}},_render_peek:function(){var c=this.model.get("peek");if(!c){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(c))},_render_body:function(){var c=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: none");if(this.expanded){this._render_body_html(c);c.show()}return c},_render_body_html:function(e){e.empty();var c=this.model.get("state");var f="_render_body_"+c,d=this[f];if(_.isFunction(d)){this[f](e)}else{e.append($('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'))}e.append('<div style="clear: both"></div>');this._setUpBehaviors(e)},_render_body_new:function(d){var c=_l("This is a new dataset and not all of its data are available yet");d.append($("<div>"+_l(c)+"</div>"))},_render_body_noPermission:function(c){c.append($("<div>"+_l("You do not have permission to view this dataset")+"</div>"))},_render_body_upload:function(c){c.append($("<div>"+_l("Dataset is uploading")+"</div>"))},_render_body_queued:function(c){c.append($("<div>"+_l("Job is waiting to run")+"</div>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_paused:function(c){c.append($("<div>"+_l('Job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_running:function(c){c.append("<div>"+_l("Job is currently running")+"</div>");c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_error:function(c){if(!this.model.get("purged")){c.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}c.append((_l("An error occurred with this dataset")+": <i>"+$.trim(this.model.get("misc_info"))+"</i>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers.concat([this._render_downloadButton])))},_render_body_discarded:function(c){c.append("<div>"+_l("The job creating this dataset was cancelled before completion")+".</div>");c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_setting_metadata:function(c){c.append($("<div>"+_l("Metadata is being auto-detected")+".</div>"))},_render_body_empty:function(c){c.append($("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>"));c.append(this._render_primaryActionButtons(this.defaultPrimaryActionButtonRenderers))},_render_body_failed_metadata:function(c){c.append($(a.templates.failedMetadata(_.extend(this.model.toJSON(),{urls:this.urls}))));this._render_body_ok(c)},_render_body_ok:function(c){c.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){c.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));return}c.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton]));c.append('<div class="clear"/>');c.append(this._render_displayAppArea());this._render_displayApps(c);c.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility"},toggleBodyVisibility:function(d,c){c=(c===undefined)?(!this.body.is(":visible")):(c);if(c){this.expandBody()}else{this.collapseBody()}},expandBody:function(){var c=this;function d(){c._render_body_html(c.body);c.body.slideDown(c.fxSpeed,function(){c.expanded=true;c.trigger("body-expanded",c.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch().done(function(e){d()})}else{d()}},collapseBody:function(){var c=this;this.body.slideUp(c.fxSpeed,function(){c.expanded=false;c.trigger("body-collapsed",c.model.get("id"))})},remove:function(d){var c=this;this.$el.fadeOut(c.fxSpeed,function(){c.$el.remove();c.off();if(d){d()}})},toString:function(){var c=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+c+")"}});a.templates={warningMsg:Handlebars.templates["template-warningmessagesmall"],messages:Handlebars.templates["template-hda-warning-messages"],titleLink:Handlebars.templates["template-hda-titleLink"],hdaSummary:Handlebars.templates["template-hda-hdaSummary"],downloadLinks:Handlebars.templates["template-hda-downloadLinks"],failedMetadata:Handlebars.templates["template-hda-failedMetadata"],displayApps:Handlebars.templates["template-hda-displayApps"]};return{HDABaseView:a}}); \ No newline at end of file diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/packed/mvc/dataset/hda-edit.js --- a/static/scripts/packed/mvc/dataset/hda-edit.js +++ b/static/scripts/packed/mvc/dataset/hda-edit.js @@ -1,1 +1,1 @@ -define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_setUpBehaviors:function(g){a.HDABaseView.prototype._setUpBehaviors.call(this,g)},_render_warnings:function(){return $(jQuery.trim(a.HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var g=$('<div class="historyItemButtons"></div>');g.append(this._render_displayButton());g.append(this._render_editButton());g.append(this._render_deleteButton());return g},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(g||i){h.enabled=false;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(h)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var g=this,j="historyItemDeleter-"+g.model.get("id"),h=g.urls["delete"],i={title:_l("Delete"),href:h,id:j,icon_class:"delete",on_click:function(){g.$el.find(".menu-button.delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){i={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(i)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var g=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(g,{dbkey_unknown_and_editable:true})}return a.HDABaseView.templates.hdaSummary(g)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var g=this.model.get("visualizations");if((!this.model.hasData())||(_.isEmpty(g))){this.visualizationsButton=null;return null}if(_.isObject(g[0])){return this._render_visualizationsFrameworkButton(g)}if(!this.urls.visualization){this.visualizationsButton=null;return null}var i=this.model.get("dbkey"),l=this.urls.visualization,j={},m={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(i){m.dbkey=i}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:this.urls.visualization,icon_class:"chart_curve"})});var h=this.visualizationsButton.render().$el;h.addClass("visualize-icon");function k(n){switch(n){case"trackster":return b(l,m,i);case"scatterplot":return e(l,m);default:return function(){Galaxy.frame_manager.frame_new({title:"Visualization",type:"url",content:l+"/"+n+"?"+$.param(m)})}}}if(g.length===1){h.attr("title",g[0]);h.click(k(g[0]))}else{_.each(g,function(o){var n=o.charAt(0).toUpperCase()+o.slice(1);j[_l(n)]=k(o)});make_popupmenu(h,j)}return h},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),icon_class:"chart_curve"})});var i=this.visualizationsButton.render().$el;i.addClass("visualize-icon");if(_.keys(g).length===1){i.attr("title",_.keys(g)[0]);i.attr("href",_.values(g)[0])}else{var j=[];_.each(g,function(k){j.push(k)});var h=new PopupMenu(i,j)}return i},_render_secondaryActionButtons:function(h){var i=$("<div/>"),g=this;i.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(h,function(j){i.append(j.call(g))});return i},_render_tagButton:function(){if(!this.hasUser||!this.urls.tags.get){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!this.hasUser||!this.urls.annotation.get){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.urls.tags.set){return null}return $(f.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},_render_annotationArea:function(){if(!this.urls.annotation.get){return null}return $(f.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},_render_body_error:function(g){a.HDABaseView.prototype._render_body_error.call(this,g);var h=g.find("#primary-actions-"+this.model.get("id"));h.prepend(this._render_errButton())},_render_body_ok:function(g){g.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){g.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}g.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));g.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));g.append('<div class="clear"/>');g.append(this._render_tagArea());g.append(this._render_annotationArea());g.append(this._render_displayAppArea());this._render_displayApps(g);g.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click .historyItemUndelete":function(g){this.model.undelete();return false},"click .historyItemUnhide":function(g){this.model.unhide();return false},"click .historyItemPurge":"confirmPurge","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},confirmPurge:function c(g){this.model.purge({url:this.urls.purge});return false},loadAndDisplayTags:function(i){this.log(this+".loadAndDisplayTags",i);var g=this,j=this.$el.find(".tag-area"),h=j.find(".tag-elt");if(j.is(":hidden")){if(!jQuery.trim(h.html())){$.ajax({url:this.urls.tags.get,error:function(m,k,l){g.log("Tagging failed",m,k,l);g.trigger("error",g,m,{},_l("Tagging failed"))},success:function(k){h.html(k);h.find("[title]").tooltip();j.slideDown(g.fxSpeed)}})}else{j.slideDown(g.fxSpeed)}}else{j.slideUp(g.fxSpeed)}return false},loadAndDisplayAnnotation:function(i){this.log(this+".loadAndDisplayAnnotation",i);var g=this,k=this.$el.find(".annotation-area"),j=k.find(".annotation-elt"),h=this.urls.annotation.set;if(k.is(":hidden")){if(!jQuery.trim(j.html())){$.ajax({url:this.urls.annotation.get,error:function(){g.log("Annotation failed",xhr,status,error);g.trigger("error",g,xhr,{},_l("Annotation failed"))},success:function(l){if(l===""){l="<em>"+_l("Describe or add notes to dataset")+"</em>"}j.html(l);k.find("[title]").tooltip();async_save_text(j.attr("id"),j.attr("id"),h,"new_annotation",18,true,4);k.slideDown(g.fxSpeed)}})}else{k.slideDown(g.fxSpeed)}}else{k.slideUp(g.fxSpeed)}return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});f.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function e(g,h){action=function(){Galaxy.frame_manager.frame_new({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(h),location:"center"});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i)})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:m})}}})}});return false}}return{HDAEditView:f,}}); \ No newline at end of file +define(["mvc/dataset/hda-model","mvc/dataset/hda-base"],function(d,a){var f=a.HDABaseView.extend(LoggableMixin).extend({initialize:function(g){a.HDABaseView.prototype.initialize.call(this,g);this.hasUser=g.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton]},_setUpBehaviors:function(g){a.HDABaseView.prototype._setUpBehaviors.call(this,g)},_render_warnings:function(){return $(jQuery.trim(a.HDABaseView.templates.messages(_.extend(this.model.toJSON(),{urls:this.urls}))))},_render_titleButtons:function(){var g=$('<div class="historyItemButtons"></div>');g.append(this._render_displayButton());g.append(this._render_editButton());g.append(this._render_deleteButton());return g},_render_editButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.editButton=null;return null}var i=this.model.get("purged"),g=this.model.get("deleted"),h={title:_l("Edit Attributes"),href:this.urls.edit,target:"galaxy_main",icon_class:"edit"};if(g||i){h.enabled=false;if(i){h.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(g){h.title=_l("Undelete dataset to edit attributes")}}}this.editButton=new IconButtonView({model:new IconButton(h)});return this.editButton.render().$el},_render_deleteButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){this.deleteButton=null;return null}var g=this,j="historyItemDeleter-"+g.model.get("id"),h=g.urls["delete"],i={title:_l("Delete"),href:h,id:j,icon_class:"delete",on_click:function(){g.$el.find(".menu-button.delete").trigger("mouseout");g.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){i={title:_l("Dataset is already deleted"),icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(i)});return this.deleteButton.render().$el},_render_hdaSummary:function(){var g=_.extend(this.model.toJSON(),{urls:this.urls});if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){_.extend(g,{dbkey_unknown_and_editable:true})}return a.HDABaseView.templates.hdaSummary(g)},_render_errButton:function(){if(this.model.get("state")!==d.HistoryDatasetAssociation.STATES.ERROR){this.errButton=null;return null}this.errButton=new IconButtonView({model:new IconButton({title:_l("View or report this error"),href:this.urls.report_error,target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_rerunButton:function(){this.rerunButton=new IconButtonView({model:new IconButton({title:_l("Run this job again"),href:this.urls.rerun,target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_visualizationsButton:function(){var g=this.model.get("visualizations");if((!this.model.hasData())||(_.isEmpty(g))){this.visualizationsButton=null;return null}if(_.isObject(g[0])){return this._render_visualizationsFrameworkButton(g)}if(!this.urls.visualization){this.visualizationsButton=null;return null}var i=this.model.get("dbkey"),l=this.urls.visualization,j={},m={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(i){m.dbkey=i}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),href:this.urls.visualization,icon_class:"chart_curve"})});var h=this.visualizationsButton.render().$el;h.addClass("visualize-icon");function k(n){switch(n){case"trackster":return b(l,m,i);case"scatterplot":return e(l,m);default:return function(){Galaxy.frame_manager.frame_new({title:"Visualization",type:"url",content:l+"/"+n+"?"+$.param(m)})}}}if(g.length===1){h.attr("title",g[0]);h.click(k(g[0]))}else{_.each(g,function(o){var n=o.charAt(0).toUpperCase()+o.slice(1);j[_l(n)]=k(o)});make_popupmenu(h,j)}return h},_render_visualizationsFrameworkButton:function(g){if(!(this.model.hasData())||!(g&&!_.isEmpty(g))){this.visualizationsButton=null;return null}this.visualizationsButton=new IconButtonView({model:new IconButton({title:_l("Visualize"),icon_class:"chart_curve"})});var i=this.visualizationsButton.render().$el;i.addClass("visualize-icon");if(_.keys(g).length===1){i.attr("title",_.keys(g)[0]);i.attr("href",_.values(g)[0])}else{var j=[];_.each(g,function(k){j.push(k)});var h=new PopupMenu(i,j)}return i},_render_secondaryActionButtons:function(h){var i=$("<div/>"),g=this;i.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(h,function(j){i.append(j.call(g))});return i},_render_tagButton:function(){if(!this.hasUser||!this.urls.tags.get){this.tagButton=null;return null}this.tagButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset tags"),target:"galaxy_main",href:this.urls.tags.get,icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!this.hasUser||!this.urls.annotation.get){this.annotateButton=null;return null}this.annotateButton=new IconButtonView({model:new IconButton({title:_l("Edit dataset annotation"),target:"galaxy_main",icon_class:"annotate"})});return this.annotateButton.render().$el},_render_body_error:function(g){a.HDABaseView.prototype._render_body_error.call(this,g);var h=g.find("#primary-actions-"+this.model.get("id"));h.prepend(this._render_errButton())},_render_body_ok:function(g){g.append(this._render_hdaSummary());if(this.model.isDeletedOrPurged()){g.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton]));return}g.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_showParamsButton,this._render_rerunButton,this._render_visualizationsButton]));g.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));g.append('<div class="clear"/>');g.append(this._render_tagArea());g.append(this._render_annotationArea());g.append(this._render_displayAppArea());this._render_displayApps(g);g.append(this._render_peek())},events:{"click .historyItemTitle":"toggleBodyVisibility","click .historyItemUndelete":function(g){this.model.undelete();return false},"click .historyItemUnhide":function(g){this.model.unhide();return false},"click .historyItemPurge":"confirmPurge","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},confirmPurge:function c(g){this.model.purge({url:this.urls.purge});return false},_render_tagArea:function(){if(!this.hasUser||!this.urls.tags.set){return null}return $(f.templates.tagArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},loadAndDisplayTags:function(i){this.log(this+".loadAndDisplayTags",i);var g=this,j=this.$el.find(".tag-area"),h=j.find(".tag-elt");if(j.is(":hidden")){if(!jQuery.trim(h.html())){$.ajax({url:this.urls.tags.get,error:function(m,k,l){g.log("Tagging failed",m,k,l);g.trigger("error",g,m,{},_l("Tagging failed"))},success:function(k){h.html(k);h.find("[title]").tooltip();j.slideDown(g.fxSpeed)}})}else{j.slideDown(g.fxSpeed)}}else{j.slideUp(g.fxSpeed)}return false},_render_annotationArea:function(){if(!this.hasUser||!this.urls.annotation.get){return null}return $(f.templates.annotationArea(_.extend(this.model.toJSON(),{urls:this.urls})).trim())},loadAndDisplayAnnotation:function(i){this.log(this+".loadAndDisplayAnnotation",i);var g=this,k=this.$el.find(".annotation-area"),j=k.find(".annotation-elt"),h=this.urls.annotation.set;if(k.is(":hidden")){if(!jQuery.trim(j.html())){$.ajax({url:this.urls.annotation.get,error:function(){g.log("Annotation failed",xhr,status,error);g.trigger("error",g,xhr,{},_l("Annotation failed"))},success:function(l){if(l===""){l="<em>"+_l("Describe or add notes to dataset")+"</em>"}j.html(l);k.find("[title]").tooltip();async_save_text(j.attr("id"),j.attr("id"),h,"new_annotation",18,true,4);k.slideDown(g.fxSpeed)}})}else{k.slideDown(g.fxSpeed)}}else{k.slideUp(g.fxSpeed)}return false},toString:function(){var g=(this.model)?(this.model+""):("(no model)");return"HDAView("+g+")"}});f.templates={tagArea:Handlebars.templates["template-hda-tagArea"],annotationArea:Handlebars.templates["template-hda-annotationArea"]};function e(g,h){action=function(){Galaxy.frame_manager.frame_new({title:"Scatterplot",type:"url",content:g+"/scatterplot?"+$.param(h),location:"center"});$("div.popmenu-wrapper").remove();return false};return action}function b(g,i,h){return function(){var j={};if(h){j["f-dbkey"]=h}$.ajax({url:g+"/list_tracks?"+$.param(j),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(k){var l=window.parent;l.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){l.Galaxy.modal.hide()},"View in saved visualization":function(){l.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:k,buttons:{Cancel:function(){l.Galaxy.modal.hide()},"Add to visualization":function(){$(l.document).find("input[name=id]:checked").each(function(){l.Galaxy.modal.hide();var m=$(this).val();i.id=m;l.Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:g+"/trackster?"+$.param(i)})})}}})},"View in new visualization":function(){l.Galaxy.modal.hide();var m=g+"/trackster?"+$.param(i);l.Galaxy.frame_manager.frame_new({title:"Trackster",type:"url",content:m})}}})}});return false}}return{HDAEditView:f}}); \ No newline at end of file diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/packed/mvc/dataset/hda-model.js --- a/static/scripts/packed/mvc/dataset/hda-model.js +++ b/static/scripts/packed/mvc/dataset/hda-model.js @@ -1,1 +1,1 @@ -define([],function(){var d=Backbone.Model.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"(unnamed dataset)",state:"new",deleted:false,visible:true,accessible:true,purged:false,data_type:null,file_size:0,file_ext:"",meta_files:[],misc_blurb:"",misc_info:""},urlRoot:"api/histories/",url:function(){return this.urlRoot+this.get("history_id")+"/contents/"+this.get("id")},urls:function(){var j=this.get("id");if(!j){return{}}var h={"delete":"/datasets/"+j+"/delete_async",purge:"/datasets/"+j+"/purge_async",unhide:"/datasets/"+j+"/unhide",undelete:"/datasets/"+j+"/undelete",display:"/datasets/"+j+"/display/?preview=True",download:"/datasets/"+j+"/display?to_ext="+this.get("file_ext"),edit:"/datasets/"+j+"/edit",report_error:"/dataset/errors?id="+j,rerun:"/tool_runner/rerun?id="+j,show_params:"/datasets/"+j+"/show_params",visualization:"/visualization",annotation:{get:"/dataset/get_annotation_async?id="+j,set:"/dataset/annotate_async?id="+j},tags:{get:"/tag/get_tagging_elt_async?item_id="+j+"&item_class=HistoryDatasetAssociation",set:"/tag/retag?item_id="+j+"&item_class=HistoryDatasetAssociation"}};var i=this.get("meta_files");if(i){h.meta_download=_.map(i,function(k){return{url:"/dataset/get_metadata_file?hda_id="+j+"&metadata_name="+k.file_type,file_type:k.file_type}})}return h},initialize:function(h){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",d.STATES.NOT_VIEWABLE)}this._setUpListeners()},_setUpListeners:function(){this.on("change:state",function(i,h){this.log(this+" has changed state:",i,h);if(this.inReadyState()){this.trigger("state:ready",i,h,this.previous("state"))}})},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isVisible:function(i,j){var h=true;if((!i)&&(this.get("deleted")||this.get("purged"))){h=false}if((!j)&&(!this.get("visible"))){h=false}return h},hidden:function(){return !this.get("visible")},inReadyState:function(){var h=_.contains(d.READY_STATES,this.get("state"));return(this.isDeletedOrPurged()||h)},hasDetails:function(){return _.has(this.attributes,"genome_build")},hasData:function(){return(this.get("file_size")>0)},"delete":function c(h){return this.save({deleted:true},h)},undelete:function a(h){return this.save({deleted:false},h)},hide:function b(h){return this.save({visible:false},h)},unhide:function g(h){return this.save({visible:true},h)},purge:function f(h){var i=this,j=jQuery.ajax(h);j.done(function(m,k,l){i.set("purged",true)});j.fail(function(o,k,n){var l=_l("Unable to purge this dataset");var m=("Removal of datasets by users is not allowed in this Galaxy instance");if(o.responseJSON&&o.responseJSON.error){l=o.responseJSON.error}else{if(o.responseText.indexOf(m)!==-1){l=m}}o.responseText=l;i.trigger("error",i,o,h,_l(l),{error:l})})},searchKeys:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],search:function(h){var i=this;h=h.toLowerCase();return _.filter(this.searchKeys,function(k){var j=i.get(k);return(_.isString(j)&&j.toLowerCase().indexOf(h)!==-1)})},matches:function(h){return !!this.search(h).length},toString:function(){var h=this.get("id")||"";if(this.get("name")){h=this.get("hid")+' :"'+this.get("name")+'",'+h}return"HDA("+h+")"}});d.STATES={UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",PAUSED:"paused",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};d.READY_STATES=[d.STATES.NEW,d.STATES.OK,d.STATES.EMPTY,d.STATES.PAUSED,d.STATES.FAILED_METADATA,d.STATES.NOT_VIEWABLE,d.STATES.DISCARDED,d.STATES.ERROR];d.NOT_READY_STATES=[d.STATES.UPLOAD,d.STATES.QUEUED,d.STATES.RUNNING,d.STATES.SETTING_METADATA];var e=Backbone.Collection.extend(LoggableMixin).extend({model:d,urlRoot:"/api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},initialize:function(i,h){h=h||{};this.historyId=h.historyId;this._setUpListeners()},_setUpListeners:function(){},ids:function(){return this.map(function(h){return h.id})},notReady:function(){return this.filter(function(h){return !h.inReadyState()})},running:function(){var h=[];this.each(function(i){if(!i.inReadyState()){h.push(i.get("id"))}});return h},getByHid:function(h){return _.first(this.filter(function(i){return i.get("hid")===h}))},getVisible:function(h,i){return this.filter(function(j){return j.isVisible(h,i)})},fetchAllDetails:function(){return this.fetch({data:{details:"all"}})},matches:function(h){return this.filter(function(i){return i.matches(h)})},set:function(j,h){var i=this;j=_.map(j,function(l){var m=i.get(l.id);if(!m){return l}var k=m.toJSON();_.extend(k,l);return k});Backbone.Collection.prototype.set.call(this,j,h)},toString:function(){return("HDACollection()")}});return{HistoryDatasetAssociation:d,HDACollection:e}}); \ No newline at end of file +define([],function(){var d=Backbone.Model.extend(LoggableMixin).extend({defaults:{history_id:null,model_class:"HistoryDatasetAssociation",hid:0,id:null,name:"(unnamed dataset)",state:"new",deleted:false,visible:true,accessible:true,purged:false,data_type:null,file_size:0,file_ext:"",meta_files:[],misc_blurb:"",misc_info:""},urlRoot:"api/histories/",url:function(){return this.urlRoot+this.get("history_id")+"/contents/"+this.get("id")},urls:function(){var j=this.get("id");if(!j){return{}}var h={purge:galaxy_config.root+"datasets/"+j+"/purge_async",display:galaxy_config.root+"datasets/"+j+"/display/?preview=True",download:galaxy_config.root+"datasets/"+j+"/display?to_ext="+this.get("file_ext"),edit:galaxy_config.root+"datasets/"+j+"/edit",report_error:galaxy_config.root+"dataset/errors?id="+j,rerun:galaxy_config.root+"tool_runner/rerun?id="+j,show_params:galaxy_config.root+"datasets/"+j+"/show_params",visualization:galaxy_config.root+"visualization",annotation:{get:galaxy_config.root+"dataset/get_annotation_async?id="+j,set:galaxy_config.root+"dataset/annotate_async?id="+j},tags:{get:galaxy_config.root+"tag/get_tagging_elt_async?item_id="+j+"&item_class=HistoryDatasetAssociation",set:galaxy_config.root+"tag/retag?item_id="+j+"&item_class=HistoryDatasetAssociation"}};var i=this.get("meta_files");if(i){h.meta_download=_.map(i,function(k){return{url:galaxy_config.root+"dataset/get_metadata_file?hda_id="+j+"&metadata_name="+k.file_type,file_type:k.file_type}})}return h},initialize:function(h){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",d.STATES.NOT_VIEWABLE)}this._setUpListeners()},_setUpListeners:function(){this.on("change:state",function(i,h){this.log(this+" has changed state:",i,h);if(this.inReadyState()){this.trigger("state:ready",i,h,this.previous("state"))}})},isDeletedOrPurged:function(){return(this.get("deleted")||this.get("purged"))},isVisible:function(i,j){var h=true;if((!i)&&(this.get("deleted")||this.get("purged"))){h=false}if((!j)&&(!this.get("visible"))){h=false}return h},hidden:function(){return !this.get("visible")},inReadyState:function(){var h=_.contains(d.READY_STATES,this.get("state"));return(this.isDeletedOrPurged()||h)},hasDetails:function(){return _.has(this.attributes,"genome_build")},hasData:function(){return(this.get("file_size")>0)},"delete":function c(h){return this.save({deleted:true},h)},undelete:function a(h){return this.save({deleted:false},h)},hide:function b(h){return this.save({visible:false},h)},unhide:function g(h){return this.save({visible:true},h)},purge:function f(h){var i=this,j=jQuery.ajax(h);j.done(function(m,k,l){i.set("purged",true)});j.fail(function(o,k,n){var l=_l("Unable to purge this dataset");var m=("Removal of datasets by users is not allowed in this Galaxy instance");if(o.responseJSON&&o.responseJSON.error){l=o.responseJSON.error}else{if(o.responseText.indexOf(m)!==-1){l=m}}o.responseText=l;i.trigger("error",i,o,h,_l(l),{error:l})})},searchKeys:["name","file_ext","genome_build","misc_blurb","misc_info","annotation","tags"],search:function(h){var i=this;h=h.toLowerCase();return _.filter(this.searchKeys,function(k){var j=i.get(k);return(_.isString(j)&&j.toLowerCase().indexOf(h)!==-1)})},matches:function(h){return !!this.search(h).length},toString:function(){var h=this.get("id")||"";if(this.get("name")){h=this.get("hid")+' :"'+this.get("name")+'",'+h}return"HDA("+h+")"}});d.STATES={UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",SETTING_METADATA:"setting_metadata",NEW:"new",EMPTY:"empty",OK:"ok",PAUSED:"paused",FAILED_METADATA:"failed_metadata",NOT_VIEWABLE:"noPermission",DISCARDED:"discarded",ERROR:"error"};d.READY_STATES=[d.STATES.NEW,d.STATES.OK,d.STATES.EMPTY,d.STATES.PAUSED,d.STATES.FAILED_METADATA,d.STATES.NOT_VIEWABLE,d.STATES.DISCARDED,d.STATES.ERROR];d.NOT_READY_STATES=[d.STATES.UPLOAD,d.STATES.QUEUED,d.STATES.RUNNING,d.STATES.SETTING_METADATA];var e=Backbone.Collection.extend(LoggableMixin).extend({model:d,urlRoot:galaxy_config.root+"api/histories",url:function(){return this.urlRoot+"/"+this.historyId+"/contents"},initialize:function(i,h){h=h||{};this.historyId=h.historyId;this._setUpListeners()},_setUpListeners:function(){},ids:function(){return this.map(function(h){return h.id})},notReady:function(){return this.filter(function(h){return !h.inReadyState()})},running:function(){var h=[];this.each(function(i){if(!i.inReadyState()){h.push(i.get("id"))}});return h},getByHid:function(h){return _.first(this.filter(function(i){return i.get("hid")===h}))},getVisible:function(h,i){return this.filter(function(j){return j.isVisible(h,i)})},fetchAllDetails:function(){return this.fetch({data:{details:"all"}})},matches:function(h){return this.filter(function(i){return i.matches(h)})},set:function(j,h){var i=this;j=_.map(j,function(l){var m=i.get(l.id);if(!m){return l}var k=m.toJSON();_.extend(k,l);return k});Backbone.Collection.prototype.set.call(this,j,h)},toString:function(){return("HDACollection()")}});return{HistoryDatasetAssociation:d,HDACollection:e}}); \ No newline at end of file diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/packed/mvc/history/history-model.js --- a/static/scripts/packed/mvc/history/history-model.js +++ b/static/scripts/packed/mvc/history/history-model.js @@ -1,1 +1,1 @@ -define(["mvc/dataset/hda-model"],function(a){var c=Backbone.Model.extend(LoggableMixin).extend({defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:"api/histories",renameUrl:function(){var e=this.get("id");if(!e){return undefined}return"/history/rename_async?id="+this.get("id")},annotateUrl:function(){var e=this.get("id");if(!e){return undefined}return"/history/annotate_async?id="+this.get("id")},tagUrl:function(){var e=this.get("id");if(!e){return undefined}return"/tag/get_tagging_elt_async?item_id="+this.get("id")+"&item_class=History"},initialize:function(f,g,e){e=e||{};this.logger=e.logger||null;this.log(this+".initialize:",f,g,e);this.hdas=new a.HDACollection(g||[],{historyId:this.get("id")});if(g&&_.isArray(g)){this.hdas.reset(g)}this._setUpListeners();this.checkForUpdates()},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});if(this.hdas){this.listenTo(this.hdas,"error",function(){this.trigger.apply(this,["error:hdas"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(f,e){if(this.hdas){this.hdas.historyId=e}},this)},errorHandler:function(f,i,e,h,g){this.clearUpdateTimeout()},hasUser:function(){var e=this.get("user");return !!(e&&e.id)},checkForUpdates:function(e){if(this.hdas.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(e)){e.call(this)}}return this},setUpdateTimeout:function(e){e=e||c.UPDATE_DELAY;var f=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){f.refresh()},e);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(f,e){f=f||[];e=e||{};var g=this;e.data=e.data||{};if(f.length){e.data.details=f.join(",")}var h=this.hdas.fetch(e);h.done(function(i){g.checkForUpdates(function(){this.fetch()})});return h},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}});c.UPDATE_DELAY=4000;c.getHistoryData=function d(f,p){p=p||{};var j=p.hdaDetailIds||[];var l=jQuery.Deferred(),k=null;function g(q){return jQuery.ajax("/api/histories/"+f)}function e(q){if(!q||!q.state_ids){return 0}return _.reduce(q.state_ids,function(r,t,s){return r+t.length},0)}function o(r){if(!e(r)){return[]}if(_.isFunction(j)){j=j(r)}var q=(j.length)?({details:j.join(",")}):({});return jQuery.ajax("/api/histories/"+r.id+"/contents",{data:q})}var n=p.historyFn||g,m=p.hdaFn||o;var i=n(f);i.done(function(q){k=q;l.notify({status:"history data retrieved",historyJSON:k})});i.fail(function(s,q,r){l.reject(s,"loading the history")});var h=i.then(m);h.then(function(q){l.notify({status:"dataset data retrieved",historyJSON:k,hdaJSON:q});l.resolve(k,q)});h.fail(function(s,q,r){l.reject(s,"loading the datasets",{history:k})});return l};var b=Backbone.Collection.extend(LoggableMixin).extend({model:c,urlRoot:"api/histories"});return{History:c,HistoryCollection:b}}); \ No newline at end of file +define(["mvc/dataset/hda-model"],function(a){var c=Backbone.Model.extend(LoggableMixin).extend({defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",renameUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"history/rename_async?id="+this.get("id")},annotateUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"history/annotate_async?id="+this.get("id")},tagUrl:function(){var e=this.get("id");if(!e){return undefined}return galaxy_config.root+"tag/get_tagging_elt_async?item_id="+this.get("id")+"&item_class=History"},initialize:function(f,g,e){e=e||{};this.logger=e.logger||null;this.log(this+".initialize:",f,g,e);this.hdas=new a.HDACollection(g||[],{historyId:this.get("id")});if(g&&_.isArray(g)){this.hdas.reset(g)}this._setUpListeners();this.updateTimeoutId=null;this.checkForUpdates()},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});if(this.hdas){this.listenTo(this.hdas,"error",function(){this.trigger.apply(this,["error:hdas"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(f,e){if(this.hdas){this.hdas.historyId=e}},this)},errorHandler:function(f,i,e,h,g){this.clearUpdateTimeout()},hasUser:function(){var e=this.get("user");return !!(e&&e.id)},checkForUpdates:function(e){if(this.hdas.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(e)){e.call(this)}}return this},setUpdateTimeout:function(e){e=e||c.UPDATE_DELAY;var f=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){f.refresh()},e);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(f,e){f=f||[];e=e||{};var g=this;e.data=e.data||{};if(f.length){e.data.details=f.join(",")}var h=this.hdas.fetch(e);h.done(function(i){g.checkForUpdates(function(){this.fetch()})});return h},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}});c.UPDATE_DELAY=4000;c.getHistoryData=function d(f,p){p=p||{};var j=p.hdaDetailIds||[];var l=jQuery.Deferred(),k=null;function g(q){return jQuery.ajax(galaxy_config.root+"api/histories/"+f)}function e(q){if(!q||!q.state_ids){return 0}return _.reduce(q.state_ids,function(r,t,s){return r+t.length},0)}function o(r){if(!e(r)){return[]}if(_.isFunction(j)){j=j(r)}var q=(j.length)?({details:j.join(",")}):({});return jQuery.ajax(galaxy_config.root+"api/histories/"+r.id+"/contents",{data:q})}var n=p.historyFn||g,m=p.hdaFn||o;var i=n(f);i.done(function(q){k=q;l.notify({status:"history data retrieved",historyJSON:k})});i.fail(function(s,q,r){l.reject(s,"loading the history")});var h=i.then(m);h.then(function(q){l.notify({status:"dataset data retrieved",historyJSON:k,hdaJSON:q});l.resolve(k,q)});h.fail(function(s,q,r){l.reject(s,"loading the datasets",{history:k})});return l};var b=Backbone.Collection.extend(LoggableMixin).extend({model:c,urlRoot:galaxy_config.root+"api/histories"});return{History:c,HistoryCollection:b}}); \ No newline at end of file diff -r 7f70f02747d374ebf1804a1ae380cb27968043b0 -r e66076ed4678c1ad15db09c1d220a624e2047a79 static/scripts/packed/mvc/history/history-panel.js --- a/static/scripts/packed/mvc/history/history-panel.js +++ b/static/scripts/packed/mvc/history/history-panel.js @@ -1,1 +1,1 @@ -define(["mvc/history/history-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(d,b,a){var c=Backbone.View.extend(LoggableMixin).extend({HDAView:a.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:300,events:{"click #history-tag":"loadAndDisplayTags","click #message-container":"clearMessages"},initialize:function(e){e=e||{};if(e.logger){this.logger=e.logger}this.log(this+".initialize:",e);this._setUpListeners();this.hdaViews={};this.urls={};this.indicator=new LoadingIndicator(this.$el);if(this.model){this._setUpWebStorage(e.initiallyExpanded,e.show_deleted,e.show_hidden);this._setUpModelEventHandlers()}if(e.onready){e.onready.call(this)}},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});this.on("loading-history",function(){this.showLoadingIndicator()});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(e){this.log(this+"",arguments)},this)}},errorHandler:function(g,j,f,i,h){var e=this._parseErrorMessage(g,j,f,i,h);if(j&&j.status===0&&j.readyState===0){}else{if(j&&j.status===502){}else{if(!this.$el.find("#message-container").is(":visible")){this.once("rendered",function(){this.displayMessage("error",e.message,e.details)})}else{this.displayMessage("error",e.message,e.details)}}}},_parseErrorMessage:function(h,l,g,k,j){var f=Galaxy.currUser,e={message:this._bePolite(k),details:{user:(f instanceof User)?(f.toJSON()):(f+""),source:(h instanceof Backbone.Model)?(h.toJSON()):(h+""),xhr:l,options:(l)?(_.omit(g,"xhr")):(g)}};_.extend(e.details,j||{});if(l&&_.isFunction(l.getAllResponseHeaders)){var i=l.getAllResponseHeaders();i=_.compact(i.split("\n"));i=_.map(i,function(m){return m.split(": ")});e.details.xhr.responseHeaders=_.object(i)}return e},_bePolite:function(e){e=e||_l("An error occurred while getting updates from the server");return e+". "+_l("Please contact a Galaxy administrator if the problem persists.")},_loadHistoryFromXHR:function(g,f){var e=this;g.then(function(h,i){e.setModel(h,i,f)});g.fail(function(i,h){e.render()});return g},setModel:function(g,e,f){f=f||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){g.user=Galaxy.currUser.toJSON()}this.model=new d.History(g,e,f);this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},loadHistory:function(h,g,f,k,i){this.trigger("loading-history",this);g=g||{};var e=this;var j=d.History.getHistoryData(h,{historyFn:f,hdaFn:k,hdaDetailIds:g.initiallyExpanded||i});return this._loadHistoryFromXHR(j,g).fail(function(n,l,m){e.trigger("error",e,n,g,_l("An error was encountered while "+l),{historyId:h,history:m||{}})}).always(function(){e.trigger("loading-done",e)})},loadHistoryWithHDADetails:function(h,g,f,j){var e=this,i=function(k){return e.getExpandedHdaIds(k.id)};return this.loadHistory(h,g,f,j,i)},switchToHistory:function(h,g){var e=this,f=function(){return jQuery.post("/api/histories/"+h+"/set_as_current")};return this.loadHistoryWithHDADetails(h,g,f).then(function(j,i){e.trigger("switched-history",e)})},loadCurrentHistory:function(f){var e=this;return this.loadHistoryWithHDADetails("current",f).then(function(h,g){e.trigger("current-history",e)})},createNewHistory:function(g){var e=this,f=function(){return jQuery.post("/api/histories",{current:true})};return this.loadHistory(undefined,g,f).then(function(i,h){e.trigger("new-history",e)})},refreshHdas:function(f,e){if(this.model){return this.model.refresh(f,e)}return $.when()},_getStorageKey:function(e){if(!e){throw new Error("_getStorageKey needs valid id: "+e)}return("history:"+e)},_setUpWebStorage:function(f,e,g){this.storage=new PersistentStorage(this._getStorageKey(this.model.get("id")),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(f){this.storage.set("exandedHdas",f)}if((e===true)||(e===false)){this.storage.set("show_deleted",e)}if((g===true)||(g===false)){this.storage.set("show_hidden",g)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var e in sessionStorage){if(e.indexOf("HistoryView.")===0){sessionStorage.removeItem(e)}}},getStoredOptions:function(f){if(!f||f==="current"){return(this.storage)?(this.storage.get()):({})}var e=sessionStorage.getItem(this._getStorageKey(f));return(e===null)?({}):(JSON.parse(e))},getExpandedHdaIds:function(e){var f=this.getStoredOptions(e).expandedHdas;return((_.isEmpty(f))?([]):(_.keys(f)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(f,h,e,g){this.errorHandler(f,h,e,g)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(e){this.model.fetch()},this);this.model.hdas.on("state:ready",function(f,g,e){if((!f.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(f.get("id"))}},this)},addHdaView:function(h){this.log("add."+this,h);var f=this;if(!h.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function g(j){var i=f.$el.find("#emptyHistoryMessage");if(i.is(":visible")){i.fadeOut(f.fxSpeed,j)}else{j()}},function e(j){f.scrollToTop();var i=f.$el.find("#"+f.model.get("id")+"-datasets");f.createHdaView(h).$el.hide().prependTo(i).slideDown(f.fxSpeed)}])},createHdaView:function(g){var f=g.get("id"),e=this.storage.get("expandedHdas").get(f),h=new this.HDAView({model:g,expanded:e,hasUser:this.model.hasUser(),logger:this.logger});this._setUpHdaListeners(h);this.hdaViews[f]=h;return h.render()},handleHdaDeletionChange:function(e){if(e.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(e.get("id"))}},handleHdaVisibleChange:function(e){if(e.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(e.get("id"))}},removeHdaView:function(g){var e=this,f=this.hdaViews[g];if(!f){return}f.$el.fadeOut(e.fxSpeed,function(){f.remove();delete e.hdaViews[g];if(_.isEmpty(e.hdaViews)){e.$el.find("#emptyHistoryMessage").fadeIn(e.fxSpeed)}})},render:function(g){var e=this,f;if(this.model){f=this.renderModel()}else{f=this.renderWithoutModel()}$(e).queue("fx",[function(h){if(e.$el.is(":visible")){e.$el.fadeOut(e.fxSpeed,h)}else{h()}},function(h){e.$el.empty();if(f){e.$el.append(f.children())}e.$el.fadeIn(e.fxSpeed,h)},function(h){e._setUpBehaviours();if(g){g.call(this)}}]);return this},renderModel:function(){var e=$("<div/>");e.append(c.templates.historyPanel(this.model.toJSON()));e.find("[title]").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(e.find("#"+this.model.get("id")+"-datasets"))){e.find("#emptyHistoryMessage").show()}return e},renderWithoutModel:function(){var e=$("<div/>"),f=$("<div/>").attr("id","message-container").css({"margin-left":"4px","margin-right":"4px"});return e.append(f)},renderItems:function(f){this.hdaViews={};var e=this,g=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(g,function(j){var i=j.get("id"),h=e.storage.get("expandedHdas").get(i);e.hdaViews[i]=new e.HDAView({model:j,expanded:h,hasUser:e.model.hasUser(),logger:e.logger});e._setUpHdaListeners(e.hdaViews[i]);f.prepend(e.hdaViews[i].render().$el)});return g.length},_setUpHdaListeners:function(f){var e=this;f.on("body-expanded",function(g){e.storage.get("expandedHdas").set(g,true)});f.on("body-collapsed",function(g){e.storage.get("expandedHdas").deleteKey(g)});f.on("error",function(h,j,g,i){e.errorHandler(h,j,g,i)})},_setUpBehaviours:function(){if(!this.model||!(this.model.get("user")&&this.model.get("user").email)){return}var e=this,f=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(f.is(":hidden")){f.slideDown(e.fxSpeed)}else{f.slideUp(e.fxSpeed)}return false});async_save_text("history-name-container","history-name",this.model.renameUrl(),"new_name",18);async_save_text("history-annotation-container","history-annotation",this.model.annotateUrl(),"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(e){e.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},loadAndDisplayTags:function(g){this.log(this+".loadAndDisplayTags",g);var e=this,h=this.$el.find("#history-tag-area"),f=h.find(".tag-elt");this.log("\t tagArea",h," tagElt",f);if(h.is(":hidden")){if(!jQuery.trim(f.html())){$.ajax({url:e.model.tagUrl(),error:function(k,j,i){e.log("Error loading tag area html",k,j,i);e.trigger("error",e,k,null,_l("Error loading tags"))},success:function(i){f.html(i);f.find("[title]").tooltip();h.slideDown(e.fxSpeed)}})}else{h.slideDown(e.fxSpeed)}}else{h.slideUp(e.fxSpeed)}return false},showLoadingIndicator:function(f,e,g){e=(e!==undefined)?(e):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,g)}else{this.$el.fadeOut(e);this.indicator.show(e,g)}},hideLoadingIndicator:function(e,f){e=(e!==undefined)?(e):(this.fxSpeed);if(this.indicator){this.indicator.hide(e,f)}},displayMessage:function(j,k,i){var g=this;this.scrollToTop();var h=this.$el.find("#message-container"),e=$("<div/>").addClass(j+"message").html(k);if(!_.isEmpty(i)){var f=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(g.messageToModalOptions(j,k,i));return false});e.append(" ",f)}return h.html(e)},messageToModalOptions:function(i,k,h){var e=this,j=$("<div/>"),g={title:"Details"};function f(l){l=_.omit(l,_.functions(l));return["<table>",_.map(l,function(n,m){n=(_.isObject(n))?(f(n)):(n);return'<tr><td style="vertical-align: top; color: grey">'+m+'</td><td style="padding-left: 8px">'+n+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(h)){g.body=j.append(f(h))}else{g.body=j.html(h)}g.buttons={Ok:function(){Galaxy.modal.hide();e.clearMessages()}};return g},clearMessages:function(){var e=this.$el.find("#message-container");e.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(e){this.$el.parent().scrollTop(e)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(f,g){if(!g){this.$el.parent().parent().scrollTop(f);return this}var e=window,h=this.$el.parent().parent(),j=$(e).innerHeight(),i=(j/2)-(g/2);$(h).scrollTop(f-i);return this},scrollToId:function(f){if((!f)||(!this.hdaViews[f])){return this}var e=this.hdaViews[f].$el;this.scrollIntoView(e.offset().top,e.outerHeight());return this},scrollToHid:function(e){var f=this.model.hdas.getByHid(e);if(!f){return this}return this.scrollToId(f.id)},connectToQuotaMeter:function(e){if(!e){return this}this.listenTo(e,"quota:over",this.showQuotaMessage);this.listenTo(e,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(e&&e.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var e=this.$el.find("#quota-message-container");if(e.is(":hidden")){e.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var e=this.$el.find("#quota-message-container");if(!e.is(":hidden")){e.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(e){if(!e){return this}this.on("new-storage",function(g,f){if(e&&g){e.findItemByHtml(_l("Include Deleted Datasets")).checked=g.get("show_deleted");e.findItemByHtml(_l("Include Hidden Datasets")).checked=g.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});c.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{HistoryPanel:c}}); \ No newline at end of file +define(["mvc/history/history-model","mvc/dataset/hda-base","mvc/dataset/hda-edit"],function(d,b,a){var c=Backbone.View.extend(LoggableMixin).extend({HDAView:a.HDAEditView,tagName:"div",className:"history-panel",fxSpeed:300,events:{"click #history-tag":"loadAndDisplayTags","click #message-container":"clearMessages"},initialize:function(e){e=e||{};if(e.logger){this.logger=e.logger}this.log(this+".initialize:",e);this._setUpListeners();this.hdaViews={};this.urls={};this.indicator=new LoadingIndicator(this.$el);if(this.model){this._setUpWebStorage(e.initiallyExpanded,e.show_deleted,e.show_hidden);this._setUpModelEventHandlers()}if(e.onready){e.onready.call(this)}},_setUpListeners:function(){this.on("error",function(f,i,e,h,g){this.errorHandler(f,i,e,h,g)});this.on("loading-history",function(){this.showLoadingIndicator()});this.on("loading-done",function(){this.hideLoadingIndicator()});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});this.on("switched-history current-history new-history",function(){if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});if(this.logger){this.on("all",function(e){this.log(this+"",arguments)},this)}},errorHandler:function(g,j,f,i,h){var e=this._parseErrorMessage(g,j,f,i,h);if(j&&j.status===0&&j.readyState===0){}else{if(j&&j.status===502){}else{if(!this.$el.find("#message-container").is(":visible")){this.once("rendered",function(){this.displayMessage("error",e.message,e.details)})}else{this.displayMessage("error",e.message,e.details)}}}},_parseErrorMessage:function(h,l,g,k,j){var f=Galaxy.currUser,e={message:this._bePolite(k),details:{user:(f instanceof User)?(f.toJSON()):(f+""),source:(h instanceof Backbone.Model)?(h.toJSON()):(h+""),xhr:l,options:(l)?(_.omit(g,"xhr")):(g)}};_.extend(e.details,j||{});if(l&&_.isFunction(l.getAllResponseHeaders)){var i=l.getAllResponseHeaders();i=_.compact(i.split("\n"));i=_.map(i,function(m){return m.split(": ")});e.details.xhr.responseHeaders=_.object(i)}return e},_bePolite:function(e){e=e||_l("An error occurred while getting updates from the server");return e+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadCurrentHistory:function(f){var e=this;return this.loadHistoryWithHDADetails("current",f).then(function(h,g){e.trigger("current-history",e)})},switchToHistory:function(h,g){var e=this,f=function(){return jQuery.post(galaxy_config.root+"api/histories/"+h+"/set_as_current")};return this.loadHistoryWithHDADetails(h,g,f).then(function(j,i){e.trigger("switched-history",e)})},createNewHistory:function(g){var e=this,f=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,g,f).then(function(i,h){e.trigger("new-history",e)})},loadHistoryWithHDADetails:function(h,g,f,j){var e=this,i=function(k){return e.getExpandedHdaIds(k.id)};return this.loadHistory(h,g,f,j,i)},loadHistory:function(h,g,f,k,i){this.trigger("loading-history",this);g=g||{};var e=this;var j=d.History.getHistoryData(h,{historyFn:f,hdaFn:k,hdaDetailIds:g.initiallyExpanded||i});return this._loadHistoryFromXHR(j,g).fail(function(n,l,m){e.trigger("error",e,n,g,_l("An error was encountered while "+l),{historyId:h,history:m||{}})}).always(function(){e.trigger("loading-done",e)})},_loadHistoryFromXHR:function(g,f){var e=this;g.then(function(h,i){e.setModel(h,i,f)});g.fail(function(i,h){e.render()});return g},setModel:function(g,e,f){f=f||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){g.user=Galaxy.currUser.toJSON()}this.model=new d.History(g,e,f);this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this);this.render();return this},refreshHdas:function(f,e){if(this.model){return this.model.refresh(f,e)}return $.when()},_setUpWebStorage:function(f,e,g){this.storage=new PersistentStorage(this._getStorageKey(this.model.get("id")),{expandedHdas:{},show_deleted:false,show_hidden:false});this.log(this+" (prev) storage:",JSON.stringify(this.storage.get(),null,2));if(f){this.storage.set("exandedHdas",f)}if((e===true)||(e===false)){this.storage.set("show_deleted",e)}if((g===true)||(g===false)){this.storage.set("show_hidden",g)}this.show_deleted=this.storage.get("show_deleted");this.show_hidden=this.storage.get("show_hidden");this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},_getStorageKey:function(e){if(!e){throw new Error("_getStorageKey needs valid id: "+e)}return("history:"+e)},clearWebStorage:function(){for(var e in sessionStorage){if(e.indexOf("HistoryView.")===0){sessionStorage.removeItem(e)}}},getStoredOptions:function(f){if(!f||f==="current"){return(this.storage)?(this.storage.get()):({})}var e=sessionStorage.getItem(this._getStorageKey(f));return(e===null)?({}):(JSON.parse(e))},getExpandedHdaIds:function(e){var f=this.getStoredOptions(e).expandedHdas;return((_.isEmpty(f))?([]):(_.keys(f)))},_setUpModelEventHandlers:function(){this.model.on("error error:hdas",function(f,h,e,g){this.errorHandler(f,h,e,g)},this);this.model.on("change:nice_size",this.updateHistoryDiskSize,this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("add",this.addHdaView,this);this.model.hdas.on("change:deleted",this.handleHdaDeletionChange,this);this.model.hdas.on("change:visible",this.handleHdaVisibleChange,this);this.model.hdas.on("change:purged",function(e){this.model.fetch()},this);this.model.hdas.on("state:ready",function(f,g,e){if((!f.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[f.id])}},this)},addHdaView:function(h){this.log("add."+this,h);var f=this;if(!h.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function g(j){var i=f.$el.find("#emptyHistoryMessage");if(i.is(":visible")){i.fadeOut(f.fxSpeed,j)}else{j()}},function e(j){f.scrollToTop();var i=f.$el.find("#"+f.model.get("id")+"-datasets");f.createHdaView(h).$el.hide().prependTo(i).slideDown(f.fxSpeed)}])},createHdaView:function(g){var f=g.get("id"),e=this.storage.get("expandedHdas").get(f),h=new this.HDAView({model:g,expanded:e,hasUser:this.model.hasUser(),logger:this.logger});this._setUpHdaListeners(h);this.hdaViews[f]=h;return h.render()},_setUpHdaListeners:function(f){var e=this;f.on("body-expanded",function(g){e.storage.get("expandedHdas").set(g,true)});f.on("body-collapsed",function(g){e.storage.get("expandedHdas").deleteKey(g)});f.on("error",function(h,j,g,i){e.errorHandler(h,j,g,i)})},handleHdaDeletionChange:function(e){if(e.get("deleted")&&!this.storage.get("show_deleted")){this.removeHdaView(this.hdaViews[e.id])}},handleHdaVisibleChange:function(e){if(e.hidden()&&!this.storage.get("show_hidden")){this.removeHdaView(this.hdaViews[e.id])}},removeHdaView:function(f){if(!f){return}var e=this;f.$el.fadeOut(e.fxSpeed,function(){f.off();f.remove();delete e.hdaViews[f.model.id];if(_.isEmpty(e.hdaViews)){e.$el.find("#emptyHistoryMessage").fadeIn(e.fxSpeed)}})},render:function(g){var e=this,f;if(this.model){f=this.renderModel()}else{f=this.renderWithoutModel()}$(e).queue("fx",[function(h){if(e.$el.is(":visible")){e.$el.fadeOut(e.fxSpeed,h)}else{h()}},function(h){e.$el.empty();if(f){e.$el.append(f.children())}e.$el.fadeIn(e.fxSpeed,h)},function(h){e._setUpBehaviours();if(g){g.call(this)}e.trigger("rendered",this)}]);return this},renderModel:function(){var e=$("<div/>");e.append(c.templates.historyPanel(this.model.toJSON()));e.find("[title]").tooltip({placement:"bottom"});if(!this.model.hdas.length||!this.renderItems(e.find("#"+this.model.get("id")+"-datasets"))){e.find("#emptyHistoryMessage").show()}return e},renderWithoutModel:function(){var e=$("<div/>"),f=$("<div/>").attr("id","message-container").css({"margin-left":"4px","margin-right":"4px"});return e.append(f)},renderItems:function(f){this.hdaViews={};var e=this,g=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"));_.each(g,function(h){f.prepend(e.createHdaView(h).$el)});return g.length},_setUpBehaviours:function(){if(!this.model||!(this.model.get("user")&&this.model.get("user").email)){return}var e=this,f=this.$("#history-annotation-area");this.$("#history-annotate").click(function(){if(f.is(":hidden")){f.slideDown(e.fxSpeed)}else{f.slideUp(e.fxSpeed)}return false});async_save_text("history-name-container","history-name",this.model.renameUrl(),"new_name",18);async_save_text("history-annotation-container","history-annotation",this.model.annotateUrl(),"new_annotation",18,true,4)},updateHistoryDiskSize:function(){this.$el.find("#history-size").text(this.model.get("nice_size"))},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(e){e.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.render();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.render();return this.storage.get("show_hidden")},loadAndDisplayTags:function(g){this.log(this+".loadAndDisplayTags",g);var e=this,h=this.$el.find("#history-tag-area"),f=h.find(".tag-elt");this.log("\t tagArea",h," tagElt",f);if(h.is(":hidden")){if(!jQuery.trim(f.html())){$.ajax({url:e.model.tagUrl(),error:function(k,j,i){e.log("Error loading tag area html",k,j,i);e.trigger("error",e,k,null,_l("Error loading tags"))},success:function(i){f.html(i);f.find("[title]").tooltip();h.slideDown(e.fxSpeed)}})}else{h.slideDown(e.fxSpeed)}}else{h.slideUp(e.fxSpeed)}return false},showLoadingIndicator:function(f,e,g){e=(e!==undefined)?(e):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,g)}else{this.$el.fadeOut(e);this.indicator.show(e,g)}},hideLoadingIndicator:function(e,f){e=(e!==undefined)?(e):(this.fxSpeed);if(this.indicator){this.indicator.hide(e,f)}},displayMessage:function(j,k,i){var g=this;this.scrollToTop();var h=this.$el.find("#message-container"),e=$("<div/>").addClass(j+"message").html(k);if(!_.isEmpty(i)){var f=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(g.messageToModalOptions(j,k,i));return false});e.append(" ",f)}return h.html(e)},messageToModalOptions:function(i,k,h){var e=this,j=$("<div/>"),g={title:"Details"};function f(l){l=_.omit(l,_.functions(l));return["<table>",_.map(l,function(n,m){n=(_.isObject(n))?(f(n)):(n);return'<tr><td style="vertical-align: top; color: grey">'+m+'</td><td style="padding-left: 8px">'+n+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(h)){g.body=j.append(f(h))}else{g.body=j.html(h)}g.buttons={Ok:function(){Galaxy.modal.hide();e.clearMessages()}};return g},clearMessages:function(){var e=this.$el.find("#message-container");e.empty()},scrollPosition:function(){return this.$el.parent().scrollTop()},scrollTo:function(e){this.$el.parent().scrollTop(e)},scrollToTop:function(){this.$el.parent().scrollTop(0);return this},scrollIntoView:function(f,g){if(!g){this.$el.parent().parent().scrollTop(f);return this}var e=window,h=this.$el.parent().parent(),j=$(e).innerHeight(),i=(j/2)-(g/2);$(h).scrollTop(f-i);return this},scrollToId:function(f){if((!f)||(!this.hdaViews[f])){return this}var e=this.hdaViews[f].$el;this.scrollIntoView(e.offset().top,e.outerHeight());return this},scrollToHid:function(e){var f=this.model.hdas.getByHid(e);if(!f){return this}return this.scrollToId(f.id)},connectToQuotaMeter:function(e){if(!e){return this}this.listenTo(e,"quota:over",this.showQuotaMessage);this.listenTo(e,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(e&&e.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var e=this.$el.find("#quota-message-container");if(e.is(":hidden")){e.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var e=this.$el.find("#quota-message-container");if(!e.is(":hidden")){e.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(e){if(!e){return this}this.on("new-storage",function(g,f){if(e&&g){e.findItemByHtml(_l("Include Deleted Datasets")).checked=g.get("show_deleted");e.findItemByHtml(_l("Include Hidden Datasets")).checked=g.get("show_hidden")}});return this},toString:function(){return"HistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});c.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{HistoryPanel:c}}); \ 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)
-
commits-noreply@bitbucket.org