diff --git a/client/galaxy/scripts/mvc/history/multi-panel.js b/client/galaxy/scripts/mvc/history/multi-panel.js
index 7d8a8aae928..e8ffff203c9 100644
--- a/client/galaxy/scripts/mvc/history/multi-panel.js
+++ b/client/galaxy/scripts/mvc/history/multi-panel.js
@@ -6,7 +6,6 @@ define([
"ui/mode-button",
"ui/search-input"
], function( HISTORY_MODEL, HPANEL_EDIT, baseMVC, ajaxQueue ){
-window.HISTORY_MODEL = HISTORY_MODEL;
//==============================================================================
/** */
function historyCopyDialog( history, options ){
@@ -265,7 +264,7 @@ var HistoryPanelColumn = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return ( this.currentHistory )?
[
'
',
- '', _l( 'Create new' ), ' ',
+ '', _l( 'Current History' ), ' ',
'
'
].join( '' )
:[
@@ -328,6 +327,7 @@ var HistoryPanelColumn = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
//logger : console,
+ className : 'multi-history-columns',
// ------------------------------------------------------------------------ set up
/** Set up internals, history collection, and columns to display the history */
@@ -366,9 +366,8 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
/** model id to column map */
this.columnMap = {};
-//TODO: why create here?
+ //TODO: why create here?
this.createColumns( options.columnOptions );
-
this.setUpListeners();
},
@@ -386,10 +385,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var multipanel = this;
multipanel.stopListening( multipanel.collection );
multipanel.collection = models;
-//TODO: slow... esp. on start up
- //if( multipanel.order !== 'update' ){
- multipanel.sortCollection( multipanel.order, { silent: true });
- //}
+ multipanel.sortCollection( multipanel.order, { silent: true });
multipanel.setUpCollectionListeners();
multipanel.trigger( 'new-collection', multipanel );
return multipanel;
@@ -408,11 +404,6 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
'change:deleted': multipanel.handleDeletedHistory,
'sort' : function(){ multipanel.renderColumns( 0 ); }
-
- // debugging
- //'all' : function(){
- // console.info( 'collection:', arguments );
- //}
});
},
@@ -430,11 +421,6 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
this.sortCollection();
-////TODO: this actually means these render twice (1st from setCollection) - good enough for now
- //if( oldCurrentColumn ){ oldCurrentColumn.render().delegateEvents(); }
- //TODO:?? this occasionally causes race with hdaQueue
- //newCurrentColumn.panel.render( 'fast' ).delegateEvents();
-
multipanel._recalcFirstColumnHeight();
return newCurrentColumn;
},
@@ -451,14 +437,14 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
// if it's the current column, create a new, empty history as the new current
if( column.model.id === this.currentHistoryId ){
-//TODO: figuring out the order of async here is tricky - for now let the user handle the two step process
+ //TODO: figuring out the order of async here is tricky
+ // - for now let the user handle the two step process
//multipanel.collection.create().done( function(){
// if( !multipanel.collection.includeDeleted ){ multipanel.removeColumn( column, false ); }
//});
} else if( !multipanel.collection.includeDeleted ){
multipanel.removeColumn( column );
}
-//TODO: prob. be done better
}
},
@@ -475,13 +461,12 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
//TODO: we can use a 2 arg version and return 1/0/-1
//this.collection.comparator = function( h1, h2 ){
this.collection.comparator = function( h ){
-//TODO: this won't do reverse order well
+ //TODO: this won't do reverse order well
return [ h.id !== currentHistoryId, h.get( 'name' ).toLowerCase() ];
};
break;
case 'size':
this.collection.comparator = function( h ){
-//console.debug( 'name sort', arguments )
return [ h.id !== currentHistoryId, h.get( 'size' ) ];
};
break;
@@ -501,6 +486,8 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
order = 'update';
}
this.order = order;
+ this.trigger( 'order:change', order, this );
+ this.$( '.current-order' ).text( order );
this.sortCollection();
return this;
},
@@ -533,6 +520,9 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return column;
},
+ /** return array of Columns filtered by filters and sorted to match the collection
+ * @param: filters Function[] array of filter fns
+ */
sortedFilteredColumns : function( filters ){
filters = filters || this.filters;
if( !filters || !filters.length ){
@@ -547,6 +537,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
});
},
+ /** return array of Columns sorted to match the collection */
sortedColumns : function(){
var multipanel = this;
var sorted = this.collection.map( function( history, index ){
@@ -555,9 +546,9 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return sorted;
},
- /** */
+ /** add a new column for history and render all columns if render is true */
addColumn : function add( history, render ){
-//console.debug( 'adding column for:', history );
+ //this.debug( 'adding column for:', history );
render = render !== undefined? render: true;
var newColumn = this.createColumn( history );
this.columnMap[ history.id ] = newColumn;
@@ -567,9 +558,9 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return newColumn;
},
- /** */
+ /** add a new column for history and make it the current history/column */
addAsCurrentColumn : function add( history ){
-//console.log( 'adding current column for:', history );
+ //this.log( 'adding current column for:', history );
var multipanel = this,
newColumn = this.addColumn( history, false );
this.setCurrentHistory( history );
@@ -579,7 +570,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return newColumn;
},
- /** */
+ /** remove the given column, it's listeners, and optionally render */
removeColumn : function remove( column, render ){
render = render !== undefined? render : true;
this.log( 'removeColumn', column );
@@ -657,79 +648,17 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var multipanel = this;
multipanel.log( multipanel + '.render' );
- multipanel.$el.html( multipanel.template( multipanel.options ) );
- //console.debug( multipanel.$( '.loading-overlay' ).fadeIn( 0 ) );
+ multipanel.$el.html( multipanel.mainTemplate( multipanel ) );
multipanel.renderColumns( speed );
- //console.debug( multipanel.$( '.loading-overlay' ).fadeOut( 'fast' ) );
// set the columns to full height allowed and set up behaviors for thie multipanel
multipanel.setUpBehaviors();
-//TODO: wrong - has to wait for columns to render
+ //TODO: wrong - has to wait for columns to render
+ // - create a column listener that fires this when all columns are rendered
multipanel.trigger( 'rendered', multipanel );
return multipanel;
},
- /** Template - overall structure relies on flex-boxes and is 3 components: header, middle, footer */
- template : function template( options ){
- options = options || {};
- var html = [];
- if( this.options.headerHeight ){
- html = html.concat([
- // a loading overlay
- '',
- '',
- // page & history controls
- '
',
- '
', _l( 'Done' ), ' ',
- '
',
- '
',
- '',
- _l( 'Order histories by' ) + '... ',
- ' ',
- '',
- '
',
- '',
- '
',
- // feedback
- '
',
- '',
- '
',
- // dataset controls
- '
',
- '',
- '',
- _l( 'Include deleted datasets' ),
- ' ',
- '',
- _l( 'Include hidden datasets' ),
- ' ',
- '
',
- '
'
- ]);
- }
-
- html = html.concat([
- // middle - where the columns go
- '',
- // footer
- '','
'
- ]);
- return $( html.join( '' ) );
- },
-
/** Render the columns and panels */
renderColumns : function renderColumns( speed ){
speed = speed !== undefined? speed: this.fxSpeed;
@@ -737,61 +666,21 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
// render columns and track the total number rendered, firing an event when all are rendered
var multipanel = this,
sortedAndFiltered = multipanel.sortedFilteredColumns();
-//console.log( '\t columnMapLength:', this.columnMapLength(), this.columnMap );
//this.log( '\t sortedAndFiltered:', sortedAndFiltered );
// set up width based on collection size
-//console.debug( '(render) width before:', multipanel.$( '.middle' ).width() )
multipanel.$( '.middle' ).width( sortedAndFiltered.length
//TODO: magic number 16 === the amount that safely prevents stacking of columns when adding a new one
* ( this.options.columnWidth + this.options.columnGap ) + this.options.columnGap + 16 );
-//console.debug( '(render) width now:', multipanel.$( '.middle' ).width() )
-
-//console.debug( 'sortedAndFiltered:', sortedAndFiltered )
- //multipanel.$( '.middle' ).empty();
-
-// this.$( '.middle' ).html( sortedAndFiltered.map( function( column, i ){
-// return column.$el.hide();
-// }));
-// sortedAndFiltered.forEach( function( column, i ){
-////console.debug( 'rendering:', column, i )
-// //multipanel.$( '.middle' ).append( column.$el.hide() );
-// column.delegateEvents();
-////TODO: current column in-view is never fired
-// multipanel.renderColumn( column, speed ).$el.show();
-// });
-
-// var $els = sortedAndFiltered.map( function( column, i ){
-////console.debug( 'rendering:', column, i )
-// multipanel.renderColumn( column, speed );
-// return column.$el;
-// });
-//// this breaks the event map
-// //this.$( '.middle' ).html( $els );
-//// this doesn't
-// this.$( '.middle' ).append( $els );
var $middle = multipanel.$( '.middle' );
$middle.empty();
sortedAndFiltered.forEach( function( column, i ){
-//console.debug( 'rendering:', column, i, column.panel )
-
column.$el.appendTo( $middle );
column.delegateEvents();
multipanel.renderColumn( column, speed );
-
- //column.$el.hide().appendTo( $middle );
- //multipanel.renderColumn( column, speed );
- // //.panel.on( 'all', function(){
- // // console.debug( 'column rendered:', arguments );
- // //});
- //// this won't work until we checkColumnsInView after the render
- ////column.$el.fadeIn( speed );
- //column.$el.show();
});
- //this.log( 'column rendering done' );
-
-//TODO: event columns-rendered
+ //TODO: event columns-rendered
if( this.searchFor && sortedAndFiltered.length <= 1 ){
} else {
@@ -808,15 +697,11 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
renderColumn : function( column, speed ){
speed = speed !== undefined? speed: this.fxSpeed;
return column.render( speed );
- //TODO: causes weirdness
- //return _.delay( function(){
- // return column.render( speed );
- //}, 0 );
},
-//TODO: combine the following two more sensibly
-//TODO: could have HistoryContents.haveDetails return false
-// if column.model.contents.length === 0 && !column.model.get( 'empty' ) then just check that
+ //TODO: combine the following two more sensibly
+ //TODO: could have HistoryContents.haveDetails return false
+ // if column.model.contents.length === 0 && !column.model.get( 'empty' ) then just check that
/** Get the *summary* contents of a column's history (and details on any expanded contents),
* queueing the ajax call and using a named queue to prevent the call being sent twice
*/
@@ -874,14 +759,17 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
events : {
// will move to the server root (gen. Analyze data)
'click .done.btn' : 'close',
- //TODO:?? could just go back - but that's not always correct/desired behav.
- //'click .done.btn' : function(){ window.history.back(); },
// creates a new empty history and makes it current
'click .create-new.btn' : 'create',
+
+ 'click #include-deleted' : '_clickToggleDeletedHistories',
// these change the collection and column sort order
'click .order .order-update' : function( e ){ this.setOrder( 'update' ); },
'click .order .order-name' : function( e ){ this.setOrder( 'name' ); },
- 'click .order .order-size' : function( e ){ this.setOrder( 'size' ); }
+ 'click .order .order-size' : function( e ){ this.setOrder( 'size' ); },
+
+ 'click #toggle-deleted' : '_clickToggleDeletedDatasets',
+ 'click #toggle-hidden' : '_clickToggleHiddenDatasets'
//'dragstart .list-item .title-bar' : function( e ){ console.debug( 'ok' ); }
},
@@ -897,37 +785,48 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
window.location = destination;
},
+ _clickToggleDeletedHistories : function( ev ){
+ return this.toggleDeletedHistories( $( ev.currentTarget ).is( ':checked' ) );
+ },
/** Include deleted histories in the collection */
- includeDeletedHistories : function(){
- //TODO: better through API/limit+offset
- window.location += ( /\?/.test( window.location.toString() ) )?( '&' ):( '?' )
- + 'include_deleted_histories=True';
+ toggleDeletedHistories : function( show ){
+ if( show ){
+ window.location = Galaxy.options.root + 'history/view_multiple?include_deleted_histories=True';
+ } else {
+ window.location = Galaxy.options.root + 'history/view_multiple';
+ }
},
- /** Show only non-deleted histories */
- excludeDeletedHistories : function(){
- //TODO: better through API/limit+offset
- window.location = window.location.toString().replace( /[&\?]include_deleted_histories=True/g, '' );
+ _clickToggleDeletedDatasets : function( ev ){
+ return this.toggleDeletedDatasets( $( ev.currentTarget ).is( ':checked' ) );
+ },
+ toggleDeletedDatasets : function( show ){
+ show = show !== undefined? show : false;
+ var multipanel = this;
+ multipanel.sortedFilteredColumns().forEach( function( column, i ){
+ _.delay( function(){
+ column.panel.toggleShowDeleted( show, false );
+ }, i * 200 );
+ });
+ },
+
+ _clickToggleHiddenDatasets : function( ev ){
+ return this.toggleHiddenDatasets( $( ev.currentTarget ).is( ':checked' ) );
+ },
+ toggleHiddenDatasets : function( show ){
+ show = show !== undefined? show : false;
+ var multipanel = this;
+ multipanel.sortedFilteredColumns().forEach( function( column, i ){
+ _.delay( function(){
+ column.panel.toggleShowHidden( show, false );
+ }, i * 200 );
+ });
},
/** Set up any view plugins */
setUpBehaviors : function(){
var multipanel = this;
-
-//TODO: currently doesn't need to be a mode button
- // toggle button for include deleted
- multipanel.$( '.include-deleted' ).modeButton({
- initialMode : this.collection.includeDeleted? 'exclude' : 'include',
- switchModesOnClick : false,
- modes: [
- { mode: 'include', html: _l( 'Include deleted histories' ),
- onclick: _.bind( multipanel.includeDeletedHistories, multipanel )
- },
- { mode: 'exclude', html: _l( 'Exclude deleted histories' ),
- onclick: _.bind( multipanel.excludeDeletedHistories, multipanel )
- }
- ]
- });
+ multipanel._moreOptionsPopover();
// input to search histories
multipanel.$( '#search-histories' ).searchInput({
@@ -942,7 +841,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
},
onclear : function( searchFor ){
multipanel.searchFor = null;
-//TODO: remove specifically not just reset
+ //TODO: remove specifically not just reset
multipanel.filters = [];
multipanel.renderColumns( 0 );
}
@@ -986,53 +885,25 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
}
});
-//TODO: each panel stores the hidden/deleted state - and that isn't reflected in the buttons
- // toggle button for showing deleted history contents
- multipanel.$( '#toggle-deleted' ).modeButton({
- initialMode : 'include',
- modes: [
- { mode: 'exclude', html: _l( 'Exclude deleted datasets' ) },
- { mode: 'include', html: _l( 'Include deleted datasets' ) }
- ]
- }).click( function(){
- var show = $( this ).modeButton( 'getMode' ).mode === 'exclude';
- multipanel.sortedFilteredColumns().forEach( function( column, i ){
- _.delay( function(){
- column.panel.toggleShowDeleted( show, false );
- }, i * 200 );
- });
- });
-
- // toggle button for showing hidden history contents
- multipanel.$( '#toggle-hidden' ).modeButton({
- initialMode : 'include',
- modes: [
- { mode: 'exclude', html: _l( 'Exclude hidden datasets' ) },
- { mode: 'include', html: _l( 'Include hidden datasets' ) }
- ]
- }).click( function(){
- var show = $( this ).modeButton( 'getMode' ).mode === 'exclude';
- multipanel.sortedFilteredColumns().forEach( function( column, i ){
- _.delay( function(){
- column.panel.toggleShowHidden( show, false );
- }, i * 200 );
- });
- });
-
// resize first (fixed position) column on page resize
$( window ).resize( function(){
multipanel._recalcFirstColumnHeight();
});
// when scrolling - check for histories now in view: they will fire 'in-view' and queueHdaLoading if necc.
-//TODO:?? might be able to simplify and not use pub-sub
+ //TODO:?? might be able to simplify and not use pub-sub
var debouncedInView = _.debounce( _.bind( this.checkColumnsInView, this ), 100 );
this.$( '.middle' ).parent().scroll( debouncedInView );
},
- ///** Put the in-view columns then the other columns in a queue, rendering each one at a time */
- //panelRenderQueue : function( columns, fn, args, renderEventName ){
- //},
+ _moreOptionsPopover : function(){
+ return this.$( '.open-more-options.btn' ).popover({
+ container : '.header',
+ placement : 'bottom',
+ html : true,
+ content : $( this.optionsPopoverTemplate( this ) )
+ });
+ },
/** Adjust the height of the first, current column since flex-boxes won't work with fixed postiion elements */
_recalcFirstColumnHeight : function(){
@@ -1052,18 +923,17 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
/** returns the columns currently in the viewport */
columnsInView : function(){
//TODO: uses offset which is render intensive
-//TODO: 2N - could use arg filter (sortedFilteredColumns( filter )) instead
+ //TODO: 2N - could use arg filter (sortedFilteredColumns( filter )) instead
var vp = this._viewport();
return this.sortedFilteredColumns().filter( function( column ){
return column.currentHistory || column.inView( vp.left, vp.right );
});
},
-//TODO: sortByInView - return cols in view, then others
+ //TODO: sortByInView - return cols in view, then others
/** trigger in-view from columns in-view */
checkColumnsInView : function(){
-//TODO: assbackward
-//console.debug( 'checking columns in view', this.columnsInView() );
+ //TODO: assbackward - don't fire from the column, fire from here and listen from here
this.columnsInView().forEach( function( column ){
column.trigger( 'in-view', column );
});
@@ -1073,7 +943,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
currentColumnDropTargetOn : function(){
var currentColumn = this.columnMap[ this.currentHistoryId ];
if( !currentColumn ){ return; }
-//TODO: fix this - shouldn't need monkeypatch
+ //TODO: fix this - shouldn't need monkeypatch
currentColumn.panel.dataDropped = function( data ){};
currentColumn.panel.dropTargetOn();
},
@@ -1090,7 +960,73 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
/** String rep */
toString : function(){
return 'MultiPanelColumns(' + ( this.columns? this.columns.length : 0 ) + ')';
- }
+ },
+
+ // ------------------------------------------------------------------------ templates
+ mainTemplate : _.template([
+ '',
+ '
',
+ '
', _l( 'Create new' ), ' ',
+ '
',
+ '
',
+ '
',
+ //TODO: tip not working
+ ' ',
+ ' ',
+ '
',
+ // feedback
+ '
',
+ '',
+ '
',
+ '
',
+ '', _l( 'Done' ), ' ',
+ '
',
+ '
',
+ // middle - where the columns go
+ '',
+ // footer
+ '',
+ '
'
+ ].join(''), { variable: 'view' }),
+
+ optionsPopoverTemplate : _.template([
+ '',
+ '
>',
+ _l( 'Include deleted histories' ),
+ '
',
+
+ '
',
+ '',
+ _l( 'Order histories by' ) + ' ',
+ '<%= view.order %> ',
+ ' ',
+ ' ',
+ '',
+ '
',
+
+ '
',
+ _l( 'Include deleted datasets' ),
+ '
',
+ '
',
+ _l( 'Include hidden datasets' ),
+ '
',
+ '
'
+ ].join(''), { variable: 'view' }),
+
});
diff --git a/static/scripts/mvc/history/multi-panel.js b/static/scripts/mvc/history/multi-panel.js
index 7d8a8aae928..e8ffff203c9 100644
--- a/static/scripts/mvc/history/multi-panel.js
+++ b/static/scripts/mvc/history/multi-panel.js
@@ -6,7 +6,6 @@ define([
"ui/mode-button",
"ui/search-input"
], function( HISTORY_MODEL, HPANEL_EDIT, baseMVC, ajaxQueue ){
-window.HISTORY_MODEL = HISTORY_MODEL;
//==============================================================================
/** */
function historyCopyDialog( history, options ){
@@ -265,7 +264,7 @@ var HistoryPanelColumn = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return ( this.currentHistory )?
[
'',
- '', _l( 'Create new' ), ' ',
+ '', _l( 'Current History' ), ' ',
'
'
].join( '' )
:[
@@ -328,6 +327,7 @@ var HistoryPanelColumn = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
//logger : console,
+ className : 'multi-history-columns',
// ------------------------------------------------------------------------ set up
/** Set up internals, history collection, and columns to display the history */
@@ -366,9 +366,8 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
/** model id to column map */
this.columnMap = {};
-//TODO: why create here?
+ //TODO: why create here?
this.createColumns( options.columnOptions );
-
this.setUpListeners();
},
@@ -386,10 +385,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var multipanel = this;
multipanel.stopListening( multipanel.collection );
multipanel.collection = models;
-//TODO: slow... esp. on start up
- //if( multipanel.order !== 'update' ){
- multipanel.sortCollection( multipanel.order, { silent: true });
- //}
+ multipanel.sortCollection( multipanel.order, { silent: true });
multipanel.setUpCollectionListeners();
multipanel.trigger( 'new-collection', multipanel );
return multipanel;
@@ -408,11 +404,6 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
'change:deleted': multipanel.handleDeletedHistory,
'sort' : function(){ multipanel.renderColumns( 0 ); }
-
- // debugging
- //'all' : function(){
- // console.info( 'collection:', arguments );
- //}
});
},
@@ -430,11 +421,6 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
this.sortCollection();
-////TODO: this actually means these render twice (1st from setCollection) - good enough for now
- //if( oldCurrentColumn ){ oldCurrentColumn.render().delegateEvents(); }
- //TODO:?? this occasionally causes race with hdaQueue
- //newCurrentColumn.panel.render( 'fast' ).delegateEvents();
-
multipanel._recalcFirstColumnHeight();
return newCurrentColumn;
},
@@ -451,14 +437,14 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
// if it's the current column, create a new, empty history as the new current
if( column.model.id === this.currentHistoryId ){
-//TODO: figuring out the order of async here is tricky - for now let the user handle the two step process
+ //TODO: figuring out the order of async here is tricky
+ // - for now let the user handle the two step process
//multipanel.collection.create().done( function(){
// if( !multipanel.collection.includeDeleted ){ multipanel.removeColumn( column, false ); }
//});
} else if( !multipanel.collection.includeDeleted ){
multipanel.removeColumn( column );
}
-//TODO: prob. be done better
}
},
@@ -475,13 +461,12 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
//TODO: we can use a 2 arg version and return 1/0/-1
//this.collection.comparator = function( h1, h2 ){
this.collection.comparator = function( h ){
-//TODO: this won't do reverse order well
+ //TODO: this won't do reverse order well
return [ h.id !== currentHistoryId, h.get( 'name' ).toLowerCase() ];
};
break;
case 'size':
this.collection.comparator = function( h ){
-//console.debug( 'name sort', arguments )
return [ h.id !== currentHistoryId, h.get( 'size' ) ];
};
break;
@@ -501,6 +486,8 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
order = 'update';
}
this.order = order;
+ this.trigger( 'order:change', order, this );
+ this.$( '.current-order' ).text( order );
this.sortCollection();
return this;
},
@@ -533,6 +520,9 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return column;
},
+ /** return array of Columns filtered by filters and sorted to match the collection
+ * @param: filters Function[] array of filter fns
+ */
sortedFilteredColumns : function( filters ){
filters = filters || this.filters;
if( !filters || !filters.length ){
@@ -547,6 +537,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
});
},
+ /** return array of Columns sorted to match the collection */
sortedColumns : function(){
var multipanel = this;
var sorted = this.collection.map( function( history, index ){
@@ -555,9 +546,9 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return sorted;
},
- /** */
+ /** add a new column for history and render all columns if render is true */
addColumn : function add( history, render ){
-//console.debug( 'adding column for:', history );
+ //this.debug( 'adding column for:', history );
render = render !== undefined? render: true;
var newColumn = this.createColumn( history );
this.columnMap[ history.id ] = newColumn;
@@ -567,9 +558,9 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return newColumn;
},
- /** */
+ /** add a new column for history and make it the current history/column */
addAsCurrentColumn : function add( history ){
-//console.log( 'adding current column for:', history );
+ //this.log( 'adding current column for:', history );
var multipanel = this,
newColumn = this.addColumn( history, false );
this.setCurrentHistory( history );
@@ -579,7 +570,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
return newColumn;
},
- /** */
+ /** remove the given column, it's listeners, and optionally render */
removeColumn : function remove( column, render ){
render = render !== undefined? render : true;
this.log( 'removeColumn', column );
@@ -657,79 +648,17 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var multipanel = this;
multipanel.log( multipanel + '.render' );
- multipanel.$el.html( multipanel.template( multipanel.options ) );
- //console.debug( multipanel.$( '.loading-overlay' ).fadeIn( 0 ) );
+ multipanel.$el.html( multipanel.mainTemplate( multipanel ) );
multipanel.renderColumns( speed );
- //console.debug( multipanel.$( '.loading-overlay' ).fadeOut( 'fast' ) );
// set the columns to full height allowed and set up behaviors for thie multipanel
multipanel.setUpBehaviors();
-//TODO: wrong - has to wait for columns to render
+ //TODO: wrong - has to wait for columns to render
+ // - create a column listener that fires this when all columns are rendered
multipanel.trigger( 'rendered', multipanel );
return multipanel;
},
- /** Template - overall structure relies on flex-boxes and is 3 components: header, middle, footer */
- template : function template( options ){
- options = options || {};
- var html = [];
- if( this.options.headerHeight ){
- html = html.concat([
- // a loading overlay
- '',
- '',
- // page & history controls
- '
',
- '
', _l( 'Done' ), ' ',
- '
',
- '
',
- '',
- _l( 'Order histories by' ) + '... ',
- ' ',
- '',
- '
',
- '',
- '
',
- // feedback
- '
',
- '',
- '
',
- // dataset controls
- '
',
- '',
- '',
- _l( 'Include deleted datasets' ),
- ' ',
- '',
- _l( 'Include hidden datasets' ),
- ' ',
- '
',
- '
'
- ]);
- }
-
- html = html.concat([
- // middle - where the columns go
- '',
- // footer
- '','
'
- ]);
- return $( html.join( '' ) );
- },
-
/** Render the columns and panels */
renderColumns : function renderColumns( speed ){
speed = speed !== undefined? speed: this.fxSpeed;
@@ -737,61 +666,21 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
// render columns and track the total number rendered, firing an event when all are rendered
var multipanel = this,
sortedAndFiltered = multipanel.sortedFilteredColumns();
-//console.log( '\t columnMapLength:', this.columnMapLength(), this.columnMap );
//this.log( '\t sortedAndFiltered:', sortedAndFiltered );
// set up width based on collection size
-//console.debug( '(render) width before:', multipanel.$( '.middle' ).width() )
multipanel.$( '.middle' ).width( sortedAndFiltered.length
//TODO: magic number 16 === the amount that safely prevents stacking of columns when adding a new one
* ( this.options.columnWidth + this.options.columnGap ) + this.options.columnGap + 16 );
-//console.debug( '(render) width now:', multipanel.$( '.middle' ).width() )
-
-//console.debug( 'sortedAndFiltered:', sortedAndFiltered )
- //multipanel.$( '.middle' ).empty();
-
-// this.$( '.middle' ).html( sortedAndFiltered.map( function( column, i ){
-// return column.$el.hide();
-// }));
-// sortedAndFiltered.forEach( function( column, i ){
-////console.debug( 'rendering:', column, i )
-// //multipanel.$( '.middle' ).append( column.$el.hide() );
-// column.delegateEvents();
-////TODO: current column in-view is never fired
-// multipanel.renderColumn( column, speed ).$el.show();
-// });
-
-// var $els = sortedAndFiltered.map( function( column, i ){
-////console.debug( 'rendering:', column, i )
-// multipanel.renderColumn( column, speed );
-// return column.$el;
-// });
-//// this breaks the event map
-// //this.$( '.middle' ).html( $els );
-//// this doesn't
-// this.$( '.middle' ).append( $els );
var $middle = multipanel.$( '.middle' );
$middle.empty();
sortedAndFiltered.forEach( function( column, i ){
-//console.debug( 'rendering:', column, i, column.panel )
-
column.$el.appendTo( $middle );
column.delegateEvents();
multipanel.renderColumn( column, speed );
-
- //column.$el.hide().appendTo( $middle );
- //multipanel.renderColumn( column, speed );
- // //.panel.on( 'all', function(){
- // // console.debug( 'column rendered:', arguments );
- // //});
- //// this won't work until we checkColumnsInView after the render
- ////column.$el.fadeIn( speed );
- //column.$el.show();
});
- //this.log( 'column rendering done' );
-
-//TODO: event columns-rendered
+ //TODO: event columns-rendered
if( this.searchFor && sortedAndFiltered.length <= 1 ){
} else {
@@ -808,15 +697,11 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
renderColumn : function( column, speed ){
speed = speed !== undefined? speed: this.fxSpeed;
return column.render( speed );
- //TODO: causes weirdness
- //return _.delay( function(){
- // return column.render( speed );
- //}, 0 );
},
-//TODO: combine the following two more sensibly
-//TODO: could have HistoryContents.haveDetails return false
-// if column.model.contents.length === 0 && !column.model.get( 'empty' ) then just check that
+ //TODO: combine the following two more sensibly
+ //TODO: could have HistoryContents.haveDetails return false
+ // if column.model.contents.length === 0 && !column.model.get( 'empty' ) then just check that
/** Get the *summary* contents of a column's history (and details on any expanded contents),
* queueing the ajax call and using a named queue to prevent the call being sent twice
*/
@@ -874,14 +759,17 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
events : {
// will move to the server root (gen. Analyze data)
'click .done.btn' : 'close',
- //TODO:?? could just go back - but that's not always correct/desired behav.
- //'click .done.btn' : function(){ window.history.back(); },
// creates a new empty history and makes it current
'click .create-new.btn' : 'create',
+
+ 'click #include-deleted' : '_clickToggleDeletedHistories',
// these change the collection and column sort order
'click .order .order-update' : function( e ){ this.setOrder( 'update' ); },
'click .order .order-name' : function( e ){ this.setOrder( 'name' ); },
- 'click .order .order-size' : function( e ){ this.setOrder( 'size' ); }
+ 'click .order .order-size' : function( e ){ this.setOrder( 'size' ); },
+
+ 'click #toggle-deleted' : '_clickToggleDeletedDatasets',
+ 'click #toggle-hidden' : '_clickToggleHiddenDatasets'
//'dragstart .list-item .title-bar' : function( e ){ console.debug( 'ok' ); }
},
@@ -897,37 +785,48 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
window.location = destination;
},
+ _clickToggleDeletedHistories : function( ev ){
+ return this.toggleDeletedHistories( $( ev.currentTarget ).is( ':checked' ) );
+ },
/** Include deleted histories in the collection */
- includeDeletedHistories : function(){
- //TODO: better through API/limit+offset
- window.location += ( /\?/.test( window.location.toString() ) )?( '&' ):( '?' )
- + 'include_deleted_histories=True';
+ toggleDeletedHistories : function( show ){
+ if( show ){
+ window.location = Galaxy.options.root + 'history/view_multiple?include_deleted_histories=True';
+ } else {
+ window.location = Galaxy.options.root + 'history/view_multiple';
+ }
},
- /** Show only non-deleted histories */
- excludeDeletedHistories : function(){
- //TODO: better through API/limit+offset
- window.location = window.location.toString().replace( /[&\?]include_deleted_histories=True/g, '' );
+ _clickToggleDeletedDatasets : function( ev ){
+ return this.toggleDeletedDatasets( $( ev.currentTarget ).is( ':checked' ) );
+ },
+ toggleDeletedDatasets : function( show ){
+ show = show !== undefined? show : false;
+ var multipanel = this;
+ multipanel.sortedFilteredColumns().forEach( function( column, i ){
+ _.delay( function(){
+ column.panel.toggleShowDeleted( show, false );
+ }, i * 200 );
+ });
+ },
+
+ _clickToggleHiddenDatasets : function( ev ){
+ return this.toggleHiddenDatasets( $( ev.currentTarget ).is( ':checked' ) );
+ },
+ toggleHiddenDatasets : function( show ){
+ show = show !== undefined? show : false;
+ var multipanel = this;
+ multipanel.sortedFilteredColumns().forEach( function( column, i ){
+ _.delay( function(){
+ column.panel.toggleShowHidden( show, false );
+ }, i * 200 );
+ });
},
/** Set up any view plugins */
setUpBehaviors : function(){
var multipanel = this;
-
-//TODO: currently doesn't need to be a mode button
- // toggle button for include deleted
- multipanel.$( '.include-deleted' ).modeButton({
- initialMode : this.collection.includeDeleted? 'exclude' : 'include',
- switchModesOnClick : false,
- modes: [
- { mode: 'include', html: _l( 'Include deleted histories' ),
- onclick: _.bind( multipanel.includeDeletedHistories, multipanel )
- },
- { mode: 'exclude', html: _l( 'Exclude deleted histories' ),
- onclick: _.bind( multipanel.excludeDeletedHistories, multipanel )
- }
- ]
- });
+ multipanel._moreOptionsPopover();
// input to search histories
multipanel.$( '#search-histories' ).searchInput({
@@ -942,7 +841,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
},
onclear : function( searchFor ){
multipanel.searchFor = null;
-//TODO: remove specifically not just reset
+ //TODO: remove specifically not just reset
multipanel.filters = [];
multipanel.renderColumns( 0 );
}
@@ -986,53 +885,25 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
}
});
-//TODO: each panel stores the hidden/deleted state - and that isn't reflected in the buttons
- // toggle button for showing deleted history contents
- multipanel.$( '#toggle-deleted' ).modeButton({
- initialMode : 'include',
- modes: [
- { mode: 'exclude', html: _l( 'Exclude deleted datasets' ) },
- { mode: 'include', html: _l( 'Include deleted datasets' ) }
- ]
- }).click( function(){
- var show = $( this ).modeButton( 'getMode' ).mode === 'exclude';
- multipanel.sortedFilteredColumns().forEach( function( column, i ){
- _.delay( function(){
- column.panel.toggleShowDeleted( show, false );
- }, i * 200 );
- });
- });
-
- // toggle button for showing hidden history contents
- multipanel.$( '#toggle-hidden' ).modeButton({
- initialMode : 'include',
- modes: [
- { mode: 'exclude', html: _l( 'Exclude hidden datasets' ) },
- { mode: 'include', html: _l( 'Include hidden datasets' ) }
- ]
- }).click( function(){
- var show = $( this ).modeButton( 'getMode' ).mode === 'exclude';
- multipanel.sortedFilteredColumns().forEach( function( column, i ){
- _.delay( function(){
- column.panel.toggleShowHidden( show, false );
- }, i * 200 );
- });
- });
-
// resize first (fixed position) column on page resize
$( window ).resize( function(){
multipanel._recalcFirstColumnHeight();
});
// when scrolling - check for histories now in view: they will fire 'in-view' and queueHdaLoading if necc.
-//TODO:?? might be able to simplify and not use pub-sub
+ //TODO:?? might be able to simplify and not use pub-sub
var debouncedInView = _.debounce( _.bind( this.checkColumnsInView, this ), 100 );
this.$( '.middle' ).parent().scroll( debouncedInView );
},
- ///** Put the in-view columns then the other columns in a queue, rendering each one at a time */
- //panelRenderQueue : function( columns, fn, args, renderEventName ){
- //},
+ _moreOptionsPopover : function(){
+ return this.$( '.open-more-options.btn' ).popover({
+ container : '.header',
+ placement : 'bottom',
+ html : true,
+ content : $( this.optionsPopoverTemplate( this ) )
+ });
+ },
/** Adjust the height of the first, current column since flex-boxes won't work with fixed postiion elements */
_recalcFirstColumnHeight : function(){
@@ -1052,18 +923,17 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
/** returns the columns currently in the viewport */
columnsInView : function(){
//TODO: uses offset which is render intensive
-//TODO: 2N - could use arg filter (sortedFilteredColumns( filter )) instead
+ //TODO: 2N - could use arg filter (sortedFilteredColumns( filter )) instead
var vp = this._viewport();
return this.sortedFilteredColumns().filter( function( column ){
return column.currentHistory || column.inView( vp.left, vp.right );
});
},
-//TODO: sortByInView - return cols in view, then others
+ //TODO: sortByInView - return cols in view, then others
/** trigger in-view from columns in-view */
checkColumnsInView : function(){
-//TODO: assbackward
-//console.debug( 'checking columns in view', this.columnsInView() );
+ //TODO: assbackward - don't fire from the column, fire from here and listen from here
this.columnsInView().forEach( function( column ){
column.trigger( 'in-view', column );
});
@@ -1073,7 +943,7 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
currentColumnDropTargetOn : function(){
var currentColumn = this.columnMap[ this.currentHistoryId ];
if( !currentColumn ){ return; }
-//TODO: fix this - shouldn't need monkeypatch
+ //TODO: fix this - shouldn't need monkeypatch
currentColumn.panel.dataDropped = function( data ){};
currentColumn.panel.dropTargetOn();
},
@@ -1090,7 +960,73 @@ var MultiPanelColumns = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
/** String rep */
toString : function(){
return 'MultiPanelColumns(' + ( this.columns? this.columns.length : 0 ) + ')';
- }
+ },
+
+ // ------------------------------------------------------------------------ templates
+ mainTemplate : _.template([
+ '',
+ '
',
+ '
', _l( 'Create new' ), ' ',
+ '
',
+ '
',
+ '
',
+ //TODO: tip not working
+ ' ',
+ ' ',
+ '
',
+ // feedback
+ '
',
+ '',
+ '
',
+ '
',
+ '', _l( 'Done' ), ' ',
+ '
',
+ '
',
+ // middle - where the columns go
+ '',
+ // footer
+ '',
+ '
'
+ ].join(''), { variable: 'view' }),
+
+ optionsPopoverTemplate : _.template([
+ '',
+ '
>',
+ _l( 'Include deleted histories' ),
+ '
',
+
+ '
',
+ '',
+ _l( 'Order histories by' ) + ' ',
+ '<%= view.order %> ',
+ ' ',
+ ' ',
+ '',
+ '
',
+
+ '
',
+ _l( 'Include deleted datasets' ),
+ '
',
+ '
',
+ _l( 'Include hidden datasets' ),
+ '
',
+ '
'
+ ].join(''), { variable: 'view' }),
+
});
diff --git a/static/scripts/packed/mvc/history/multi-panel.js b/static/scripts/packed/mvc/history/multi-panel.js
index a421bace670..8f62c6aa681 100644
--- a/static/scripts/packed/mvc/history/multi-panel.js
+++ b/static/scripts/packed/mvc/history/multi-panel.js
@@ -1 +1 @@
-define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/base-mvc","utils/ajax-queue","ui/mode-button","ui/search-input"],function(d,l,z,a){window.HISTORY_MODEL=d;function g(I,E){E=E||{};if(!(Galaxy&&Galaxy.modal)){return I.copy()}var F=I.get("name"),C="Copy of '"+F+"'";function D(K){if(!K){if(!Galaxy.modal.$("#invalid-title").size()){var J=$("
").attr("id","invalid-title").css({color:"red","margin-top":"8px"}).addClass("bg-danger").text(_l("Please enter a valid history title"));Galaxy.modal.$(".modal-body").append(J)}return false}return K}function G(J){var K=$(' Copying history...
').css("margin-top","8px");Galaxy.modal.$(".modal-body").append(K);I.copy(true,J).fail(function(){alert(_l("History could not be copied. Please contact a Galaxy administrator"))}).always(function(){Galaxy.modal.hide()})}function H(){var J=Galaxy.modal.$("#copy-modal-title").val();if(!D(J)){return}G(J)}Galaxy.modal.show(_.extend({title:_l("Copying history")+' "'+F+'"',body:$(['',_l("Enter a title for the copied history"),":"," ",' '].join("")),buttons:{Cancel:function(){Galaxy.modal.hide()},Copy:H}},E));$("#copy-modal-title").focus().select();$("#copy-modal-title").on("keydown",function(J){if(J.keyCode===13){H()}})}var B=Backbone.View.extend(z.LoggableMixin).extend({tagName:"div",className:"history-column flex-column flex-row-container",id:function q(){if(!this.model){return""}return"history-column-"+this.model.get("id")},initialize:function c(C){C=C||{};this.panel=C.panel||this.createPanel(C);this.setUpListeners()},createPanel:function u(D){D=_.extend({model:this.model,dragItems:true},D);var C=new l.HistoryPanelEdit(D);C._renderEmptyMessage=this.__patch_renderEmptyMessage;return C},__patch_renderEmptyMessage:function(E){var D=this,F=_.chain(this.model.get("state_ids")).values().flatten().value().length,C=D.$emptyMessage(E);if(!_.isEmpty(D.hdaViews)){C.hide()}else{if(F&&!this.model.contents.length){C.empty().append($(' loading datasets... ')).show()}else{if(D.searchFor){C.text(D.noneFoundMsg).show()}else{C.text(D.emptyMsg).show()}}}return C},setUpListeners:function f(){var C=this;this.once("rendered",function(){C.trigger("rendered:initial",C)});this.setUpPanelListeners()},setUpPanelListeners:function k(){var C=this;this.listenTo(this.panel,{rendered:function(){C.trigger("rendered",C)}},this)},inView:function(C,D){var F=this.$el.offset().left,E=F+this.$el.width();if(ED){return false}return true},$panel:function e(){return this.$(".history-panel")},render:function A(D){D=(D!==undefined)?(D):("fast");var C=this.model?this.model.toJSON():{};this.$el.html(this.template(C));this.renderPanel(D);this.setUpBehaviors();return this},setUpBehaviors:function v(){},template:function w(D){D=D||{};var C=['',this.controlsLeftTemplate(),'
','',D.deleted?_l("Undelete"):_l("Delete")," ",'',_l("Copy")," ","
","
",'"].join("");return $(C)},controlsLeftTemplate:function(){return(this.currentHistory)?['','',_l("Create new")," ","
"].join(""):['','',_l("Switch to")," ","
"].join("")},renderPanel:function h(C){C=(C!==undefined)?(C):("fast");this.panel.setElement(this.$panel()).render(C);return this},events:{"click .switch-to.btn":function(){this.model.setAsCurrent()},"click .delete-history.btn":function(){var C=this,D;if(this.model.get("deleted")){D=this.model.undelete()}else{D=this.model._delete()}D.fail(function(G,E,F){alert(_l("Could not delete the history")+":\n"+F)}).done(function(E){C.render()})},"click .copy-history.btn":"copy"},copy:function s(){g(this.model)},toString:function(){return"HistoryPanelColumn("+(this.panel?this.panel:"")+")"}});var m=Backbone.View.extend(z.LoggableMixin).extend({initialize:function c(C){C=C||{};this.log(this+".init",C);if(!C.currentHistoryId){throw new Error(this+" requires a currentHistoryId in the options")}this.currentHistoryId=C.currentHistoryId;this.options={columnWidth:312,borderWidth:1,columnGap:8,headerHeight:29,footerHeight:0,controlsHeight:20};this.order=C.order||"update";this.hdaQueue=new a.NamedAjaxQueue([],false);this.collection=null;this.setCollection(C.histories||[]);this.columnMap={};this.createColumns(C.columnOptions);this.setUpListeners()},setUpListeners:function f(){},setCollection:function y(D){var C=this;C.stopListening(C.collection);C.collection=D;C.sortCollection(C.order,{silent:true});C.setUpCollectionListeners();C.trigger("new-collection",C);return C},setUpCollectionListeners:function(){var C=this,D=C.collection;C.listenTo(D,{add:C.addAsCurrentColumn,"set-as-current":C.setCurrentHistory,"change:deleted":C.handleDeletedHistory,sort:function(){C.renderColumns(0)}})},setCurrentHistory:function p(D){var C=this.columnMap[this.currentHistoryId];if(C){C.currentHistory=false;C.$el.height("")}this.currentHistoryId=D.id;var E=this.columnMap[this.currentHistoryId];E.currentHistory=true;this.sortCollection();multipanel._recalcFirstColumnHeight();return E},handleDeletedHistory:function b(D){if(D.get("deleted")){this.log("handleDeletedHistory",this.collection.includeDeleted,D);var C=this;column=C.columnMap[D.id];if(!column){return}if(column.model.id===this.currentHistoryId){}else{if(!C.collection.includeDeleted){C.removeColumn(column)}}}},sortCollection:function(C,D){C=C||this.order;var E=this.currentHistoryId;switch(C){case"name":this.collection.comparator=function(F){return[F.id!==E,F.get("name").toLowerCase()]};break;case"size":this.collection.comparator=function(F){return[F.id!==E,F.get("size")]};break;default:this.collection.comparator=function(F){return[F.id!==E,Date(F.get("update_time"))]}}this.collection.sort(D);return this.collection},setOrder:function(C){if(["update","name","size"].indexOf(C)===-1){C="update"}this.order=C;this.sortCollection();return this},create:function(C){return this.collection.create({current:true})},createColumns:function r(D){D=D||{};var C=this;this.columnMap={};C.collection.each(function(E,F){var G=C.createColumn(E,D);C.columnMap[E.id]=G})},createColumn:function t(E,C){C=_.extend({},C,{model:E});var D=new B(C);if(E.id===this.currentHistoryId){D.currentHistory=true}this.setUpColumnListeners(D);return D},sortedFilteredColumns:function(C){C=C||this.filters;if(!C||!C.length){return this.sortedColumns()}var D=this;return D.sortedColumns().filter(function(G,F){var E=G.currentHistory||_.every(C.map(function(H){return H.call(G)}));return E})},sortedColumns:function(){var D=this;var C=this.collection.map(function(F,E){return D.columnMap[F.id]});return C},addColumn:function o(E,C){C=C!==undefined?C:true;var D=this.createColumn(E);this.columnMap[E.id]=D;if(C){this.renderColumns()}return D},addAsCurrentColumn:function o(E){var D=this,C=this.addColumn(E,false);this.setCurrentHistory(E);C.once("rendered",function(){D.queueHdaFetch(C)});return C},removeColumn:function x(E,D){D=D!==undefined?D:true;this.log("removeColumn",E);if(!E){return}var F=this,C=this.options.columnWidth+this.options.columnGap;E.$el.fadeOut("fast",function(){if(D){$(this).remove();F.$(".middle").width(F.$(".middle").width()-C);F.checkColumnsInView();F._recalcFirstColumnHeight()}F.stopListening(E.panel);F.stopListening(E);delete F.columnMap[E.model.id];E.remove()})},setUpColumnListeners:function n(C){var D=this;D.listenTo(C,{"in-view":D.queueHdaFetch});D.listenTo(C.panel,{"view:draggable:dragstart":function(H,F,E,G){D._dropData=JSON.parse(H.dataTransfer.getData("text"));D.currentColumnDropTargetOn()},"view:draggable:dragend":function(H,F,E,G){D._dropData=null;D.currentColumnDropTargetOff()},"droptarget:drop":function(G,H,F){var I=D._dropData.filter(function(J){return(_.isObject(J)&&J.id&&J.model_class==="HistoryDatasetAssociation")});D._dropData=null;var E=new a.NamedAjaxQueue();I.forEach(function(J){E.add({name:"copy-"+J.id,fn:function(){return F.model.contents.copy(J.id)}})});E.start();E.done(function(J){F.model.fetch()})}})},columnMapLength:function(){return Object.keys(this.columnMap).length},render:function A(D){D=D!==undefined?D:this.fxSpeed;var C=this;C.log(C+".render");C.$el.html(C.template(C.options));C.renderColumns(D);C.setUpBehaviors();C.trigger("rendered",C);return C},template:function w(C){C=C||{};var D=[];if(this.options.headerHeight){D=D.concat(['','','
','
',_l("Done")," ",'
','
','',_l("Order histories by")+'... '," ",'","
",'',"
",'
','","
",'
','','',_l("Include deleted datasets")," ",'',_l("Include hidden datasets")," ","
","
"])}D=D.concat(['",'',"
"]);return $(D.join(""))},renderColumns:function j(F){F=F!==undefined?F:this.fxSpeed;var E=this,C=E.sortedFilteredColumns();E.$(".middle").width(C.length*(this.options.columnWidth+this.options.columnGap)+this.options.columnGap+16);var D=E.$(".middle");D.empty();C.forEach(function(H,G){H.$el.appendTo(D);H.delegateEvents();E.renderColumn(H,F)});if(this.searchFor&&C.length<=1){}else{E.checkColumnsInView();this._recalcFirstColumnHeight()}return C},renderColumn:function(C,D){D=D!==undefined?D:this.fxSpeed;return C.render(D)},queueHdaFetch:function i(E){if(E.model.contents.length===0&&!E.model.get("empty")){var C={},D=_.values(E.panel.storage.get("expandedIds")).join();if(D){C.dataset_details=D}this.hdaQueue.add({name:E.model.id,fn:function(){var F=E.model.contents.fetch({data:C,silent:true});return F.done(function(G){E.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},queueHdaFetchDetails:function(C){if((C.model.contents.length===0&&!C.model.get("empty"))||(!C.model.contents.haveDetails())){this.hdaQueue.add({name:C.model.id,fn:function(){var D=C.model.contents.fetch({data:{details:"all"},silent:true});return D.done(function(E){C.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},renderInfo:function(C){this.$(".header .header-info").text(C)},events:{"click .done.btn":"close","click .create-new.btn":"create","click .order .order-update":function(C){this.setOrder("update")},"click .order .order-name":function(C){this.setOrder("name")},"click .order .order-size":function(C){this.setOrder("size")}},close:function(D){var C="/";if(Galaxy&&Galaxy.options&&Galaxy.options.root){C=Galaxy.options.root}else{if(galaxy_config&&galaxy_config.root){C=galaxy_config.root}}window.location=C},includeDeletedHistories:function(){window.location+=(/\?/.test(window.location.toString()))?("&"):("?")+"include_deleted_histories=True"},excludeDeletedHistories:function(){window.location=window.location.toString().replace(/[&\?]include_deleted_histories=True/g,"")},setUpBehaviors:function(){var D=this;D.$(".include-deleted").modeButton({initialMode:this.collection.includeDeleted?"exclude":"include",switchModesOnClick:false,modes:[{mode:"include",html:_l("Include deleted histories"),onclick:_.bind(D.includeDeletedHistories,D)},{mode:"exclude",html:_l("Exclude deleted histories"),onclick:_.bind(D.excludeDeletedHistories,D)}]});D.$("#search-histories").searchInput({name:"search-histories",placeholder:_l("search histories"),onsearch:function(E){D.searchFor=E;D.filters=[function(){return this.model.matchesAll(D.searchFor)}];D.renderColumns(0)},onclear:function(E){D.searchFor=null;D.filters=[];D.renderColumns(0)}});D.$("#search-datasets").searchInput({name:"search-datasets",placeholder:_l("search all datasets"),onfirstsearch:function(E){D.hdaQueue.clear();D.$("#search-datasets").searchInput("toggle-loading");D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E);D.queueHdaFetchDetails(F)});D.hdaQueue.progress(function(F){D.renderInfo([_l("searching"),(F.curr+1),_l("of"),F.total].join(" "))});D.hdaQueue.deferred.done(function(){D.renderInfo("");D.$("#search-datasets").searchInput("toggle-loading")})},onsearch:function(E){D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E)})},onclear:function(E){D.searchFor=null;D.sortedFilteredColumns().forEach(function(F){F.panel.clearSearch()})}});D.$("#toggle-deleted").modeButton({initialMode:"include",modes:[{mode:"exclude",html:_l("Exclude deleted datasets")},{mode:"include",html:_l("Include deleted datasets")}]}).click(function(){var E=$(this).modeButton("getMode").mode==="exclude";D.sortedFilteredColumns().forEach(function(G,F){_.delay(function(){G.panel.toggleShowDeleted(E,false)},F*200)})});D.$("#toggle-hidden").modeButton({initialMode:"include",modes:[{mode:"exclude",html:_l("Exclude hidden datasets")},{mode:"include",html:_l("Include hidden datasets")}]}).click(function(){var E=$(this).modeButton("getMode").mode==="exclude";D.sortedFilteredColumns().forEach(function(G,F){_.delay(function(){G.panel.toggleShowHidden(E,false)},F*200)})});$(window).resize(function(){D._recalcFirstColumnHeight()});var C=_.debounce(_.bind(this.checkColumnsInView,this),100);this.$(".middle").parent().scroll(C)},_recalcFirstColumnHeight:function(){var C=this.$(".history-column").first(),E=this.$(".middle").height(),D=C.find(".panel-controls").height();C.height(E).find(".inner").height(E-D)},_viewport:function(){var C=this.$(".middle").parent().offset().left;return{left:C,right:C+this.$(".middle").parent().width()}},columnsInView:function(){var C=this._viewport();return this.sortedFilteredColumns().filter(function(D){return D.currentHistory||D.inView(C.left,C.right)})},checkColumnsInView:function(){this.columnsInView().forEach(function(C){C.trigger("in-view",C)})},currentColumnDropTargetOn:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=function(D){};C.panel.dropTargetOn()},currentColumnDropTargetOff:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=l.HistoryPanelEdit.prototype.dataDrop;C.panel.dropTargetOff()},toString:function(){return"MultiPanelColumns("+(this.columns?this.columns.length:0)+")"}});return{MultiPanelColumns:m}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/history/history-panel-edit","mvc/base-mvc","utils/ajax-queue","ui/mode-button","ui/search-input"],function(d,l,z,a){function g(I,E){E=E||{};if(!(Galaxy&&Galaxy.modal)){return I.copy()}var F=I.get("name"),C="Copy of '"+F+"'";function D(K){if(!K){if(!Galaxy.modal.$("#invalid-title").size()){var J=$("
").attr("id","invalid-title").css({color:"red","margin-top":"8px"}).addClass("bg-danger").text(_l("Please enter a valid history title"));Galaxy.modal.$(".modal-body").append(J)}return false}return K}function G(J){var K=$(' Copying history...
').css("margin-top","8px");Galaxy.modal.$(".modal-body").append(K);I.copy(true,J).fail(function(){alert(_l("History could not be copied. Please contact a Galaxy administrator"))}).always(function(){Galaxy.modal.hide()})}function H(){var J=Galaxy.modal.$("#copy-modal-title").val();if(!D(J)){return}G(J)}Galaxy.modal.show(_.extend({title:_l("Copying history")+' "'+F+'"',body:$(['',_l("Enter a title for the copied history"),":"," ",' '].join("")),buttons:{Cancel:function(){Galaxy.modal.hide()},Copy:H}},E));$("#copy-modal-title").focus().select();$("#copy-modal-title").on("keydown",function(J){if(J.keyCode===13){H()}})}var B=Backbone.View.extend(z.LoggableMixin).extend({tagName:"div",className:"history-column flex-column flex-row-container",id:function q(){if(!this.model){return""}return"history-column-"+this.model.get("id")},initialize:function c(C){C=C||{};this.panel=C.panel||this.createPanel(C);this.setUpListeners()},createPanel:function u(D){D=_.extend({model:this.model,dragItems:true},D);var C=new l.HistoryPanelEdit(D);C._renderEmptyMessage=this.__patch_renderEmptyMessage;return C},__patch_renderEmptyMessage:function(E){var D=this,F=_.chain(this.model.get("state_ids")).values().flatten().value().length,C=D.$emptyMessage(E);if(!_.isEmpty(D.hdaViews)){C.hide()}else{if(F&&!this.model.contents.length){C.empty().append($(' loading datasets... ')).show()}else{if(D.searchFor){C.text(D.noneFoundMsg).show()}else{C.text(D.emptyMsg).show()}}}return C},setUpListeners:function f(){var C=this;this.once("rendered",function(){C.trigger("rendered:initial",C)});this.setUpPanelListeners()},setUpPanelListeners:function k(){var C=this;this.listenTo(this.panel,{rendered:function(){C.trigger("rendered",C)}},this)},inView:function(C,D){var F=this.$el.offset().left,E=F+this.$el.width();if(ED){return false}return true},$panel:function e(){return this.$(".history-panel")},render:function A(D){D=(D!==undefined)?(D):("fast");var C=this.model?this.model.toJSON():{};this.$el.html(this.template(C));this.renderPanel(D);this.setUpBehaviors();return this},setUpBehaviors:function v(){},template:function w(D){D=D||{};var C=['',this.controlsLeftTemplate(),'
','',D.deleted?_l("Undelete"):_l("Delete")," ",'',_l("Copy")," ","
","
",'"].join("");return $(C)},controlsLeftTemplate:function(){return(this.currentHistory)?['','',_l("Current History")," ","
"].join(""):['','',_l("Switch to")," ","
"].join("")},renderPanel:function h(C){C=(C!==undefined)?(C):("fast");this.panel.setElement(this.$panel()).render(C);return this},events:{"click .switch-to.btn":function(){this.model.setAsCurrent()},"click .delete-history.btn":function(){var C=this,D;if(this.model.get("deleted")){D=this.model.undelete()}else{D=this.model._delete()}D.fail(function(G,E,F){alert(_l("Could not delete the history")+":\n"+F)}).done(function(E){C.render()})},"click .copy-history.btn":"copy"},copy:function s(){g(this.model)},toString:function(){return"HistoryPanelColumn("+(this.panel?this.panel:"")+")"}});var m=Backbone.View.extend(z.LoggableMixin).extend({className:"multi-history-columns",initialize:function c(C){C=C||{};this.log(this+".init",C);if(!C.currentHistoryId){throw new Error(this+" requires a currentHistoryId in the options")}this.currentHistoryId=C.currentHistoryId;this.options={columnWidth:312,borderWidth:1,columnGap:8,headerHeight:29,footerHeight:0,controlsHeight:20};this.order=C.order||"update";this.hdaQueue=new a.NamedAjaxQueue([],false);this.collection=null;this.setCollection(C.histories||[]);this.columnMap={};this.createColumns(C.columnOptions);this.setUpListeners()},setUpListeners:function f(){},setCollection:function y(D){var C=this;C.stopListening(C.collection);C.collection=D;C.sortCollection(C.order,{silent:true});C.setUpCollectionListeners();C.trigger("new-collection",C);return C},setUpCollectionListeners:function(){var C=this,D=C.collection;C.listenTo(D,{add:C.addAsCurrentColumn,"set-as-current":C.setCurrentHistory,"change:deleted":C.handleDeletedHistory,sort:function(){C.renderColumns(0)}})},setCurrentHistory:function p(D){var C=this.columnMap[this.currentHistoryId];if(C){C.currentHistory=false;C.$el.height("")}this.currentHistoryId=D.id;var E=this.columnMap[this.currentHistoryId];E.currentHistory=true;this.sortCollection();multipanel._recalcFirstColumnHeight();return E},handleDeletedHistory:function b(D){if(D.get("deleted")){this.log("handleDeletedHistory",this.collection.includeDeleted,D);var C=this;column=C.columnMap[D.id];if(!column){return}if(column.model.id===this.currentHistoryId){}else{if(!C.collection.includeDeleted){C.removeColumn(column)}}}},sortCollection:function(C,D){C=C||this.order;var E=this.currentHistoryId;switch(C){case"name":this.collection.comparator=function(F){return[F.id!==E,F.get("name").toLowerCase()]};break;case"size":this.collection.comparator=function(F){return[F.id!==E,F.get("size")]};break;default:this.collection.comparator=function(F){return[F.id!==E,Date(F.get("update_time"))]}}this.collection.sort(D);return this.collection},setOrder:function(C){if(["update","name","size"].indexOf(C)===-1){C="update"}this.order=C;this.trigger("order:change",C,this);this.$(".current-order").text(C);this.sortCollection();return this},create:function(C){return this.collection.create({current:true})},createColumns:function r(D){D=D||{};var C=this;this.columnMap={};C.collection.each(function(E,F){var G=C.createColumn(E,D);C.columnMap[E.id]=G})},createColumn:function t(E,C){C=_.extend({},C,{model:E});var D=new B(C);if(E.id===this.currentHistoryId){D.currentHistory=true}this.setUpColumnListeners(D);return D},sortedFilteredColumns:function(C){C=C||this.filters;if(!C||!C.length){return this.sortedColumns()}var D=this;return D.sortedColumns().filter(function(G,F){var E=G.currentHistory||_.every(C.map(function(H){return H.call(G)}));return E})},sortedColumns:function(){var D=this;var C=this.collection.map(function(F,E){return D.columnMap[F.id]});return C},addColumn:function o(E,C){C=C!==undefined?C:true;var D=this.createColumn(E);this.columnMap[E.id]=D;if(C){this.renderColumns()}return D},addAsCurrentColumn:function o(E){var D=this,C=this.addColumn(E,false);this.setCurrentHistory(E);C.once("rendered",function(){D.queueHdaFetch(C)});return C},removeColumn:function x(E,D){D=D!==undefined?D:true;this.log("removeColumn",E);if(!E){return}var F=this,C=this.options.columnWidth+this.options.columnGap;E.$el.fadeOut("fast",function(){if(D){$(this).remove();F.$(".middle").width(F.$(".middle").width()-C);F.checkColumnsInView();F._recalcFirstColumnHeight()}F.stopListening(E.panel);F.stopListening(E);delete F.columnMap[E.model.id];E.remove()})},setUpColumnListeners:function n(C){var D=this;D.listenTo(C,{"in-view":D.queueHdaFetch});D.listenTo(C.panel,{"view:draggable:dragstart":function(H,F,E,G){D._dropData=JSON.parse(H.dataTransfer.getData("text"));D.currentColumnDropTargetOn()},"view:draggable:dragend":function(H,F,E,G){D._dropData=null;D.currentColumnDropTargetOff()},"droptarget:drop":function(G,H,F){var I=D._dropData.filter(function(J){return(_.isObject(J)&&J.id&&J.model_class==="HistoryDatasetAssociation")});D._dropData=null;var E=new a.NamedAjaxQueue();I.forEach(function(J){E.add({name:"copy-"+J.id,fn:function(){return F.model.contents.copy(J.id)}})});E.start();E.done(function(J){F.model.fetch()})}})},columnMapLength:function(){return Object.keys(this.columnMap).length},render:function A(D){D=D!==undefined?D:this.fxSpeed;var C=this;C.log(C+".render");C.$el.html(C.mainTemplate(C));C.renderColumns(D);C.setUpBehaviors();C.trigger("rendered",C);return C},renderColumns:function j(F){F=F!==undefined?F:this.fxSpeed;var E=this,C=E.sortedFilteredColumns();E.$(".middle").width(C.length*(this.options.columnWidth+this.options.columnGap)+this.options.columnGap+16);var D=E.$(".middle");D.empty();C.forEach(function(H,G){H.$el.appendTo(D);H.delegateEvents();E.renderColumn(H,F)});if(this.searchFor&&C.length<=1){}else{E.checkColumnsInView();this._recalcFirstColumnHeight()}return C},renderColumn:function(C,D){D=D!==undefined?D:this.fxSpeed;return C.render(D)},queueHdaFetch:function i(E){if(E.model.contents.length===0&&!E.model.get("empty")){var C={},D=_.values(E.panel.storage.get("expandedIds")).join();if(D){C.dataset_details=D}this.hdaQueue.add({name:E.model.id,fn:function(){var F=E.model.contents.fetch({data:C,silent:true});return F.done(function(G){E.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},queueHdaFetchDetails:function(C){if((C.model.contents.length===0&&!C.model.get("empty"))||(!C.model.contents.haveDetails())){this.hdaQueue.add({name:C.model.id,fn:function(){var D=C.model.contents.fetch({data:{details:"all"},silent:true});return D.done(function(E){C.panel.renderItems()})}});if(!this.hdaQueue.running){this.hdaQueue.start()}}},renderInfo:function(C){this.$(".header .header-info").text(C)},events:{"click .done.btn":"close","click .create-new.btn":"create","click #include-deleted":"_clickToggleDeletedHistories","click .order .order-update":function(C){this.setOrder("update")},"click .order .order-name":function(C){this.setOrder("name")},"click .order .order-size":function(C){this.setOrder("size")},"click #toggle-deleted":"_clickToggleDeletedDatasets","click #toggle-hidden":"_clickToggleHiddenDatasets"},close:function(D){var C="/";if(Galaxy&&Galaxy.options&&Galaxy.options.root){C=Galaxy.options.root}else{if(galaxy_config&&galaxy_config.root){C=galaxy_config.root}}window.location=C},_clickToggleDeletedHistories:function(C){return this.toggleDeletedHistories($(C.currentTarget).is(":checked"))},toggleDeletedHistories:function(C){if(C){window.location=Galaxy.options.root+"history/view_multiple?include_deleted_histories=True"}else{window.location=Galaxy.options.root+"history/view_multiple"}},_clickToggleDeletedDatasets:function(C){return this.toggleDeletedDatasets($(C.currentTarget).is(":checked"))},toggleDeletedDatasets:function(C){C=C!==undefined?C:false;var D=this;D.sortedFilteredColumns().forEach(function(F,E){_.delay(function(){F.panel.toggleShowDeleted(C,false)},E*200)})},_clickToggleHiddenDatasets:function(C){return this.toggleHiddenDatasets($(C.currentTarget).is(":checked"))},toggleHiddenDatasets:function(C){C=C!==undefined?C:false;var D=this;D.sortedFilteredColumns().forEach(function(F,E){_.delay(function(){F.panel.toggleShowHidden(C,false)},E*200)})},setUpBehaviors:function(){var D=this;D._moreOptionsPopover();D.$("#search-histories").searchInput({name:"search-histories",placeholder:_l("search histories"),onsearch:function(E){D.searchFor=E;D.filters=[function(){return this.model.matchesAll(D.searchFor)}];D.renderColumns(0)},onclear:function(E){D.searchFor=null;D.filters=[];D.renderColumns(0)}});D.$("#search-datasets").searchInput({name:"search-datasets",placeholder:_l("search all datasets"),onfirstsearch:function(E){D.hdaQueue.clear();D.$("#search-datasets").searchInput("toggle-loading");D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E);D.queueHdaFetchDetails(F)});D.hdaQueue.progress(function(F){D.renderInfo([_l("searching"),(F.curr+1),_l("of"),F.total].join(" "))});D.hdaQueue.deferred.done(function(){D.renderInfo("");D.$("#search-datasets").searchInput("toggle-loading")})},onsearch:function(E){D.searchFor=E;D.sortedFilteredColumns().forEach(function(F){F.panel.searchItems(E)})},onclear:function(E){D.searchFor=null;D.sortedFilteredColumns().forEach(function(F){F.panel.clearSearch()})}});$(window).resize(function(){D._recalcFirstColumnHeight()});var C=_.debounce(_.bind(this.checkColumnsInView,this),100);this.$(".middle").parent().scroll(C)},_moreOptionsPopover:function(){return this.$(".open-more-options.btn").popover({container:".header",placement:"bottom",html:true,content:$(this.optionsPopoverTemplate(this))})},_recalcFirstColumnHeight:function(){var C=this.$(".history-column").first(),E=this.$(".middle").height(),D=C.find(".panel-controls").height();C.height(E).find(".inner").height(E-D)},_viewport:function(){var C=this.$(".middle").parent().offset().left;return{left:C,right:C+this.$(".middle").parent().width()}},columnsInView:function(){var C=this._viewport();return this.sortedFilteredColumns().filter(function(D){return D.currentHistory||D.inView(C.left,C.right)})},checkColumnsInView:function(){this.columnsInView().forEach(function(C){C.trigger("in-view",C)})},currentColumnDropTargetOn:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=function(D){};C.panel.dropTargetOn()},currentColumnDropTargetOff:function(){var C=this.columnMap[this.currentHistoryId];if(!C){return}C.panel.dataDropped=l.HistoryPanelEdit.prototype.dataDrop;C.panel.dropTargetOff()},toString:function(){return"MultiPanelColumns("+(this.columns?this.columns.length:0)+")"},mainTemplate:_.template(['','
','
',_l("Create new")," ",'
','
','
',' '," ","
",'
','","
",'
','',_l("Done")," ","
","
",'",'',"
"].join(""),{variable:"view"}),optionsPopoverTemplate:_.template(['','
>',_l("Include deleted histories"),"
",'
','',_l("Order histories by")+" ",'<%= view.order %> ',' '," ",'","
",'
',_l("Include deleted datasets"),"
",'
',_l("Include hidden datasets"),"
","
"].join(""),{variable:"view"}),});return{MultiPanelColumns:m}});
\ No newline at end of file
diff --git a/templates/webapps/galaxy/history/view_multiple.mako b/templates/webapps/galaxy/history/view_multiple.mako
index d756c750ef9..baf606aba1c 100644
--- a/templates/webapps/galaxy/history/view_multiple.mako
+++ b/templates/webapps/galaxy/history/view_multiple.mako
@@ -75,29 +75,36 @@
.flex-column {
}
+ /* ---------------------- header & footer */
.header, .footer {
width: 100%;
}
+ /* ---------------------- header */
.header {
background-color: lightgrey;
min-height: ${header_height}px;
max-height: ${header_height}px;
}
- .header-control {
+ .control-column {
margin-top: 4px;
}
- .header-control-right,
- .header-control-left {
+
+ .control-column-right,
+ .control-column-left {
margin-right: 8px;
margin-left: 8px;
+ /*background-color: green;*/
}
- .header-control-left > * {
+ .control-column-left > * {
margin: 0px 4px 4px 0px;
}
+ .more-options input[type=checkbox] {
+ margin-top: 3px;
+ }
- .header-control-center {
+ .control-column-center {
text-align: center;
max-height: 22px;
-webkit-flex: 0 1 auto;
@@ -117,26 +124,35 @@
}
- .header-control-right {
+ .control-column-right {
text-align: right;
}
- .header-control-right > * {
+ .control-column-right > * {
margin: 0px 0px 4px 4px;
}
- .header-search {
+ .search-control {
display: inline-block;
+ width: 40%;
}
- .header-search .search-clear,
- .header-search .search-loading {
+ .search-control .search-clear,
+ .search-control .search-loading {
margin-top: -22px;
}
+ .footer input.search-query,
.header input.search-query {
font-size: 90%;
height: 21px;
- padding: 2px;
+ line-height: normal;
+ padding: 2px 2px 1px 2px;
}
+ .open-more-options {
+ padding: 0 4px 0 4px;
+ font-size: 150%;
+ }
+
+ /* ---------------------- middle */
.outer-middle {
overflow: auto;
}
@@ -169,13 +185,18 @@
align-self: auto;
}
.header .btn,
+ .footer .btn,
.panel-controls .btn {
- height: ${controls_height}px;
- line-height: ${controls_height - 2}px;
+ height: 20px;
+ /*line-height: ${controls_height - 2}px;*/
+ line-height: normal;
font-size: 90%;
padding-top: 0px;
padding-bottom: 0px;
}
+ .header .btn {
+ height: 21px;
+ }
.panel-controls .pull-left .btn {
margin-right: 4px;
}
@@ -183,13 +204,14 @@
margin-left: 4px;
}
+ /* ---------------------- footer */
.footer {
min-height: ${footer_height}px;
max-height: ${footer_height}px;
- background-color: grey;
+ background-color: lightgrey;
}
- /* ---- columns */
+ /* ---------------------- columns */
.history-panel {
width: 100%;
margin-top: 4px;
@@ -230,6 +252,12 @@
vertical-align: middle;
}
+ .current-label {
+ display: inline-block;
+ color: grey;
+ padding-left: 2px;
+ margin-top: 2px;
+ }
%def>