mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-09-24 16:30:27 +08:00
UI, Pair creator: initial (sloppy) refactor of pair creator to inherit from list creator
This commit is contained in:
@@ -57,14 +57,19 @@ var DatasetCollectionElementView = Backbone.View.extend( BASE_MVC.LoggableMixin
|
||||
var view = this,
|
||||
parentWidth = this.$el.parent().width();
|
||||
this.$el.animate({ 'margin-right' : parentWidth }, 'fast', function(){
|
||||
view.off();
|
||||
view.$el.remove();
|
||||
view.destroy();
|
||||
view.trigger( 'discard', {
|
||||
source : view
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
/** remove the DOM and any listeners */
|
||||
destroy : function(){
|
||||
this.off();
|
||||
this.$el.remove();
|
||||
},
|
||||
|
||||
events : {
|
||||
'click' : '_click',
|
||||
'click .name' : '_clickName',
|
||||
@@ -133,8 +138,10 @@ var DatasetCollectionElementView = Backbone.View.extend( BASE_MVC.LoggableMixin
|
||||
*/
|
||||
var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
|
||||
|
||||
/** the class used to display individual elements */
|
||||
elementViewClass : DatasetCollectionElementView,
|
||||
/** the class this creator will create and save */
|
||||
collectionClass : HDCA.HistoryListDatasetCollection,
|
||||
collectionClass : HDCA.HistoryListDatasetCollection,
|
||||
className : 'list-collection-creator collection-creator flex-row-container',
|
||||
|
||||
defaultAttributes : {
|
||||
@@ -195,7 +202,7 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
this._ensureElementIds();
|
||||
this._validateElements();
|
||||
this._mangleDuplicateNames();
|
||||
// this._sortElements();
|
||||
this._sortElements();
|
||||
},
|
||||
|
||||
/** add ids to dataset objs in initial list if none */
|
||||
@@ -265,16 +272,18 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
|
||||
/** sort a list of elements */
|
||||
_sortElements : function( list ){
|
||||
// currently only natural sort by name
|
||||
this.workingElements.sort( function( a, b ){ return naturalSort( a.name, b.name ); });
|
||||
return this.workingElements;
|
||||
// // currently only natural sort by name
|
||||
// this.workingElements.sort( function( a, b ){ return naturalSort( a.name, b.name ); });
|
||||
// return this.workingElements;
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ rendering
|
||||
// templates : ListCollectionCreator.templates,
|
||||
|
||||
/** render the entire interface */
|
||||
render : function( speed, callback ){
|
||||
//this.debug( '-- _render' );
|
||||
this.$el.empty().html( ListCollectionCreator.templates.main() );
|
||||
this.$el.empty().html( this.templates.main() );
|
||||
this._renderHeader( speed );
|
||||
this._renderMiddle( speed );
|
||||
this._renderFooter( speed );
|
||||
@@ -286,8 +295,8 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
|
||||
/** render the header section */
|
||||
_renderHeader : function( speed, callback ){
|
||||
var $header = this.$( '.header' ).empty().html( ListCollectionCreator.templates.header() )
|
||||
.find( '.help-content' ).prepend( $( ListCollectionCreator.templates.helpContent() ) );
|
||||
var $header = this.$( '.header' ).empty().html( this.templates.header() )
|
||||
.find( '.help-content' ).prepend( $( this.templates.helpContent() ) );
|
||||
//TODO: should only show once despite calling _renderHeader again
|
||||
if( this.invalidElements.length ){
|
||||
this._invalidElementsAlert();
|
||||
@@ -297,14 +306,14 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
|
||||
/** render the middle including the elements */
|
||||
_renderMiddle : function( speed, callback ){
|
||||
var $middle = this.$( '.middle' ).empty().html( ListCollectionCreator.templates.middle() );
|
||||
var $middle = this.$( '.middle' ).empty().html( this.templates.middle() );
|
||||
this._renderList( speed );
|
||||
return $middle;
|
||||
},
|
||||
|
||||
/** render the footer, completion controls, and cancel controls */
|
||||
_renderFooter : function( speed, callback ){
|
||||
var $footer = this.$( '.footer' ).empty().html( ListCollectionCreator.templates.footer() );
|
||||
var $footer = this.$( '.footer' ).empty().html( this.templates.footer() );
|
||||
if( typeof this.oncancel === 'function' ){
|
||||
this.$( '.cancel-create.btn' ).show();
|
||||
}
|
||||
@@ -361,15 +370,20 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
|
||||
/** render the elements in order (or a warning if no elements found) */
|
||||
_renderList : function( speed, callback ){
|
||||
//this.debug( '-- _renderList' );
|
||||
var creator = this,
|
||||
$tmp = jQuery( '<div/>' );
|
||||
|
||||
_.each( this.elementViews, function( view ){
|
||||
view.destroy();
|
||||
creator.removeElementView( view );
|
||||
});
|
||||
|
||||
if( !this.workingElements.length ){
|
||||
this._renderNoValidElements();
|
||||
return;
|
||||
}
|
||||
|
||||
//this.debug( '-- _renderList' );
|
||||
var creator = this,
|
||||
$tmp = jQuery( '<div/>' );
|
||||
|
||||
creator.workingElements.forEach( function( element ){
|
||||
var elementView = creator._createElementView( element );
|
||||
$tmp.append( elementView.$el );
|
||||
@@ -382,7 +396,7 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
|
||||
/** create an element view, cache in elementViews, set up listeners, and return */
|
||||
_createElementView : function( element ){
|
||||
var elementView = new DatasetCollectionElementView({
|
||||
var elementView = new this.elementViewClass({
|
||||
//TODO: use non-generic class or not all
|
||||
// model : COLLECTION.DatasetDCE( element )
|
||||
element : element,
|
||||
@@ -441,7 +455,7 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
|
||||
/** render a message in the list that no valid elements were found to create a collection */
|
||||
_renderNoValidElements : function(){
|
||||
this.$( '.collection-elements' ).append( ListCollectionCreator.templates.noValidElements() );
|
||||
this.$( '.collection-elements' ).append( this.templates.noValidElements() );
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ API
|
||||
@@ -758,140 +772,140 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
|
||||
}
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ templates
|
||||
//TODO: move to require text plugin and load these as text
|
||||
//TODO: underscore currently unnecc. bc no vars are used
|
||||
//TODO: better way of localizing text-nodes in long strings
|
||||
/** underscore template fns attached to class */
|
||||
templates : {
|
||||
/** the skeleton */
|
||||
main : _.template([
|
||||
'<div class="header flex-row no-flex"></div>',
|
||||
'<div class="middle flex-row flex-row-container"></div>',
|
||||
'<div class="footer flex-row no-flex">'
|
||||
].join('')),
|
||||
|
||||
/** the header (not including help text) */
|
||||
header : _.template([
|
||||
'<div class="main-help well clear">',
|
||||
'<a class="more-help" href="javascript:void(0);">', _l( 'More help' ), '</a>',
|
||||
'<div class="help-content">',
|
||||
'<a class="less-help" href="javascript:void(0);">', _l( 'Less' ), '</a>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="alert alert-dismissable">',
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>',
|
||||
'<span class="alert-message"></span>',
|
||||
'</div>',
|
||||
].join('')),
|
||||
|
||||
/** the middle: element list */
|
||||
middle : _.template([
|
||||
'<div class="collection-elements-controls">',
|
||||
'<a class="reset" href="javascript:void(0);" title="', _l( 'Undo all reordering and discards' ), '">',
|
||||
_l( 'Start over' ),
|
||||
'</a>',
|
||||
'<a class="clear-selected" href="javascript:void(0);" title="', _l( 'De-select all selected datasets' ), '">',
|
||||
_l( 'Clear selected' ),
|
||||
'</a>',
|
||||
'</div>',
|
||||
'<div class="collection-elements scroll-container flex-row">',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
/** creation and cancel controls */
|
||||
footer : _.template([
|
||||
'<div class="attributes clear">',
|
||||
'<div class="clear">',
|
||||
'<input class="collection-name form-control pull-right" ',
|
||||
'placeholder="', _l( 'Enter a name for your new list' ), '" />',
|
||||
'<div class="collection-name-prompt pull-right">', _l( 'Name' ), ':</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div class="actions clear vertically-spaced">',
|
||||
'<div class="other-options pull-left">',
|
||||
'<button class="cancel-create btn" tabindex="-1">', _l( 'Cancel' ), '</button>',
|
||||
'<div class="create-other btn-group dropup">',
|
||||
'<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',
|
||||
_l( 'Create a different kind of collection' ),
|
||||
' <span class="caret"></span>',
|
||||
'</button>',
|
||||
'<ul class="dropdown-menu" role="menu">',
|
||||
'<li><a href="#">', _l( 'Create a <i>single</i> pair' ), '</a></li>',
|
||||
'<li><a href="#">', _l( 'Create a list of <i>unpaired</i> datasets' ), '</a></li>',
|
||||
'</ul>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div class="main-options pull-right">',
|
||||
'<button class="create-collection btn btn-primary">', _l( 'Create list' ), '</button>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
/** help content */
|
||||
helpContent : _.template([
|
||||
'<p>', _l([
|
||||
'Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and ',
|
||||
'workflows in order to have analyses done on each member of the entire group. This interface allows ',
|
||||
'you to create a collection and re-order the final collection.'
|
||||
].join( '' )), '</p>',
|
||||
'<ul>',
|
||||
'<li>', _l([
|
||||
'Rename elements in the list by clicking on ',
|
||||
'<i data-target=".collection-element .name">the existing name</i>.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Discard elements from the final created list by clicking on the ',
|
||||
'<i data-target=".collection-element .discard">"Discard"</i> button.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Reorder the list by clicking and dragging elements. Select multiple elements by clicking on ',
|
||||
'<i data-target=".collection-element">them</i> and you can then move those selected by dragging the ',
|
||||
'entire group. Deselect them by clicking them again or by clicking the ',
|
||||
'the <i data-target=".clear-selected">"Clear selected"</i> link.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Click the <i data-target=".reset">"Start over"</i> link to begin again as if you had just opened ',
|
||||
'the interface.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Click the <i data-target=".cancel-create">"Cancel"</i> button to exit the interface.'
|
||||
].join( '' )), '</li>',
|
||||
'</ul><br />',
|
||||
'<p>', _l([
|
||||
'Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ',
|
||||
'click <i data-target=".create-collection">"Create list"</i>.'
|
||||
].join( '' )), '</p>'
|
||||
].join('')),
|
||||
|
||||
/** shown in list when all elements are discarded */
|
||||
noElementsLeft : _.template([
|
||||
'<li class="no-elements-left-message empty-message">',
|
||||
_l( 'No elements left' ), '<br />',
|
||||
_l( 'Would you like to ' ),
|
||||
'<a class="reset" href="javascript:void(0)">', _l( 'start over' ), '</a>?',
|
||||
'</li>'
|
||||
].join('')),
|
||||
|
||||
/** shown in list when no valid elements were found to begin with */
|
||||
noValidElements : _.template([
|
||||
'<li class="no-valid-elements-message empty-message">',
|
||||
_l( 'No valid elements!' ), '<br />',
|
||||
_l( 'You may need to ' ),
|
||||
'<a class="cancel-create" href="javascript:void(0)">', _l( 'cancel' ), '</a> ',
|
||||
'and reselect new elements',
|
||||
'</li>'
|
||||
].join(''))
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ misc
|
||||
/** string rep */
|
||||
toString : function(){ return 'ListCollectionCreator'; }
|
||||
});
|
||||
|
||||
|
||||
//TODO: move to require text plugin and load these as text
|
||||
//TODO: underscore currently unnecc. bc no vars are used
|
||||
//TODO: better way of localizing text-nodes in long strings
|
||||
/** underscore template fns attached to class */
|
||||
ListCollectionCreator.templates = ListCollectionCreator.templates || {
|
||||
|
||||
/** the skeleton */
|
||||
main : _.template([
|
||||
'<div class="header flex-row no-flex"></div>',
|
||||
'<div class="middle flex-row flex-row-container"></div>',
|
||||
'<div class="footer flex-row no-flex">'
|
||||
].join('')),
|
||||
|
||||
/** the header (not including help text) */
|
||||
header : _.template([
|
||||
'<div class="main-help well clear">',
|
||||
'<a class="more-help" href="javascript:void(0);">', _l( 'More help' ), '</a>',
|
||||
'<div class="help-content">',
|
||||
'<a class="less-help" href="javascript:void(0);">', _l( 'Less' ), '</a>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
'<div class="alert alert-dismissable">',
|
||||
'<button type="button" class="close" data-dismiss="alert" aria-hidden="true">×</button>',
|
||||
'<span class="alert-message"></span>',
|
||||
'</div>',
|
||||
].join('')),
|
||||
|
||||
/** the middle: element list */
|
||||
middle : _.template([
|
||||
'<div class="collection-elements-controls">',
|
||||
'<a class="reset" href="javascript:void(0);" title="', _l( 'Undo all reordering and discards' ), '">',
|
||||
_l( 'Start over' ),
|
||||
'</a>',
|
||||
'<a class="clear-selected" href="javascript:void(0);" title="', _l( 'De-select all selected datasets' ), '">',
|
||||
_l( 'Clear selected' ),
|
||||
'</a>',
|
||||
'</div>',
|
||||
'<div class="collection-elements scroll-container flex-row">',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
/** creation and cancel controls */
|
||||
footer : _.template([
|
||||
'<div class="attributes clear">',
|
||||
'<div class="clear">',
|
||||
'<input class="collection-name form-control pull-right" ',
|
||||
'placeholder="', _l( 'Enter a name for your new list' ), '" />',
|
||||
'<div class="collection-name-prompt pull-right">', _l( 'Name' ), ':</div>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div class="actions clear vertically-spaced">',
|
||||
'<div class="other-options pull-left">',
|
||||
'<button class="cancel-create btn" tabindex="-1">', _l( 'Cancel' ), '</button>',
|
||||
'<div class="create-other btn-group dropup">',
|
||||
'<button class="btn btn-default dropdown-toggle" data-toggle="dropdown">',
|
||||
_l( 'Create a different kind of collection' ),
|
||||
' <span class="caret"></span>',
|
||||
'</button>',
|
||||
'<ul class="dropdown-menu" role="menu">',
|
||||
'<li><a href="#">', _l( 'Create a <i>single</i> pair' ), '</a></li>',
|
||||
'<li><a href="#">', _l( 'Create a list of <i>unpaired</i> datasets' ), '</a></li>',
|
||||
'</ul>',
|
||||
'</div>',
|
||||
'</div>',
|
||||
|
||||
'<div class="main-options pull-right">',
|
||||
'<button class="create-collection btn btn-primary">', _l( 'Create list' ), '</button>',
|
||||
'</div>',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
/** help content */
|
||||
helpContent : _.template([
|
||||
'<p>', _l([
|
||||
'Collections of datasets are permanent, ordered lists of datasets that can be passed to tools and ',
|
||||
'workflows in order to have analyses done on each member of the entire group. This interface allows ',
|
||||
'you to create a collection and re-order the final collection.'
|
||||
].join( '' )), '</p>',
|
||||
'<ul>',
|
||||
'<li>', _l([
|
||||
'Rename elements in the list by clicking on ',
|
||||
'<i data-target=".collection-element .name">the existing name</i>.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Discard elements from the final created list by clicking on the ',
|
||||
'<i data-target=".collection-element .discard">"Discard"</i> button.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Reorder the list by clicking and dragging elements. Select multiple elements by clicking on ',
|
||||
'<i data-target=".collection-element">them</i> and you can then move those selected by dragging the ',
|
||||
'entire group. Deselect them by clicking them again or by clicking the ',
|
||||
'the <i data-target=".clear-selected">"Clear selected"</i> link.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Click the <i data-target=".reset">"Start over"</i> link to begin again as if you had just opened ',
|
||||
'the interface.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Click the <i data-target=".cancel-create">"Cancel"</i> button to exit the interface.'
|
||||
].join( '' )), '</li>',
|
||||
'</ul><br />',
|
||||
'<p>', _l([
|
||||
'Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ',
|
||||
'click <i data-target=".create-collection">"Create list"</i>.'
|
||||
].join( '' )), '</p>'
|
||||
].join('')),
|
||||
|
||||
/** shown in list when all elements are discarded */
|
||||
noElementsLeft : _.template([
|
||||
'<li class="no-elements-left-message empty-message">',
|
||||
_l( 'No elements left' ), '<br />',
|
||||
_l( 'Would you like to ' ),
|
||||
'<a class="reset" href="javascript:void(0)">', _l( 'start over' ), '</a>?',
|
||||
'</li>'
|
||||
].join('')),
|
||||
|
||||
/** shown in list when no valid elements were found to begin with */
|
||||
noValidElements : _.template([
|
||||
'<li class="no-valid-elements-message empty-message">',
|
||||
_l( 'No valid elements!' ), '<br />',
|
||||
_l( 'You may need to ' ),
|
||||
'<a class="cancel-create" href="javascript:void(0)">', _l( 'cancel' ), '</a> ',
|
||||
'and reselect new elements',
|
||||
'</li>'
|
||||
].join(''))
|
||||
};
|
||||
|
||||
|
||||
//=============================================================================
|
||||
/** Create a modal and load its body with the given CreatorClass creator type
|
||||
@@ -967,6 +981,7 @@ function createListCollection( contents ){
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
DatasetCollectionElementView: DatasetCollectionElementView,
|
||||
ListCollectionCreator : ListCollectionCreator,
|
||||
|
||||
collectionCreatorModal : collectionCreatorModal,
|
||||
|
||||
@@ -1,33 +1,208 @@
|
||||
define([
|
||||
"mvc/collection/list-collection-creator",
|
||||
"mvc/history/hdca-model",
|
||||
"mvc/ui/error-modal",
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_COLLECTION_CREATOR, errorModal, _l ){
|
||||
], function( LIST_CREATOR, HDCA, errorModal, BASE_MVC, _l ){
|
||||
/*==============================================================================
|
||||
|
||||
function createPairHDCA( collection ){
|
||||
// currently: datasets in the ok state
|
||||
var elementsJSON = LIST_COLLECTION_CREATOR.validElements( collection );
|
||||
if( !elementsJSON.length ){
|
||||
LIST_COLLECTION_CREATOR.noValidElementsErrorModal();
|
||||
return jQuery.Deferred().reject( LIST_COLLECTION_CREATOR.noValidElementsMessage );
|
||||
}
|
||||
if( elementsJSON.length !== 2 ){
|
||||
errorModal(
|
||||
'When pairing datasets, select only two datasets: one forward and one reverse.',
|
||||
'Not a valid pair'
|
||||
);
|
||||
return jQuery.Deferred().reject( LIST_COLLECTION_CREATOR.noValidElementsMessage );
|
||||
}
|
||||
==============================================================================*/
|
||||
/** */
|
||||
var PairedDatasetCollectionElementView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
|
||||
//TODO: use proper class (DatasetDCE or NestedDCDCE (or the union of both))
|
||||
tagName : 'li',
|
||||
className : 'collection-element',
|
||||
|
||||
var name = 'New Dataset Pair',
|
||||
elementIdentifiers = [
|
||||
{ name: "forward", src: "hda", id: elementsJSON[0].id },
|
||||
{ name: "reverse", src: "hda", id: elementsJSON[1].id }
|
||||
];
|
||||
return collection.createHDCA( elementIdentifiers, 'paired', name );
|
||||
initialize : function( attributes ){
|
||||
this.element = attributes.element || {};
|
||||
this.identifier = attributes.identifier;
|
||||
},
|
||||
|
||||
render : function(){
|
||||
this.$el
|
||||
.attr( 'data-element-id', this.element.id )
|
||||
.html( this.template({ identifier: this.identifier, element: this.element }) );
|
||||
return this;
|
||||
},
|
||||
|
||||
//TODO: lots of unused space in the element - possibly load details and display them horiz.
|
||||
template : _.template([
|
||||
'<span class="identifier"><%= identifier %></span>',
|
||||
'<span class="name"><%= element.name %></span>',
|
||||
].join('')),
|
||||
|
||||
/** remove the DOM and any listeners */
|
||||
destroy : function(){
|
||||
this.off();
|
||||
this.$el.remove();
|
||||
},
|
||||
|
||||
/** string rep */
|
||||
toString : function(){
|
||||
return 'DatasetCollectionElementView()';
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// ============================================================================
|
||||
var _super = LIST_CREATOR.ListCollectionCreator;
|
||||
|
||||
/** An interface for building collections.
|
||||
*/
|
||||
var PairCollectionCreator = _super.extend({
|
||||
|
||||
/** the class used to display individual elements */
|
||||
elementViewClass : PairedDatasetCollectionElementView,
|
||||
/** the class this creator will create and save */
|
||||
collectionClass : HDCA.HistoryPairDatasetCollection,
|
||||
className : 'pair-collection-creator collection-creator flex-row-container',
|
||||
|
||||
/** mangle duplicate names using a mac-like '(counter)' addition to any duplicates */
|
||||
_mangleDuplicateNames : function(){
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ rendering elements
|
||||
/** render the elements in order (or a warning if no elements found) */
|
||||
_renderList : function( speed, callback ){
|
||||
//this.debug( '-- _renderList' );
|
||||
var creator = this,
|
||||
$tmp = jQuery( '<div/>' );
|
||||
|
||||
_.each( this.elementViews, function( view ){
|
||||
view.destroy();
|
||||
creator.removeElementView( view );
|
||||
});
|
||||
|
||||
if( this.workingElements.length < 2 ){
|
||||
this._renderNoValidElements();
|
||||
return;
|
||||
}
|
||||
$tmp.append( creator._createForwardElementView().$el );
|
||||
$tmp.append( creator._createReverseElementView().$el );
|
||||
creator.$list().empty().append( $tmp.children() );
|
||||
_.invoke( creator.elementViews, 'render' );
|
||||
},
|
||||
|
||||
_createForwardElementView : function(){
|
||||
var element = this.workingElements[0],
|
||||
view = this._createElementView( element );
|
||||
view.identifier = _l( 'Forward' );
|
||||
return view;
|
||||
},
|
||||
|
||||
_createReverseElementView : function(){
|
||||
var element = this.workingElements[1],
|
||||
view = this._createElementView( element );
|
||||
view.identifier = _l( 'Reverse' );
|
||||
return view;
|
||||
},
|
||||
|
||||
/** listen to any element events */
|
||||
_listenToElementView : function( view ){
|
||||
// var creator = this;
|
||||
// creator.listenTo( view, {
|
||||
// });
|
||||
},
|
||||
|
||||
swap : function(){
|
||||
this.workingElements = [
|
||||
this.workingElements[1],
|
||||
this.workingElements[0],
|
||||
];
|
||||
this._renderList();
|
||||
},
|
||||
|
||||
events : _.extend( _.clone( _super.prototype.events ), {
|
||||
'click .swap' : 'swap',
|
||||
}),
|
||||
|
||||
// ------------------------------------------------------------------------ templates
|
||||
//TODO: move to require text plugin and load these as text
|
||||
//TODO: underscore currently unnecc. bc no vars are used
|
||||
//TODO: better way of localizing text-nodes in long strings
|
||||
/** underscore template fns attached to class */
|
||||
templates : _.extend( _.clone( _super.prototype.templates ), {
|
||||
/** the middle: element list */
|
||||
middle : _.template([
|
||||
'<div class="collection-elements-controls">',
|
||||
'<a class="swap" href="javascript:void(0);" title="', _l( 'Swap forward and reverse datasets' ), '">',
|
||||
_l( 'Swap' ),
|
||||
'</a>',
|
||||
'</div>',
|
||||
'<div class="collection-elements scroll-container flex-row">',
|
||||
'</div>'
|
||||
].join('')),
|
||||
|
||||
/** help content */
|
||||
helpContent : _.template([
|
||||
'<p>', _l([
|
||||
'Pair collections are permanent collections containing two datasets: one forward and one reverse. ',
|
||||
'Often these are forward and reverse reads. The pair collections can be passed to tools and ',
|
||||
'workflows in order to have analyses done on both datasets. This interface allows ',
|
||||
'you to create a pair, name it, and swap which is forward and which reverse.'
|
||||
].join( '' )), '</p>',
|
||||
'<ul>',
|
||||
'<li>', _l([
|
||||
'Click the <i data-target=".swap">"Swap"</i> link to make your forward dataset the reverse ',
|
||||
'and the reverse dataset forward.'
|
||||
].join( '' )), '</li>',
|
||||
'<li>', _l([
|
||||
'Click the <i data-target=".cancel-create">"Cancel"</i> button to exit the interface.'
|
||||
].join( '' )), '</li>',
|
||||
'</ul><br />',
|
||||
'<p>', _l([
|
||||
'Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ',
|
||||
'click <i data-target=".create-collection">"Create list"</i>.'
|
||||
].join( '' )), '</p>'
|
||||
].join(''))
|
||||
}),
|
||||
|
||||
// ------------------------------------------------------------------------ misc
|
||||
/** string rep */
|
||||
toString : function(){ return 'PairCollectionCreator'; }
|
||||
});
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** List collection flavor of collectionCreatorModal. */
|
||||
var pairCollectionCreatorModal = function _pairCollectionCreatorModal( elements, options ){
|
||||
options = options || {};
|
||||
options.title = _l( 'Create a collection from a pair of datasets' );
|
||||
return LIST_CREATOR.collectionCreatorModal( elements, options, PairCollectionCreator );
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Use a modal to create a pair collection, then add it to the given history contents.
|
||||
* @returns {Deferred} resolved when the collection is added to the history.
|
||||
*/
|
||||
function createPairCollection( contents ){
|
||||
if( contents.length !== 2 ){
|
||||
errorModal(
|
||||
'When pairing datasets, select only two datasets: one forward and one reverse.',
|
||||
'Not a valid pair'
|
||||
);
|
||||
return jQuery.Deferred().reject( 'invalid pair' );
|
||||
}
|
||||
|
||||
var elements = contents.toJSON(),
|
||||
promise = pairCollectionCreatorModal( elements, {
|
||||
creationFn : function( elements, name ){
|
||||
elements = [
|
||||
{ name: "forward", src: "hda", id: elements[0].id },
|
||||
{ name: "reverse", src: "hda", id: elements[1].id }
|
||||
];
|
||||
return contents.createHDCA( elements, 'paired', name );
|
||||
}
|
||||
});
|
||||
return promise;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
return {
|
||||
createPairHDCA : createPairHDCA
|
||||
PairCollectionCreator : PairCollectionCreator,
|
||||
pairCollectionCreatorModal : pairCollectionCreatorModal,
|
||||
createPairCollection : createPairCollection,
|
||||
};
|
||||
});
|
||||
|
||||
@@ -293,7 +293,7 @@ var HistoryPanelEdit = _super.extend(
|
||||
},
|
||||
// TODO: Only show quick pair if two things selected.
|
||||
{ html: _l( 'Build Dataset Pair' ), func: function() {
|
||||
PAIR_COLLECTION_CREATOR.createPairHDCA( panel.getSelectedModels() )
|
||||
PAIR_COLLECTION_CREATOR.createPairCollection( panel.getSelectedModels() )
|
||||
.done( function(){ panel.model.refresh() });
|
||||
}
|
||||
},
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
{"version":3,"file":"pair-collection-creator.js","sources":["../../../src/mvc/collection/pair-collection-creator.js"],"names":["define","LIST_COLLECTION_CREATOR","errorModal","createPairHDCA","collection","elementsJSON","validElements","length","noValidElementsErrorModal","jQuery","Deferred","reject","noValidElementsMessage","name","elementIdentifiers","src","id","createHDCA"],"mappings":"AAAAA,QACI,yCACA,qBACA,sBACD,SAAUC,EAAyBC,GAElC,QAASC,GAAgBC,GAErB,GAAIC,GAAeJ,EAAwBK,cAAeF,EAC1D,KAAKC,EAAaE,OAEd,MADAN,GAAwBO,4BACjBC,OAAOC,WAAWC,OAAQV,EAAwBW,uBAE7D,IAA4B,IAAxBP,EAAaE,OAKb,MAJAL,GACI,gFACA,oBAEGO,OAAOC,WAAWC,OAAQV,EAAwBW,uBAG7D,IAAIC,GAAO,mBACPC,IACMD,KAAM,UAAWE,IAAK,MAAOC,GAAIX,EAAa,GAAGW,KACjDH,KAAM,UAAWE,IAAK,MAAOC,GAAIX,EAAa,GAAGW,IAE3D,OAAOZ,GAAWa,WAAYH,EAAoB,SAAUD,GAGhE,OACIV,eAAiBA"}
|
||||
{"version":3,"file":"pair-collection-creator.js","sources":["../../../src/mvc/collection/pair-collection-creator.js"],"names":["define","LIST_CREATOR","HDCA","errorModal","BASE_MVC","_l","createPairCollection","contents","length","jQuery","Deferred","reject","elements","toJSON","promise","pairCollectionCreatorModal","creationFn","name","src","id","createHDCA","PairedDatasetCollectionElementView","Backbone","View","extend","LoggableMixin","tagName","className","initialize","attributes","this","element","identifier","render","$el","attr","html","template","_","join","destroy","off","remove","toString","_super","ListCollectionCreator","PairCollectionCreator","elementViewClass","collectionClass","HistoryPairDatasetCollection","_mangleDuplicateNames","_renderList","creator","$tmp","each","elementViews","view","removeElementView","workingElements","_renderNoValidElements","append","_createForwardElementView","_createReverseElementView","$list","empty","children","invoke","_createElementView","_listenToElementView","swap","events","clone","prototype","click .swap","templates","middle","helpContent","options","title","collectionCreatorModal"],"mappings":"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"}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +1,2 @@
|
||||
define(["mvc/collection/list-collection-creator","mvc/ui/error-modal","utils/localization"],function(a,b){function c(c){var d=a.validElements(c);if(!d.length)return a.noValidElementsErrorModal(),jQuery.Deferred().reject(a.noValidElementsMessage);if(2!==d.length)return b("When pairing datasets, select only two datasets: one forward and one reverse.","Not a valid pair"),jQuery.Deferred().reject(a.noValidElementsMessage);var e="New Dataset Pair",f=[{name:"forward",src:"hda",id:d[0].id},{name:"reverse",src:"hda",id:d[1].id}];return c.createHDCA(f,"paired",e)}return{createPairHDCA:c}});
|
||||
define(["mvc/collection/list-collection-creator","mvc/history/hdca-model","mvc/ui/error-modal","mvc/base-mvc","utils/localization"],function(a,b,c,d,e){function f(a){if(2!==a.length)return c("When pairing datasets, select only two datasets: one forward and one reverse.","Not a valid pair"),jQuery.Deferred().reject("invalid pair");var b=a.toJSON(),d=j(b,{creationFn:function(b,c){return b=[{name:"forward",src:"hda",id:b[0].id},{name:"reverse",src:"hda",id:b[1].id}],a.createHDCA(b,"paired",c)}});return d}var g=Backbone.View.extend(d.LoggableMixin).extend({tagName:"li",className:"collection-element",initialize:function(a){this.element=a.element||{},this.identifier=a.identifier},render:function(){return this.$el.attr("data-element-id",this.element.id).html(this.template({identifier:this.identifier,element:this.element})),this},template:_.template(['<span class="identifier"><%= identifier %></span>','<span class="name"><%= element.name %></span>'].join("")),destroy:function(){this.off(),this.$el.remove()},toString:function(){return"DatasetCollectionElementView()"}}),h=a.ListCollectionCreator,i=h.extend({elementViewClass:g,collectionClass:b.HistoryPairDatasetCollection,className:"pair-collection-creator collection-creator flex-row-container",_mangleDuplicateNames:function(){},_renderList:function(){var a=this,b=jQuery("<div/>");return _.each(this.elementViews,function(b){b.destroy(),a.removeElementView(b)}),this.workingElements.length<2?void this._renderNoValidElements():(b.append(a._createForwardElementView().$el),b.append(a._createReverseElementView().$el),a.$list().empty().append(b.children()),void _.invoke(a.elementViews,"render"))},_createForwardElementView:function(){var a=this.workingElements[0],b=this._createElementView(a);return b.identifier=e("Forward"),b},_createReverseElementView:function(){var a=this.workingElements[1],b=this._createElementView(a);return b.identifier=e("Reverse"),b},_listenToElementView:function(){},swap:function(){this.workingElements=[this.workingElements[1],this.workingElements[0]],this._renderList()},events:_.extend(_.clone(h.prototype.events),{"click .swap":"swap"}),templates:_.extend(_.clone(h.prototype.templates),{middle:_.template(['<div class="collection-elements-controls">','<a class="swap" href="javascript:void(0);" title="',e("Swap forward and reverse datasets"),'">',e("Swap"),"</a>","</div>",'<div class="collection-elements scroll-container flex-row">',"</div>"].join("")),helpContent:_.template(["<p>",e(["Pair collections are permanent collections containing two datasets: one forward and one reverse. ","Often these are forward and reverse reads. The pair collections can be passed to tools and ","workflows in order to have analyses done on both datasets. This interface allows ","you to create a pair, name it, and swap which is forward and which reverse."].join("")),"</p>","<ul>","<li>",e(['Click the <i data-target=".swap">"Swap"</i> link to make your forward dataset the reverse ',"and the reverse dataset forward."].join("")),"</li>","<li>",e(['Click the <i data-target=".cancel-create">"Cancel"</i> button to exit the interface.'].join("")),"</li>","</ul><br />","<p>",e(['Once your collection is complete, enter a <i data-target=".collection-name">name</i> and ','click <i data-target=".create-collection">"Create list"</i>.'].join("")),"</p>"].join(""))}),toString:function(){return"PairCollectionCreator"}}),j=function(b,c){return c=c||{},c.title=e("Create a collection from a pair of datasets"),a.collectionCreatorModal(b,c,i)};return{PairCollectionCreator:i,pairCollectionCreatorModal:j,createPairCollection:f}});
|
||||
//# sourceMappingURL=../../../maps/mvc/collection/pair-collection-creator.js.map
|
||||
File diff suppressed because one or more lines are too long
@@ -2277,6 +2277,16 @@ pre.peek table,pre.peek th,pre.peek tr,pre.peek td{font-family:Monaco,Menlo,Cons
|
||||
.collection-creator.list-collection-creator .element-drop-placeholder{width:60px;height:3px;margin:2px 0px 0px 6px;background:black}.collection-creator.list-collection-creator .element-drop-placeholder:before{float:left;font-size:120%;margin:-9px 0 0 -6px;font-family:FontAwesome;content:'\f0da'}
|
||||
.collection-creator.list-collection-creator .element-drop-placeholder:last-child{margin-bottom:4px}
|
||||
.collection-creator.list-collection-creator .empty-message{margin:8px;color:grey;font-style:italic;text-align:center}
|
||||
.collection-creator.pair-collection-creator .footer{margin-top:8px}
|
||||
.collection-creator.pair-collection-creator .main-help{cursor:pointer}
|
||||
.collection-creator.pair-collection-creator .collection-elements-controls{margin-bottom:8px}.collection-creator.pair-collection-creator .collection-elements-controls .clear-selected{float:right !important;float:right;display:none}
|
||||
.collection-creator.pair-collection-creator .collection-elements{max-height:400px;overflow-y:auto;overflow-x:hidden}
|
||||
.collection-creator.pair-collection-creator .collection-element{height:32px;margin:2px 4px 0px 4px;opacity:1.0;border:1px solid lightgrey;border-radius:3px;padding:0 8px 0 8px;line-height:28px;cursor:pointer;overflow:hidden}.collection-creator.pair-collection-creator .collection-element:last-of-type{margin-bottom:2px}
|
||||
.collection-creator.pair-collection-creator .collection-element:hover{border-color:black}
|
||||
.collection-creator.pair-collection-creator .collection-element button{margin-top:3px}
|
||||
.collection-creator.pair-collection-creator .collection-element .identifier:after{content:':';margin-right:6px}
|
||||
.collection-creator.pair-collection-creator .collection-element .name:hover{text-decoration:auto}
|
||||
.collection-creator.pair-collection-creator .empty-message{margin:8px;color:grey;font-style:italic;text-align:center}
|
||||
.collection-creator.list-of-pairs-collection-creator .column-headers{margin-bottom:8px}
|
||||
.search-input .search-query{width:100%;padding-right:24px}
|
||||
.search-input .search-clear,.search-input .search-loading{position:relative;display:inline-block;float:right;margin-top:-24px;margin-right:4px;font-size:1.4em;line-height:23px;color:grey}
|
||||
|
||||
@@ -534,6 +534,68 @@
|
||||
|
||||
// ======================================================================== pair
|
||||
.collection-creator.pair-collection-creator {
|
||||
.footer {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.main-help {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.collection-elements-controls {
|
||||
margin-bottom: 8px;
|
||||
|
||||
.clear-selected {
|
||||
.pull-right;
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.collection-elements {
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
// TODO: taken from .dataset above - swap these out
|
||||
.collection-element {
|
||||
height: 32px;
|
||||
margin: 2px 4px 0px 4px;
|
||||
opacity: 1.0;
|
||||
border: 1px solid lightgrey;
|
||||
border-radius: 3px;
|
||||
padding: 0 8px 0 8px;
|
||||
line-height: 28px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
|
||||
&:last-of-type {
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
&:hover {
|
||||
border-color: black;
|
||||
}
|
||||
|
||||
button {
|
||||
margin-top: 3px;
|
||||
}
|
||||
.identifier {
|
||||
&:after {
|
||||
content: ':';
|
||||
margin-right: 6px;
|
||||
}
|
||||
}
|
||||
.name {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.empty-message {
|
||||
margin: 8px;
|
||||
color: grey;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
|
||||
// ======================================================================== list of pairs
|
||||
|
||||
@@ -51,17 +51,21 @@ $(function(){
|
||||
define( 'app', function(){
|
||||
require([
|
||||
'mvc/history/history-contents',
|
||||
'mvc/collection/list-collection-creator'
|
||||
], function( HISTORY_CONTENTS, LCC ){
|
||||
// 'mvc/collection/list-collection-creator'
|
||||
'mvc/collection/pair-collection-creator'
|
||||
// ], function( HISTORY_CONTENTS, LCC ){
|
||||
], function( HISTORY_CONTENTS, PCC ){
|
||||
$(function(){
|
||||
var hdas = bootstrapped.hdas.filter( function( hda ){
|
||||
return !( hda.deleted || hda.purged );
|
||||
return ( hda.state === 'ok' )
|
||||
&& !( hda.deleted || hda.purged );
|
||||
});
|
||||
hdas = hdas.slice( 0, 2 )
|
||||
console.debug( hdas );
|
||||
var collection = new HISTORY_CONTENTS.HistoryContents( hdas, { historyId : bootstrapped.history.id })
|
||||
|
||||
// LCC.listCollectionCreatorModal( hdas )
|
||||
LCC.createListCollection( collection )
|
||||
PCC.createPairCollection( collection )
|
||||
.done( function( response ){
|
||||
console.info( 'creation succeeded:', arguments );
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user