Abstraction for re-use between collection creators.

The new mixin reduces the duplication between the list and list of paired collection creators.

I'd like to add functionality related to hiding the original datasets (especially useful for direct upload of collections but previously requested also) but I'd like to reduce the duplication related to doing that first. This is a start in that direction.
This commit is contained in:
John Chilton
2017-03-20 16:16:51 -04:00
parent 5440889bf6
commit 18cb50ecea
15 changed files with 148 additions and 186 deletions
@@ -0,0 +1,106 @@
define([
], function( ){
/* For presentation-related functionality shared across collection creators.
Particularily overlapping functionality related to name processing and help.
*/
var CollectionCreatorMixin = {
/** add (or clear if clear is truthy) a validation warning to the DOM element described in what */
_validationWarning : function( what, clear ){
var VALIDATION_CLASS = 'validation-warning';
if( what === 'name' ){
what = this.$( '.collection-name' ).add( this.$( '.collection-name-prompt' ) );
this.$( '.collection-name' ).focus().select();
}
if( clear ){
what = what || this.$( '.' + VALIDATION_CLASS );
what.removeClass( VALIDATION_CLASS );
} else {
what.addClass( VALIDATION_CLASS );
}
},
// ........................................................................ footer
/** handle a collection name change */
_changeName : function( ev ){
this._validationWarning( 'name', !!this._getName() );
},
/** check for enter key press when in the collection name and submit */
_nameCheckForEnter : function( ev ){
if( ev.keyCode === 13 && !this.blocking ){
this._clickCreate();
}
},
/** get the current collection name */
_getName : function(){
return _.escape( this.$( '.collection-name' ).val() );
},
// ........................................................................ header
/** expand help */
_clickMoreHelp : function( ev ){
ev.stopPropagation();
this.$( '.main-help' ).addClass( 'expanded' );
this.$( '.more-help' ).hide();
},
/** collapse help */
_clickLessHelp : function( ev ){
ev.stopPropagation();
this.$( '.main-help' ).removeClass( 'expanded' );
this.$( '.more-help' ).show();
},
/** toggle help */
_toggleHelp : function( ev ){
ev.stopPropagation();
this.$( '.main-help' ).toggleClass( 'expanded' );
this.$( '.more-help' ).toggle();
},
/** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */
_showAlert : function( message, alertClass ){
alertClass = alertClass || 'alert-danger';
this.$( '.main-help' ).hide();
this.$( '.header .alert' )
.attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show()
.find( '.alert-message' ).html( message );
},
/** hide the alerts at the top */
_hideAlert : function( message ){
this.$( '.main-help' ).show();
this.$( '.header .alert' ).hide();
},
_cancelCreate: function( ev ){
if( typeof this.oncancel === 'function' ){
this.oncancel.call( this );
}
},
/** attempt to create the current collection */
_clickCreate : function( ev ){
var name = this._getName();
if( !name ){
this._validationWarning( 'name' );
} else if( !this.blocking ){
this.createList( name );
}
},
_creatorTemplates: {
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"></div>'
].join('')),
}
}
//==============================================================================
return {
CollectionCreatorMixin: CollectionCreatorMixin
};
});
@@ -3,15 +3,17 @@ define([
"mvc/history/hdca-model",
"mvc/dataset/states",
"mvc/base-mvc",
"mvc/collection/base-creator",
"mvc/ui/ui-modal",
"utils/natural-sort",
"utils/localization",
"ui/hoverhighlight"
], function( HDCA, STATES, BASE_MVC, UI_MODAL, naturalSort, _l ){
], function( HDCA, STATES, BASE_MVC, baseCreator, UI_MODAL, naturalSort, _l ){
'use strict';
var logNamespace = 'collections';
/*==============================================================================
TODO:
use proper Element model and not just json
@@ -151,7 +153,7 @@ var DatasetCollectionElementView = Backbone.View.extend( BASE_MVC.LoggableMixin
// ============================================================================
/** An interface for building collections.
*/
var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend( baseCreator.CollectionCreatorMixin ).extend({
_logNamespace : logNamespace,
/** the class used to display individual elements */
@@ -367,21 +369,6 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
this._showAlert( this.templates.invalidElements({ problems: this.invalidElements }), 'alert-warning' );
},
/** add (or clear if clear is truthy) a validation warning to the DOM element described in what */
_validationWarning : function( what, clear ){
var VALIDATION_CLASS = 'validation-warning';
if( what === 'name' ){
what = this.$( '.collection-name' ).add( this.$( '.collection-name-prompt' ) );
this.$( '.collection-name' ).focus().select();
}
if( clear ){
what = what || this.$( '.' + VALIDATION_CLASS );
what.removeClass( VALIDATION_CLASS );
} else {
what.addClass( VALIDATION_CLASS );
}
},
_disableNameAndCreate : function( disable ){
disable = !_.isUndefined( disable )? disable : true;
if( disable ){
@@ -624,48 +611,10 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
// footer
'change .collection-name' : '_changeName',
'keydown .collection-name' : '_nameCheckForEnter',
'click .cancel-create' : function( ev ){
if( typeof this.oncancel === 'function' ){
this.oncancel.call( this );
}
},
'click .cancel-create' : '_cancelCreate',
'click .create-collection' : '_clickCreate'//,
},
// ........................................................................ header
/** expand help */
_clickMoreHelp : function( ev ){
ev.stopPropagation();
this.$( '.main-help' ).addClass( 'expanded' );
this.$( '.more-help' ).hide();
},
/** collapse help */
_clickLessHelp : function( ev ){
ev.stopPropagation();
this.$( '.main-help' ).removeClass( 'expanded' );
this.$( '.more-help' ).show();
},
/** toggle help */
_toggleHelp : function( ev ){
ev.stopPropagation();
this.$( '.main-help' ).toggleClass( 'expanded' );
this.$( '.more-help' ).toggle();
},
/** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */
_showAlert : function( message, alertClass ){
alertClass = alertClass || 'alert-danger';
this.$( '.main-help' ).hide();
this.$( '.header .alert' )
.attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show()
.find( '.alert-message' ).html( message );
},
/** hide the alerts at the top */
_hideAlert : function( message ){
this.$( '.main-help' ).show();
this.$( '.header .alert' ).hide();
},
// ........................................................................ elements
/** reset all data to the initial state */
reset : function(){
@@ -789,46 +738,12 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
this.$dragging = null;
},
// ........................................................................ footer
/** handle a collection name change */
_changeName : function( ev ){
this._validationWarning( 'name', !!this._getName() );
},
/** check for enter key press when in the collection name and submit */
_nameCheckForEnter : function( ev ){
if( ev.keyCode === 13 && !this.blocking ){
this._clickCreate();
}
},
/** get the current collection name */
_getName : function(){
return _.escape( this.$( '.collection-name' ).val() );
},
/** attempt to create the current collection */
_clickCreate : function( ev ){
var name = this._getName();
if( !name ){
this._validationWarning( 'name' );
} else if( !this.blocking ){
this.createList( name );
}
},
// ------------------------------------------------------------------------ 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"></div>'
].join('')),
templates : _.extend(baseCreator.CollectionCreatorMixin._creatorTemplates, {
/** the header (not including help text) */
header : _.template([
@@ -974,7 +889,7 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
'</div>',
'</div>'
].join('')),
},
}),
// ------------------------------------------------------------------------ misc
/** string rep */
@@ -1,11 +1,11 @@
define([
"utils/levenshtein",
"utils/natural-sort",
"mvc/collection/list-collection-creator",
"mvc/collection/base-creator",
"mvc/base-mvc",
"utils/localization",
"ui/hoverhighlight"
], function( levenshteinDistance, naturalSort, LIST_COLLECTION_CREATOR, baseMVC, _l ){
], function( levenshteinDistance, naturalSort, baseCreator, baseMVC, _l ){
'use strict';
@@ -190,7 +190,7 @@ function autoPairFnBuilder( options ){
// ============================================================================
/** An interface for building collections of paired datasets.
*/
var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).extend({
var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).extend( baseCreator.CollectionCreatorMixin ).extend({
_logNamespace : logNamespace,
className: 'list-of-pairs-collection-creator collection-creator flex-row-container',
@@ -942,6 +942,7 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte
// header
'click .more-help' : '_clickMoreHelp',
'click .less-help' : '_clickLessHelp',
'click .main-help' : '_toggleHelp',
'click .header .alert button' : '_hideAlert',
'click .forward-column .column-title' : '_clickShowOnlyUnpaired',
'click .reverse-column .column-title' : '_clickShowOnlyUnpaired',
@@ -981,39 +982,10 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte
'change .remove-extensions' : function( ev ){ this.toggleExtensions(); },
'change .collection-name' : '_changeName',
'keydown .collection-name' : '_nameCheckForEnter',
'click .cancel-create' : function( ev ){
if( typeof this.oncancel === 'function' ){
this.oncancel.call( this );
}
},
'click .cancel-create' : '_cancelCreate',
'click .create-collection' : '_clickCreate'//,
},
// ........................................................................ header
/** expand help */
_clickMoreHelp : function( ev ){
this.$( '.main-help' ).addClass( 'expanded' );
this.$( '.more-help' ).hide();
},
/** collapse help */
_clickLessHelp : function( ev ){
this.$( '.main-help' ).removeClass( 'expanded' );
this.$( '.more-help' ).show();
},
/** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*)*/
_showAlert : function( message, alertClass ){
alertClass = alertClass || 'alert-danger';
this.$( '.main-help' ).hide();
this.$( '.header .alert' ).attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show()
.find( '.alert-message' ).html( message );
},
/** hide the alerts at the top */
_hideAlert : function( message ){
this.$( '.main-help' ).show();
this.$( '.header .alert' ).hide();
},
/** toggle between showing only unpaired and split view */
_clickShowOnlyUnpaired : function( ev ){
//this.debug( 'click unpaired', ev.currentTarget );
@@ -1419,33 +1391,6 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte
creator._renderFooter();
},
/** handle a collection name change */
_changeName : function( ev ){
this._validationWarning( 'name', !!this._getName() );
},
/** check for enter key press when in the collection name and submit */
_nameCheckForEnter : function( ev ){
if( ev.keyCode === 13 && !this.blocking ){
this._clickCreate();
}
},
/** get the current collection name */
_getName : function(){
return _.escape( this.$( '.collection-name' ).val() );
},
/** attempt to create the current collection */
_clickCreate : function( ev ){
var name = this._getName();
if( !name ){
this._validationWarning( 'name' );
} else if( !this.blocking ){
this.createList();
}
},
// ------------------------------------------------------------------------ misc
/** debug a dataset list */
_printList : function( list ){
@@ -1473,14 +1418,7 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte
//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 */
PairedCollectionCreator.templates = PairedCollectionCreator.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('')),
PairedCollectionCreator.templates = PairedCollectionCreator.templates || _.extend(baseCreator.CollectionCreatorMixin._creatorTemplates, {
/** the header (not including help text) */
header : _.template([
@@ -1665,7 +1603,7 @@ PairedCollectionCreator.templates = PairedCollectionCreator.templates || {
'(Note: you do not have to pair all unpaired datasets to finish.)'
].join( '' )), '</p>'
].join(''))
};
});
//=============================================================================
@@ -0,0 +1 @@
{"version":3,"file":"base-creator.js","sources":["../../../src/mvc/collection/base-creator.js"],"names":["define","CollectionCreatorMixin","_validationWarning","what","clear","VALIDATION_CLASS","this","$","add","focus","select","removeClass","addClass","_changeName","_getName","_nameCheckForEnter","ev","keyCode","blocking","_clickCreate","_","escape","val","_clickMoreHelp","stopPropagation","hide","_clickLessHelp","show","_toggleHelp","toggleClass","toggle","_showAlert","message","alertClass","attr","find","html","_hideAlert","_cancelCreate","oncancel","call","name","createList","_creatorTemplates","main","template","join"],"mappings":"AAAAA,UACG,WAKH,GAAIC,IAGAC,mBAAqB,SAAUC,EAAMC,GACjC,GAAIC,GAAmB,oBACV,UAATF,IACAA,EAAOG,KAAKC,EAAG,oBAAqBC,IAAKF,KAAKC,EAAG,4BACjDD,KAAKC,EAAG,oBAAqBE,QAAQC,UAErCN,GACAD,EAAOA,GAAQG,KAAKC,EAAG,IAAMF,GAC7BF,EAAKQ,YAAaN,IAElBF,EAAKS,SAAUP,IAMvBQ,YAAc,WACVP,KAAKJ,mBAAoB,SAAUI,KAAKQ,aAI5CC,mBAAqB,SAAUC,GACR,KAAfA,EAAGC,SAAmBX,KAAKY,UAC3BZ,KAAKa,gBAKbL,SAAW,WACP,MAAOM,GAAEC,OAAQf,KAAKC,EAAG,oBAAqBe,QAKlDC,eAAiB,SAAUP,GACvBA,EAAGQ,kBACHlB,KAAKC,EAAG,cAAeK,SAAU,YACjCN,KAAKC,EAAG,cAAekB,QAG3BC,eAAiB,SAAUV,GACvBA,EAAGQ,kBACHlB,KAAKC,EAAG,cAAeI,YAAa,YACpCL,KAAKC,EAAG,cAAeoB,QAG3BC,YAAc,SAAUZ,GACpBA,EAAGQ,kBACHlB,KAAKC,EAAG,cAAesB,YAAa,YACpCvB,KAAKC,EAAG,cAAeuB,UAI3BC,WAAa,SAAUC,EAASC,GAC5BA,EAAaA,GAAc,eAC3B3B,KAAKC,EAAG,cAAekB,OACvBnB,KAAKC,EAAG,kBACH2B,KAAM,QAAS,2BAA4BtB,SAAUqB,GAAaN,OAClEQ,KAAM,kBAAmBC,KAAMJ,IAGxCK,WAAa,WACT/B,KAAKC,EAAG,cAAeoB,OACvBrB,KAAKC,EAAG,kBAAmBkB,QAG/Ba,cAAe,WACkB,kBAAlBhC,MAAKiC,UACZjC,KAAKiC,SAASC,KAAMlC,OAK5Ba,aAAe,WACX,GAAIsB,GAAOnC,KAAKQ,UACX2B,GAEOnC,KAAKY,UACbZ,KAAKoC,WAAYD,GAFjBnC,KAAKJ,mBAAoB,SAMjCyC,mBACIC,KAAOxB,EAAEyB,UACL,8CACA,yDACA,+CACFC,KAAK,MAMX,QACI7C,uBAAwBA"}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
webpackJsonp([4],[function(e,r,n){(function(e){var r=n(1),a=r,i=n(57).GalaxyApp,o=n(10),t=n(5),l=n(59);window.app=function(n,c){window.Galaxy=new i(n,c),Galaxy.debug("login app");var d=encodeURI(n.redirect);if(!n.show_welcome_with_login){var w=r.param({use_panels:"True",redirect:d});return void(window.location.href=Galaxy.root+"user/login?"+w)}var p=new l.PageLayoutView(e.extend(n,{el:"body",center:new o.CenterPanel({el:"#center"}),right:new o.RightPanel({title:t("Login required"),el:"#right"})}));a(function(){var e=r.param({redirect:d}),a=Galaxy.root+"user/login?"+e;p.render(),p.center.$("#galaxy_main").prop("src",n.welcome_url),p.right.$(".unified-panel-body").css("overflow","hidden").html('<iframe src="'+a+'" frameborder="0" style="width: 100%; height: 100%;"/>')})}}).call(r,n(2))}]);
webpackJsonp([4],[function(e,r,n){(function(e){var r=n(1),a=r,i=n(56).GalaxyApp,o=n(10),t=n(5),l=n(58);window.app=function(n,c){window.Galaxy=new i(n,c),Galaxy.debug("login app");var d=encodeURI(n.redirect);if(!n.show_welcome_with_login){var w=r.param({use_panels:"True",redirect:d});return void(window.location.href=Galaxy.root+"user/login?"+w)}var p=new l.PageLayoutView(e.extend(n,{el:"body",center:new o.CenterPanel({el:"#center"}),right:new o.RightPanel({title:t("Login required"),el:"#right"})}));a(function(){var e=r.param({redirect:d}),a=Galaxy.root+"user/login?"+e;p.render(),p.center.$("#galaxy_main").prop("src",n.welcome_url),p.right.$(".unified-panel-body").css("overflow","hidden").html('<iframe src="'+a+'" frameborder="0" style="width: 100%; height: 100%;"/>')})}}).call(r,n(2))}]);
//# sourceMappingURL=login.bundled.js.map
File diff suppressed because one or more lines are too long
@@ -0,0 +1,2 @@
define([],function(){var a={_validationWarning:function(a,b){var c="validation-warning";"name"===a&&(a=this.$(".collection-name").add(this.$(".collection-name-prompt")),this.$(".collection-name").focus().select()),b?(a=a||this.$("."+c),a.removeClass(c)):a.addClass(c)},_changeName:function(){this._validationWarning("name",!!this._getName())},_nameCheckForEnter:function(a){13!==a.keyCode||this.blocking||this._clickCreate()},_getName:function(){return _.escape(this.$(".collection-name").val())},_clickMoreHelp:function(a){a.stopPropagation(),this.$(".main-help").addClass("expanded"),this.$(".more-help").hide()},_clickLessHelp:function(a){a.stopPropagation(),this.$(".main-help").removeClass("expanded"),this.$(".more-help").show()},_toggleHelp:function(a){a.stopPropagation(),this.$(".main-help").toggleClass("expanded"),this.$(".more-help").toggle()},_showAlert:function(a,b){b=b||"alert-danger",this.$(".main-help").hide(),this.$(".header .alert").attr("class","alert alert-dismissable").addClass(b).show().find(".alert-message").html(a)},_hideAlert:function(){this.$(".main-help").show(),this.$(".header .alert").hide()},_cancelCreate:function(){"function"==typeof this.oncancel&&this.oncancel.call(this)},_clickCreate:function(){var a=this._getName();a?this.blocking||this.createList(a):this._validationWarning("name")},_creatorTemplates:{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"></div>'].join(""))}};return{CollectionCreatorMixin:a}});
//# sourceMappingURL=../../../maps/mvc/collection/base-creator.js.map
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long