1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/8e4196a87a2b/ Changeset: 8e4196a87a2b User: carlfeberhard Date: 2014-02-20 17:34:19 Summary: History published/shared/display as slug: use annotated-history-panel, search open by default, preserve whitespace in annotations, replace import button with 'switch to' if owned by user viewing; Annotated History Panel: panel view of history that shows datasets as a table with additional dataset info in a left cell Affected #: 10 files diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 lib/galaxy/web/base/controller.py --- a/lib/galaxy/web/base/controller.py +++ b/lib/galaxy/web/base/controller.py @@ -760,7 +760,9 @@ return self.get_inaccessible_hda_dict( trans, hda ) hda_dict[ 'accessible' ] = True + #TODO: I'm unclear as to which access pattern is right hda_dict[ 'annotation' ] = hda.get_item_annotation_str( trans.sa_session, trans.user, hda ) + #annotation = getattr( hda, 'annotation', hda.get_item_annotation_str( trans.sa_session, trans.user, hda ) ) # ---- return here if deleted AND purged OR can't access purged = ( hda.purged or hda.dataset.purged ) diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 lib/galaxy/webapps/galaxy/controllers/history.py --- a/lib/galaxy/webapps/galaxy/controllers/history.py +++ b/lib/galaxy/webapps/galaxy/controllers/history.py @@ -904,8 +904,9 @@ @web.expose def display_by_username_and_slug( self, trans, username, slug ): - """ Display history based on a username and slug. """ - + """ + Display history based on a username and slug. + """ # Get history. session = trans.sa_session user = session.query( model.User ).filter_by( username=username ).first() @@ -931,7 +932,19 @@ user_item_rating = 0 ave_item_rating, num_ratings = self.get_ave_item_rating_data( trans.sa_session, history ) + # create ownership flag for template, dictify models + # note: adding original annotation since this is published - get_dict returns user-based annos + user_is_owner = trans.user == history.user + hda_dicts = [] + for hda in datasets: + hda_dict = self.get_hda_dict( trans, hda ) + hda_dict[ 'annotation' ] = hda.annotation + hda_dicts.append( hda_dict ) + history_dict = self.get_history_dict( trans, history, hda_dictionaries=hda_dicts ) + history_dict[ 'annotation' ] = history.annotation + return trans.stream_template_mako( "history/display.mako", item=history, item_data=datasets, + user_is_owner=user_is_owner, history_dict=history_dict, hda_dicts=hda_dicts, user_item_rating = user_item_rating, ave_item_rating=ave_item_rating, num_ratings=num_ratings ) @web.expose diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 static/scripts/mvc/history/annotated-history-panel.js --- /dev/null +++ b/static/scripts/mvc/history/annotated-history-panel.js @@ -0,0 +1,118 @@ +define([ + "mvc/dataset/hda-model", + "mvc/dataset/hda-base", + "mvc/history/readonly-history-panel" +], function( hdaModel, hdaBase, readonlyPanel ){ +/* ============================================================================= +TODO: + +============================================================================= */ +/** @class View/Controller for a tabular view of the history model. + * @name AnnotatedHistoryPanel + * + * As ReadOnlyHistoryPanel, but with: + * history annotation always shown + * datasets displayed in a table: + * datasets in left cells, dataset annotations in the right + * + * @augments Backbone.View + * @borrows LoggableMixin#logger as #logger + * @borrows LoggableMixin#log as #log + * @constructs + */ +var AnnotatedHistoryPanel = readonlyPanel.ReadOnlyHistoryPanel.extend( +/** @lends HistoryPanel.prototype */{ + + ///** logger used to record this.log messages, commonly set to console */ + //// comment this out to suppress log output + //logger : console, + + className : 'annotated-history-panel', + + /** class to use for constructing the HDA views */ + HDAViewClass : hdaBase.HDABaseView, + + // ------------------------------------------------------------------------ panel rendering + renderModel : function( ){ + // huh? + this.$el.addClass( this.className ); + var $newRender = readonlyPanel.ReadOnlyHistoryPanel.prototype.renderModel.call( this ), + // move datasets from div to table + $datasetsList = $newRender.find( this.datasetsSelector ), + $datasetsTable = $( '<table/>' ).addClass( 'datasets-list datasets-table' ); + $datasetsTable.append( $datasetsList.children() ); + $newRender.find( this.datasetsSelector ).replaceWith( $datasetsTable ); + //TODO: it's possible to do this with css only, right? + + // add history annotation under subtitle + $newRender.find( '.history-subtitle' ).after( this.renderHistoryAnnotation() ); + + // hide search button, move search bar beneath controls (instead of above title), show, and set up + $newRender.find( '.history-search-btn' ).hide(); + $newRender.find( '.history-controls' ).after( $newRender.find( '.history-search-controls' ).show() ); + this.setUpSearchInput( $newRender.find( '.history-search-input' ) ); + + return $newRender; + }, + + renderHistoryAnnotation : function(){ + var annotation = this.model.get( 'annotation' ); + if( !annotation ){ return null; } + return $([ + '<div class="history-annotation">', annotation, '</div>' + ].join( '' )); + }, + + renderHdas : function( $whereTo ){ + $whereTo = $whereTo || this.$el; + var hdaViews = readonlyPanel.ReadOnlyHistoryPanel.prototype.renderHdas.call( this, $whereTo ); + $whereTo.find( this.datasetsSelector ).prepend( $( '<tr/>' ).addClass( 'headers' ).append([ + $( '<th/>' ).text( _l( 'Dataset' ) ), + $( '<th/>' ).text( _l( 'Annotation' ) ) + ])); + return hdaViews; + }, + + // ------------------------------------------------------------------------ hda sub-views + attachHdaView : function( hdaView, $whereTo ){ + $whereTo = $whereTo || this.$el; + // build a row around the dataset with the std hdaView in the first cell and the annotation in the next + var stateClass = _.find( hdaView.el.classList, function( c ){ return ( /^state\-/ ).test( c ); }), + annotation = hdaView.model.get( 'annotation' ) || '', + $tr = $( '<tr/>' ).addClass( 'dataset-row' ).append([ + $( '<td/>' ).addClass( 'dataset-container' ).append( hdaView.$el ) + // visually match the cell bg to the dataset at runtime (prevents the empty space) + // (getting bg via jq on hidden elem doesn't work on chrome/webkit - so use states) + //.css( 'background-color', hdaView.$el.css( 'background-color' ) ), + .addClass( stateClass? stateClass.replace( '-', '-color-' ): '' ), + $( '<td/>' ).addClass( 'additional-info' ).text( annotation ) + ]); + $whereTo.find( this.datasetsSelector ).append( $tr ); + }, + + // ------------------------------------------------------------------------ panel events + /** event map */ + events : _.extend( _.clone( readonlyPanel.ReadOnlyHistoryPanel.prototype.events ), { + 'click tr' : function( ev ){ + //if( !ev.target.hasAttribute( 'href' ) ){ + $( ev.currentTarget ).find( '.dataset-title-bar' ).click(); + //} + }, + // prevent propagation on icon btns so they won't bubble up to tr and toggleBodyVisibility + 'click .icon-btn' : function( ev ){ + ev.stopPropagation(); + } + }), + + // ........................................................................ misc + /** Return a string rep of the history */ + toString : function(){ + return 'AnnotatedHistoryPanel(' + (( this.model )?( this.model.get( 'name' )):( '' )) + ')'; + } +}); + +//============================================================================== + return { + AnnotatedHistoryPanel : AnnotatedHistoryPanel + }; +}); diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 static/scripts/mvc/history/readonly-history-panel.js --- a/static/scripts/mvc/history/readonly-history-panel.js +++ b/static/scripts/mvc/history/readonly-history-panel.js @@ -526,7 +526,6 @@ $whereTo = $whereTo || this.$el; var historyView = this, newHdaViews = {}, - $datasetsList = $whereTo.find( this.datasetsSelector ), // only render the shown hdas //TODO: switch to more general filtered pattern visibleHdas = this.model.hdas.getVisible( @@ -536,7 +535,7 @@ ); //console.debug( 'renderHdas, visibleHdas:', visibleHdas, $whereTo ); //TODO: prepend to sep div, add as one - $datasetsList.empty(); + $whereTo.find( this.datasetsSelector ).empty(); if( visibleHdas.length ){ visibleHdas.each( function( hda ){ @@ -547,7 +546,7 @@ if( _.contains( historyView.selectedHdaIds, hdaId ) ){ hdaView.selected = true; } - $datasetsList.prepend( hdaView.render().$el ); + historyView.attachHdaView( hdaView.render(), $whereTo ); }); $whereTo.find( this.emptyMsgSelector ).hide(); @@ -561,6 +560,12 @@ return this.hdaViews; }, + attachHdaView : function( hdaView, $whereTo ){ + $whereTo = $whereTo || this.$el; + var $datasetsList = $whereTo.find( this.datasetsSelector ); + $datasetsList.prepend( hdaView.$el ); + }, + /** Add an hda view to the panel for the given hda * @param {HistoryDatasetAssociation} hda */ diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 static/scripts/packed/mvc/history/annotated-history-panel.js --- /dev/null +++ b/static/scripts/packed/mvc/history/annotated-history-panel.js @@ -0,0 +1,1 @@ +define(["mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/history/readonly-history-panel"],function(c,a,b){var d=b.ReadOnlyHistoryPanel.extend({className:"annotated-history-panel",HDAViewClass:a.HDABaseView,renderModel:function(){this.$el.addClass(this.className);var g=b.ReadOnlyHistoryPanel.prototype.renderModel.call(this),e=g.find(this.datasetsSelector),f=$("<table/>").addClass("datasets-list datasets-table");f.append(e.children());g.find(this.datasetsSelector).replaceWith(f);g.find(".history-subtitle").after(this.renderHistoryAnnotation());g.find(".history-search-btn").hide();g.find(".history-controls").after(g.find(".history-search-controls").show());this.setUpSearchInput(g.find(".history-search-input"));return g},renderHistoryAnnotation:function(){var e=this.model.get("annotation");if(!e){return null}return $(['<div class="history-annotation">',e,"</div>"].join(""))},renderHdas:function(f){f=f||this.$el;var e=b.ReadOnlyHistoryPanel.prototype.renderHdas.call(this,f);f.find(this.datasetsSelector).prepend($("<tr/>").addClass("headers").append([$("<th/>").text(_l("Dataset")),$("<th/>").text(_l("Annotation"))]));return e},attachHdaView:function(h,f){f=f||this.$el;var i=_.find(h.el.classList,function(j){return(/^state\-/).test(j)}),e=h.model.get("annotation")||"",g=$("<tr/>").addClass("dataset-row").append([$("<td/>").addClass("dataset-container").append(h.$el).addClass(i?i.replace("-","-color-"):""),$("<td/>").addClass("additional-info").text(e)]);f.find(this.datasetsSelector).append(g)},events:_.extend(_.clone(b.ReadOnlyHistoryPanel.prototype.events),{"click tr":function(e){$(e.currentTarget).find(".dataset-title-bar").click()},"click .icon-btn":function(e){e.stopPropagation()}}),toString:function(){return"AnnotatedHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{AnnotatedHistoryPanel:d}}); \ No newline at end of file diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 static/scripts/packed/mvc/history/readonly-history-panel.js --- a/static/scripts/packed/mvc/history/readonly-history-panel.js +++ b/static/scripts/packed/mvc/history/readonly-history-panel.js @@ -1,1 +1,1 @@ -define(["mvc/history/history-model","mvc/dataset/hda-base"],function(e,a){var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(f){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([f],[true])))},removeExpandedHda:function(f){this.save("expandedHdas",_.omit(this.get("expandedHdas"),f))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function c(f){if(!f){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+f)}return("history:"+f)};var b=Backbone.View.extend(LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",msgsSelector:".message-container",emptyMsgSelector:".empty-history-message",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(f){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.linkTarget=f.linkTarget||"_blank";this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searchFor="";this._setUpListeners();if(this.model){this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers()}if(f.onready){f.onready.call(this)}},_setUpListeners:function(){this.on("error",function(g,j,f,i,h){this.errorHandler(g,j,f,i,h)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}},errorHandler:function(h,k,g,j,i){var f=this._parseErrorMessage(h,k,g,j,i);if(k&&k.status===0&&k.readyState===0){}else{if(k&&k.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",f.message,f.details)})}else{this.displayMessage("error",f.message,f.details)}}}},_parseErrorMessage:function(i,m,h,l,k){var g=Galaxy.currUser,f={message:this._bePolite(l),details:{user:(g instanceof User)?(g.toJSON()):(g+""),source:(i instanceof Backbone.Model)?(i.toJSON()):(i+""),xhr:m,options:(m)?(_.omit(h,"xhr")):(h)}};_.extend(f.details,k||{});if(m&&_.isFunction(m.getAllResponseHeaders)){var j=m.getAllResponseHeaders();j=_.compact(j.split("\n"));j=_.map(j,function(n){return n.split(": ")});f.details.xhr.responseHeaders=_.object(j)}return f},_bePolite:function(f){f=f||_l("An error occurred while getting updates from the server");return f+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(i,h,g,k){var f=this,j=function(l){return f.getExpandedHdaIds(l.id)};return this.loadHistory(i,h,g,k,j)},loadHistory:function(i,h,g,l,j){this.trigger("loading-history",this);h=h||{};var f=this;var k=e.History.getHistoryData(i,{historyFn:g,hdaFn:l,hdaDetailIds:h.initiallyExpanded||j});return this._loadHistoryFromXHR(k,h).fail(function(o,m,n){f.trigger("error",f,o,h,_l("An error was encountered while "+m),{historyId:i,history:n||{}})}).always(function(){f.trigger("loading-done",f)})},_loadHistoryFromXHR:function(h,g){var f=this;h.then(function(i,j){f.setModel(i,j,g)});h.fail(function(j,i){f.render()});return h},setModel:function(h,f,g){g=g||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){h.user=Galaxy.currUser.toJSON()}this.model=new e.History(h,f,g);this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(g,f,h){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(g)){this.storage.set("exandedHdas",g)}if(_.isBoolean(f)){this.storage.set("show_deleted",f)}if(_.isBoolean(h)){this.storage.set("show_hidden",h)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var f in sessionStorage){if(f.indexOf("history:")===0){sessionStorage.removeItem(f)}}},getStoredOptions:function(g){if(!g||g==="current"){return(this.storage)?(this.storage.get()):({})}var f=sessionStorage.getItem(d.historyStorageKey(g));return(f===null)?({}):(JSON.parse(f))},getExpandedHdaIds:function(f){var g=this.getStoredOptions(f).expandedHdas;return((_.isEmpty(g))?([]):(_.keys(g)))},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(g,i,f,h){this.errorHandler(g,i,f,h)},this)},render:function(h,i){h=(h===undefined)?(this.fxSpeed):(h);var f=this,g;if(this.model){g=this.renderModel()}else{g=this.renderWithoutModel()}$(f).queue("fx",[function(j){if(h&&f.$el.is(":visible")){f.$el.fadeOut(h,j)}else{j()}},function(j){f.$el.empty();if(g){f.$el.append(g.children())}j()},function(j){if(h&&!f.$el.is(":visible")){f.$el.fadeIn(h,j)}else{j()}},function(j){if(i){i.call(this)}f.trigger("rendered",this);j()}]);return this},renderWithoutModel:function(){var f=$("<div/>"),g=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return f.append(g)},renderModel:function(){var f=$("<div/>");f.append(b.templates.historyPanel(this.model.toJSON()));f.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(f);this.renderHdas(f);return f},_renderSearchButton:function(f){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},createHdaView:function(g){var f=g.get("id"),h=new this.HDAViewClass({model:g,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[f],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(h);return h},_setUpHdaListeners:function(g){var f=this;g.on("body-expanded",function(h){f.storage.addExpandedHda(h)});g.on("body-collapsed",function(h){f.storage.removeExpandedHda(h)});g.on("error",function(i,k,h,j){f.errorHandler(i,k,h,j)})},renderHdas:function(h){h=h||this.$el;var g=this,j={},f=h.find(this.datasetsSelector),i=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);f.empty();if(i.length){i.each(function(l){var k=l.get("id"),m=g.createHdaView(l);j[k]=m;if(_.contains(g.selectedHdaIds,k)){m.selected=true}f.prepend(m.render().$el)});h.find(this.emptyMsgSelector).hide()}else{h.find(this.emptyMsgSelector).text((this.model.hdas.length&&this.searchFor)?(this.noneFoundMsg):(this.emptyMsg)).show()}this.hdaViews=j;return this.hdaViews},addHdaView:function(i){this.log("add."+this,i);var g=this;if(!i.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function h(k){var j=g.$el.find(g.emptyMsgSelector);if(j.is(":visible")){j.fadeOut(g.fxSpeed,k)}else{k()}},function f(k){g.scrollToTop();var j=g.$el.find(g.datasetsSelector),l=g.createHdaView(i);g.hdaViews[i.id]=l;l.render().$el.hide().prependTo(j).slideDown(g.fxSpeed)}])},refreshHdas:function(g,f){if(this.model){return this.model.refresh(g,f)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(f){f.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(g){var h=this,k=".history-search-input";function j(l){h.searchFor=l;h.filters=[function(m){return m.matchesAll(h.searchFor)}];h.trigger("search:searching",l,h);h.renderHdas()}function f(l){if(h.model.hdas.haveDetails()){j(l);return}h.$el.find(k).searchInput("toggle-loading");h.model.hdas.fetchAllDetails({silent:true}).always(function(){h.$el.find(k).searchInput("toggle-loading")}).done(function(){j(l)})}function i(){h.searchFor="";h.filters=[];h.trigger("search:clear",h);h.renderHdas()}g.searchInput({initialVal:h.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:f,onsearch:j,onclear:i});return g},showSearchControls:function(g){g=(g===undefined)?(this.fxSpeed):(g);var f=this.$el.find(".history-search-controls"),h=f.find(".history-search-input");if(!h.children().size()){this.setUpSearchInput(h)}f.slideDown(g,function(){$(this).find("input").focus()})},hideSearchControls:function(f){f=(f===undefined)?(this.fxSpeed):(f);this.$el.find(".history-search-controls").slideUp(f)},toggleSearchControls:function(f){speed=(jQuery.type(f)==="number")?(f):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showLoadingIndicator:function(g,f,h){f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},hideLoadingIndicator:function(f,g){f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},displayMessage:function(k,l,j){var h=this;this.scrollToTop();var i=this.$el.find(this.msgsSelector),f=$("<div/>").addClass(k+"message").html(l);if(!_.isEmpty(j)){var g=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(h._messageToModalOptions(k,l,j));return false});f.append(" ",g)}return i.html(f)},_messageToModalOptions:function(j,l,i){var f=this,k=$("<div/>"),h={title:"Details"};function g(m){m=_.omit(m,_.functions(m));return["<table>",_.map(m,function(o,n){o=(_.isObject(o))?(g(o)):(o);return'<tr><td style="vertical-align: top; color: grey">'+n+'</td><td style="padding-left: 8px">'+o+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(i)){h.body=k.append(g(i))}else{h.body=k.html(i)}h.buttons={Ok:function(){Galaxy.modal.hide();f.clearMessages()}};return h},clearMessages:function(){var f=this.$el.find(this.msgsSelector);f.empty()},scrollPosition:function(){return this.$el.scrollTop()},scrollTo:function(f){this.$el.scrollTop(f);return this},scrollToTop:function(){this.$el.scrollTop(0);return this},scrollIntoView:function(k,g){if(g===undefined){this.scrollTo(k);return this}var f=window,j=this.$el.parent(),i=$(f).innerHeight(),h=(i/2)-(g/2);this.scrollTo(k-h);return this},scrollToId:function(g){if((!g)||(!this.hdaViews[g])){return this}var f=this.hdaViews[g].$el;this.scrollIntoView(f.offset().top,f.outerHeight());return this},scrollToHid:function(f){var g=this.model.hdas.getByHid(f);if(!g){return this}return this.scrollToId(g.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});b.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{ReadOnlyHistoryPanel:b}}); \ No newline at end of file +define(["mvc/history/history-model","mvc/dataset/hda-base"],function(e,a){var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(f){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([f],[true])))},removeExpandedHda:function(f){this.save("expandedHdas",_.omit(this.get("expandedHdas"),f))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function c(f){if(!f){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+f)}return("history:"+f)};var b=Backbone.View.extend(LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",msgsSelector:".message-container",emptyMsgSelector:".empty-history-message",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(f){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.linkTarget=f.linkTarget||"_blank";this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searchFor="";this._setUpListeners();if(this.model){this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers()}if(f.onready){f.onready.call(this)}},_setUpListeners:function(){this.on("error",function(g,j,f,i,h){this.errorHandler(g,j,f,i,h)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}},errorHandler:function(h,k,g,j,i){var f=this._parseErrorMessage(h,k,g,j,i);if(k&&k.status===0&&k.readyState===0){}else{if(k&&k.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",f.message,f.details)})}else{this.displayMessage("error",f.message,f.details)}}}},_parseErrorMessage:function(i,m,h,l,k){var g=Galaxy.currUser,f={message:this._bePolite(l),details:{user:(g instanceof User)?(g.toJSON()):(g+""),source:(i instanceof Backbone.Model)?(i.toJSON()):(i+""),xhr:m,options:(m)?(_.omit(h,"xhr")):(h)}};_.extend(f.details,k||{});if(m&&_.isFunction(m.getAllResponseHeaders)){var j=m.getAllResponseHeaders();j=_.compact(j.split("\n"));j=_.map(j,function(n){return n.split(": ")});f.details.xhr.responseHeaders=_.object(j)}return f},_bePolite:function(f){f=f||_l("An error occurred while getting updates from the server");return f+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(i,h,g,k){var f=this,j=function(l){return f.getExpandedHdaIds(l.id)};return this.loadHistory(i,h,g,k,j)},loadHistory:function(i,h,g,l,j){this.trigger("loading-history",this);h=h||{};var f=this;var k=e.History.getHistoryData(i,{historyFn:g,hdaFn:l,hdaDetailIds:h.initiallyExpanded||j});return this._loadHistoryFromXHR(k,h).fail(function(o,m,n){f.trigger("error",f,o,h,_l("An error was encountered while "+m),{historyId:i,history:n||{}})}).always(function(){f.trigger("loading-done",f)})},_loadHistoryFromXHR:function(h,g){var f=this;h.then(function(i,j){f.setModel(i,j,g)});h.fail(function(j,i){f.render()});return h},setModel:function(h,f,g){g=g||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){h.user=Galaxy.currUser.toJSON()}this.model=new e.History(h,f,g);this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(g,f,h){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(g)){this.storage.set("exandedHdas",g)}if(_.isBoolean(f)){this.storage.set("show_deleted",f)}if(_.isBoolean(h)){this.storage.set("show_hidden",h)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var f in sessionStorage){if(f.indexOf("history:")===0){sessionStorage.removeItem(f)}}},getStoredOptions:function(g){if(!g||g==="current"){return(this.storage)?(this.storage.get()):({})}var f=sessionStorage.getItem(d.historyStorageKey(g));return(f===null)?({}):(JSON.parse(f))},getExpandedHdaIds:function(f){var g=this.getStoredOptions(f).expandedHdas;return((_.isEmpty(g))?([]):(_.keys(g)))},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(g,i,f,h){this.errorHandler(g,i,f,h)},this)},render:function(h,i){h=(h===undefined)?(this.fxSpeed):(h);var f=this,g;if(this.model){g=this.renderModel()}else{g=this.renderWithoutModel()}$(f).queue("fx",[function(j){if(h&&f.$el.is(":visible")){f.$el.fadeOut(h,j)}else{j()}},function(j){f.$el.empty();if(g){f.$el.append(g.children())}j()},function(j){if(h&&!f.$el.is(":visible")){f.$el.fadeIn(h,j)}else{j()}},function(j){if(i){i.call(this)}f.trigger("rendered",this);j()}]);return this},renderWithoutModel:function(){var f=$("<div/>"),g=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return f.append(g)},renderModel:function(){var f=$("<div/>");f.append(b.templates.historyPanel(this.model.toJSON()));f.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(f);this.renderHdas(f);return f},_renderSearchButton:function(f){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},createHdaView:function(g){var f=g.get("id"),h=new this.HDAViewClass({model:g,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[f],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(h);return h},_setUpHdaListeners:function(g){var f=this;g.on("body-expanded",function(h){f.storage.addExpandedHda(h)});g.on("body-collapsed",function(h){f.storage.removeExpandedHda(h)});g.on("error",function(i,k,h,j){f.errorHandler(i,k,h,j)})},renderHdas:function(g){g=g||this.$el;var f=this,i={},h=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);g.find(this.datasetsSelector).empty();if(h.length){h.each(function(k){var j=k.get("id"),l=f.createHdaView(k);i[j]=l;if(_.contains(f.selectedHdaIds,j)){l.selected=true}f.attachHdaView(l.render(),g)});g.find(this.emptyMsgSelector).hide()}else{g.find(this.emptyMsgSelector).text((this.model.hdas.length&&this.searchFor)?(this.noneFoundMsg):(this.emptyMsg)).show()}this.hdaViews=i;return this.hdaViews},attachHdaView:function(h,g){g=g||this.$el;var f=g.find(this.datasetsSelector);f.prepend(h.$el)},addHdaView:function(i){this.log("add."+this,i);var g=this;if(!i.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function h(k){var j=g.$el.find(g.emptyMsgSelector);if(j.is(":visible")){j.fadeOut(g.fxSpeed,k)}else{k()}},function f(k){g.scrollToTop();var j=g.$el.find(g.datasetsSelector),l=g.createHdaView(i);g.hdaViews[i.id]=l;l.render().$el.hide().prependTo(j).slideDown(g.fxSpeed)}])},refreshHdas:function(g,f){if(this.model){return this.model.refresh(g,f)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(f){f.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(g){var h=this,k=".history-search-input";function j(l){h.searchFor=l;h.filters=[function(m){return m.matchesAll(h.searchFor)}];h.trigger("search:searching",l,h);h.renderHdas()}function f(l){if(h.model.hdas.haveDetails()){j(l);return}h.$el.find(k).searchInput("toggle-loading");h.model.hdas.fetchAllDetails({silent:true}).always(function(){h.$el.find(k).searchInput("toggle-loading")}).done(function(){j(l)})}function i(){h.searchFor="";h.filters=[];h.trigger("search:clear",h);h.renderHdas()}g.searchInput({initialVal:h.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:f,onsearch:j,onclear:i});return g},showSearchControls:function(g){g=(g===undefined)?(this.fxSpeed):(g);var f=this.$el.find(".history-search-controls"),h=f.find(".history-search-input");if(!h.children().size()){this.setUpSearchInput(h)}f.slideDown(g,function(){$(this).find("input").focus()})},hideSearchControls:function(f){f=(f===undefined)?(this.fxSpeed):(f);this.$el.find(".history-search-controls").slideUp(f)},toggleSearchControls:function(f){speed=(jQuery.type(f)==="number")?(f):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showLoadingIndicator:function(g,f,h){f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},hideLoadingIndicator:function(f,g){f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},displayMessage:function(k,l,j){var h=this;this.scrollToTop();var i=this.$el.find(this.msgsSelector),f=$("<div/>").addClass(k+"message").html(l);if(!_.isEmpty(j)){var g=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(h._messageToModalOptions(k,l,j));return false});f.append(" ",g)}return i.html(f)},_messageToModalOptions:function(j,l,i){var f=this,k=$("<div/>"),h={title:"Details"};function g(m){m=_.omit(m,_.functions(m));return["<table>",_.map(m,function(o,n){o=(_.isObject(o))?(g(o)):(o);return'<tr><td style="vertical-align: top; color: grey">'+n+'</td><td style="padding-left: 8px">'+o+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(i)){h.body=k.append(g(i))}else{h.body=k.html(i)}h.buttons={Ok:function(){Galaxy.modal.hide();f.clearMessages()}};return h},clearMessages:function(){var f=this.$el.find(this.msgsSelector);f.empty()},scrollPosition:function(){return this.$el.scrollTop()},scrollTo:function(f){this.$el.scrollTop(f);return this},scrollToTop:function(){this.$el.scrollTop(0);return this},scrollIntoView:function(k,g){if(g===undefined){this.scrollTo(k);return this}var f=window,j=this.$el.parent(),i=$(f).innerHeight(),h=(i/2)-(g/2);this.scrollTo(k-h);return this},scrollToId:function(g){if((!g)||(!this.hdaViews[g])){return this}var f=this.hdaViews[g].$el;this.scrollIntoView(f.offset().top,f.outerHeight());return this},scrollToHid:function(f){var g=this.model.hdas.getByHid(f);if(!g){return this}return this.scrollToId(g.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});b.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{ReadOnlyHistoryPanel:b}}); \ No newline at end of file diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 static/style/blue/base.css --- a/static/style/blue/base.css +++ b/static/style/blue/base.css @@ -1684,6 +1684,19 @@ .dataset.state-discarded{background:#eee}.dataset.state-discarded .state-icon:before{content:"\f014"} .dataset.state-noPermission{background:#eee;filter:alpha(opacity=60);-moz-opacity:.60;opacity:.60}.dataset.state-noPermission .state-icon{font-size:20px}.dataset.state-noPermission .state-icon:before{content:"\f023"} .dataset.state-new{background:#eee}.dataset.state-new .state-icon:before{content:"\f06a"} +.annotated-history-panel{padding-top:10px}.annotated-history-panel [class$=messagesmall]{margin:8px 0px 8px 0px} +.annotated-history-panel .history-controls{margin:0px 0px 16px 4px;padding:0px}.annotated-history-panel .history-controls .history-name{font-size:150%} +.annotated-history-panel .history-controls .history-subtitle{margin:0px;padding:0px 0px 0px 4px;padding-left:4px} +.annotated-history-panel .history-controls .history-annotation{border:1px solid lightgrey;border-width:1px 0px 0px 0px;padding:4px 0px 4px 0px;margin:4px;white-space:pre-wrap} +.annotated-history-panel .history-controls .history-annotation:empty{display:none} +.annotated-history-panel .history-controls .history-search-controls{padding:16px 0px 0px 0px} +.annotated-history-panel table.datasets-list{width:100%;table-layout:fixed}.annotated-history-panel table.datasets-list .headers{border-bottom:2px solid grey} +.annotated-history-panel table.datasets-list .headers th{padding:8px} +.annotated-history-panel table.datasets-list .dataset-row{cursor:pointer;border-bottom:1px solid grey} +.annotated-history-panel table.datasets-list .dataset-row>td{margin:0px;padding:0px;vertical-align:top} +.annotated-history-panel table.datasets-list .dataset-row>td:nth-child(1){width:50%} +.annotated-history-panel table.datasets-list .dataset-row>td:nth-child(2){padding:8px 16px 8px 16px;white-space:pre-wrap} +.annotated-history-panel table.datasets-list .dataset-row .dataset{border:0px} .hda .hda-hid:after{content:':'} body.historyPage{background:#dfe5f9;color:#000;margin:5px;border:0;padding:0} div.historyLinks{margin:5px 5px} diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 static/style/src/less/history.less --- a/static/style/src/less/history.less +++ b/static/style/src/less/history.less @@ -688,6 +688,78 @@ } +// ---------------------------------------------------------------------------- annotated-history-panel +.annotated-history-panel { + //TODO: most of these styles are specific to history/display.mako and not to this type of panel in general + //TODO: some of these styles are also overrides of history-panel - remove those from hpanel and revisit this + padding-top: 10px; + + [class$=messagesmall] { + margin: 8px 0px 8px 0px; + } + + .history-controls { + margin: 0px 0px 16px 4px; + padding: 0px; + + .history-name { + font-size: 150%; + } + .history-subtitle { + margin: 0px; + padding: 0px 0px 0px 4px; + padding-left: 4px; + } + + .history-annotation { + border: 1px solid lightgrey; + border-width: 1px 0px 0px 0px; + padding: 4px 0px 4px 0px; + margin: 4px; + white-space: pre-wrap; + } + .history-annotation:empty { + display: none; + } + + .history-search-controls { + padding: 16px 0px 0px 0px; + } + } + + table.datasets-list { + width: 100%; + table-layout: fixed; + + .headers { + border-bottom: 2px solid grey; + } + .headers th { + padding: 8px; + } + .dataset-row { + cursor: pointer; + border-bottom: 1px solid grey; + } + .dataset-row > td { + margin: 0px; + padding: 0px; + vertical-align: top; + } + .dataset-row > td:nth-child(1) { + width: 50%; + } + .dataset-row > td:nth-child(2) { + /* top and bottom should be <= title-bar padding */ + padding: 8px 16px 8px 16px; + white-space: pre-wrap; + } + .dataset-row .dataset { + border: 0px; + } + } +} + // ---------------------------------------------------------------------------- hdas .hda .hda-hid:after { content: ':'; diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 templates/display_base.mako --- a/templates/display_base.mako +++ b/templates/display_base.mako @@ -85,7 +85,7 @@ }); // Init history boxes. - init_history_items( $("div.historyItemWrapper"), false, "nochanges" ); + //init_history_items( $("div.historyItemWrapper"), false, "nochanges" ); // Init user item rating. $('.user_rating_star').rating({ @@ -115,7 +115,7 @@ <%def name="stylesheets()"> ${parent.stylesheets()} ${h.css( "autocomplete_tagging", "embed_item", "jquery.rating" )} - ${h.css( "history", "autocomplete_tagging", "trackster", "library", + ${h.css( "autocomplete_tagging", "trackster", "library", "jquery-ui/smoothness/jquery-ui" )} <style type="text/css"> diff -r 32eadec01e3ebeb076b68938269e22f45fb202bb -r 8e4196a87a2b78521241adf104f524a5ea05caa1 templates/webapps/galaxy/history/display.mako --- a/templates/webapps/galaxy/history/display.mako +++ b/templates/webapps/galaxy/history/display.mako @@ -1,84 +1,74 @@ <%inherit file="/display_base.mako"/> -<%namespace file="/root/history_common.mako" import="render_dataset" /> +<%namespace file="history_panel.mako" import="history_panel_javascripts" /> ## Set vars so that there's no need to change the code below. -<% +<% history = published_item datasets = published_item_data %><%def name="javascripts()"> ${parent.javascripts()} + ${history_panel_javascripts()} </%def><%def name="stylesheets()"> ${parent.stylesheets()} - ${h.css( "history" )} <style type="text/css"> - .historyItemBody { - display: none; - } - .column { - float: left; - padding: 10px; - margin: 20px; - background: #666; - border: 5px solid #ccc; - width: 300px; - } </style> - - <noscript> - <style> - .historyItemBody { - display: block; - } - </style> - </noscript></%def><%def name="render_item_links( history )"> - <a - href="${h.url_for( controller='/history', action='imp', id=trans.security.encode_id(history.id) )}" - class="icon-button import" - ## Needed to overwide initial width so that link is floated left appropriately. - style="width: 100%" - title="Import history">Import history</a> +<% + encoded_history_id = history_dict[ 'id' ] + import_url = h.url_for( controller='history', action='imp', id=encoded_history_id ) + switch_url = h.url_for( controller='history', action='switch_to_history', hist_id=encoded_history_id ) +%> + ## Needed to overwide initial width so that link is floated left appropriately. + %if not user_is_owner: + <a href="${import_url}" style="width: 100%" title="${_('Make a copy of this history and switch to it')}"> + ${_('Import history')} + </a> + %else: + <a href="${switch_url}" style="width: 100%" title="${_('Make this history your current history')}"> + ${_('Switch to this history')} + </a> + %endif +</%def> + +<%def name="render_item_header( item )"></%def><%def name="render_item( history, datasets )"> - %if history.deleted: - <div class="warningmessagesmall"> - ${_('You are currently viewing a deleted history!')} - </div> - <p></p> - %endif - %if not datasets: - <div class="infomessagesmall" id="emptyHistoryMessage"> - %else: - ## Render requested datasets, ordered from newest to oldest, including annotations. - <table class="annotated-item"> - <tr><th>Dataset</th><th class="annotation">Annotation</th></tr> - %for data in datasets: - <tr> - %if data.visible: - <td> - <div class="historyItemContainer visible-right-border" id="historyItemContainer-${data.id}"> - ${render_dataset( data, data.hid, show_deleted_on_refresh = show_deleted, for_editing=False )} - </div> - </td> - <td class="annotation"> - %if hasattr( data, "annotation") and data.annotation is not None: - ${data.annotation} - %endif - </td> - %endif - </tr> - %endfor - </table> - <div class="infomessagesmall" id="emptyHistoryMessage" style="display:none;"> - %endif - ${_("This history is empty.")} - </div> +<div id="history-${ history_dict[ 'id' ] }" class="history-panel"> +</div> +<script type="text/javascript"> + var debugging = JSON.parse( sessionStorage.getItem( 'debugging' ) ) || false, + historyJSON = ${h.to_json_string( history_dict )}, + hdaJSON = ${h.to_json_string( hda_dicts )}; + //window.historyJSON = historyJSON; + window.hdaJSON = hdaJSON; + + require.config({ + baseUrl : "${h.url_for( '/static/scripts' )}" + })([ 'mvc/history/annotated-history-panel' ], function( panelMod ){ + // history module is already in the dpn chain from the panel. We can re-scope it here. + var historyModel = require( 'mvc/history/history-model' ), + hdaBaseView = require( 'mvc/dataset/hda-base' ), + history = new historyModel.History( historyJSON, hdaJSON, { + logger: ( debugging )?( console ):( null ) + }); + + window.historyPanel = new panelMod.AnnotatedHistoryPanel({ + show_deleted : false, + show_hidden : false, + el : $( "#history-" + historyJSON.id ), + model : history, + onready : function(){ + this.render(); + } + }); + }); +</script></%def> Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.