Skip to content

Commit 0d6f076

Browse files
committed
Allow upload to collections.
- New upload tab for "Collections". - This has a new option to select "Collection Type" in footer. - Collection upload geared toward homogeneous datasets - must specify genome and file format for all files. - New button "Build" after all individual datasets have finished their upload to the server. - Clicking "Build" launches the appropriate collection builder for selected collection type. - By default, uploading a collection hides the original uploaded datasets (can be unchecked). Implement tests for all uploaded collection types.
1 parent 82ca693 commit 0d6f076

31 files changed

+794
-74
lines changed

client/galaxy/scripts/mvc/collection/base-creator.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@ var CollectionCreatorMixin = {
9393
}
9494
},
9595

96-
_setUpCommonSettings : function( ) {
97-
this.hideOriginals = false;
96+
_setUpCommonSettings : function( attributes ) {
97+
this.hideOriginals = attributes.defaultHideSourceItems || false;
9898
},
9999

100100
/** render the footer, completion controls, and cancel controls */

client/galaxy/scripts/mvc/collection/list-collection-creator.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten
195195
/** unordered, original list - cache to allow reversal */
196196
creator.initialElements = attributes.elements || [];
197197

198-
this._setUpCommonSettings();
198+
this._setUpCommonSettings( attributes );
199199
this._instanceSetUp();
200200
this._elementsSetUp();
201201
this._setUpBehaviors();
@@ -948,9 +948,10 @@ var listCollectionCreatorModal = function _listCollectionCreatorModal( elements,
948948
/** Use a modal to create a list collection, then add it to the given history contents.
949949
* @returns {Deferred} resolved when the collection is added to the history.
950950
*/
951-
function createListCollection( contents ){
951+
function createListCollection( contents, defaultHideSourceItems ){
952952
var elements = contents.toJSON(),
953953
promise = listCollectionCreatorModal( elements, {
954+
defaultHideSourceItems: defaultHideSourceItems,
954955
creationFn : function( elements, name, hideSourceItems ){
955956
elements = elements.map( function( element ){
956957
return {

client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte
259259
/** Used for blocking UI events during ajax/operations (don't post twice) */
260260
this.blocking = false;
261261

262-
this._setUpCommonSettings();
262+
this._setUpCommonSettings( attributes );
263263
this._setUpBehaviors();
264264
this._dataSetUp();
265265
},
@@ -1642,11 +1642,12 @@ var pairedCollectionCreatorModal = function _pairedCollectionCreatorModal( datas
16421642

16431643

16441644
//=============================================================================
1645-
function createListOfPairsCollection( collection ){
1645+
function createListOfPairsCollection( collection, defaultHideSourceItems ){
16461646
var elements = collection.toJSON();
16471647
//TODO: validate elements
16481648
return pairedCollectionCreatorModal( elements, {
1649-
historyId : collection.historyId
1649+
historyId : collection.historyId,
1650+
defaultHideSourceItems: defaultHideSourceItems
16501651
});
16511652
}
16521653

client/galaxy/scripts/mvc/collection/pair-collection-creator.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -230,9 +230,10 @@ var pairCollectionCreatorModal = function _pairCollectionCreatorModal( elements,
230230
/** Use a modal to create a pair collection, then add it to the given history contents.
231231
* @returns {Deferred} resolved when the collection is added to the history.
232232
*/
233-
function createPairCollection( contents ){
233+
function createPairCollection( contents, defaultHideSourceItems ){
234234
var elements = contents.toJSON(),
235235
promise = pairCollectionCreatorModal( elements, {
236+
defaultHideSourceItems: defaultHideSourceItems,
236237
creationFn : function( elements, name, hideSourceItems ){
237238
elements = [
238239
{ name: "forward", src: "hda", id: elements[0].id },

client/galaxy/scripts/mvc/history/history-view-edit.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,9 +295,10 @@ var HistoryViewEdit = _super.extend(
295295
];
296296
},
297297

298-
buildCollection : function( collectionType, selection ) {
298+
buildCollection : function( collectionType, selection, hideSourceItems ) {
299299
var panel = this;
300300
var selection = selection || panel.getSelectedModels();
301+
var hideSourceItems = hideSourceItems || false;
301302
var createFunc;
302303
if( collectionType == "list" ) {
303304
createFunc = LIST_COLLECTION_CREATOR.createListCollection;
@@ -308,7 +309,7 @@ var HistoryViewEdit = _super.extend(
308309
} else {
309310
console.warn( "Unknown collectionType encountered " + collectionType );
310311
}
311-
createFunc( selection ).done( function() { panel.model.refresh() } );
312+
createFunc( selection, hideSourceItems ).done( function() { panel.model.refresh() } );
312313
},
313314

314315
// ------------------------------------------------------------------------ sub-views
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
/** Renders the collection uploader rows */
2+
define( [ 'utils/utils', 'mvc/upload/upload-model', 'mvc/upload/upload-settings', 'mvc/ui/ui-popover', 'mvc/ui/ui-select' ],
3+
function( Utils, UploadModel, UploadSettings, Popover, Select ) {
4+
return Backbone.View.extend({
5+
/** Dictionary of upload states and associated icons */
6+
status_classes : {
7+
init : 'upload-icon-button fa fa-trash-o',
8+
queued : 'upload-icon fa fa-spinner fa-spin',
9+
running : 'upload-icon fa fa-spinner fa-spin',
10+
success : 'upload-icon-button fa fa-check',
11+
error : 'upload-icon-button fa fa-exclamation-triangle'
12+
},
13+
14+
initialize: function( app, options ) {
15+
var self = this;
16+
this.app = app;
17+
this.model = options.model;
18+
this.setElement( this._template( options.model ) );
19+
this.$mode = this.$( '.upload-mode' );
20+
this.$title = this.$( '.upload-title-extended' );
21+
this.$text = this.$( '.upload-text' );
22+
this.$size = this.$( '.upload-size' );
23+
this.$info_text = this.$( '.upload-info-text' );
24+
this.$info_progress = this.$( '.upload-info-progress' );
25+
this.$text_content = this.$( '.upload-text-content' );
26+
this.$symbol = this.$( '.upload-symbol' );
27+
this.$progress_bar = this.$( '.upload-progress-bar' );
28+
this.$percentage = this.$( '.upload-percentage' );
29+
30+
// append popup to settings icon
31+
this.settings = new Popover.View({
32+
title : 'Upload configuration',
33+
container : this.$( '.upload-settings' ),
34+
placement : 'bottom'
35+
});
36+
37+
// identify default genome and extension values
38+
var default_genome = this.app.select_genome.value();
39+
var default_extension = this.app.select_extension.value();
40+
41+
// handle click event
42+
this.$symbol.on('click', function() { self._removeRow(); });
43+
44+
// handle text editing event
45+
this.$text_content.on( 'change input', function( e ) {
46+
self.model.set( { 'url_paste': $( e.target ).val(),
47+
'file_size': $( e.target ).val().length } );
48+
});
49+
50+
// model events
51+
this.listenTo( this.model, 'change:percentage', function() { self._refreshPercentage() } );
52+
this.listenTo( this.model, 'change:status', function() { self._refreshStatus() } );
53+
this.listenTo( this.model, 'change:info', function() { self._refreshInfo() } );
54+
this.listenTo( this.model, 'change:file_size', function() { self._refreshFileSize() } );
55+
this.listenTo( this.model, 'remove', function() { self.remove() } );
56+
this.app.collection.on('reset', function() { self.remove() } );
57+
},
58+
59+
render: function() {
60+
var options = this.model.attributes;
61+
this.$title.html( _.escape( options.file_name ) );
62+
this.$size.html( Utils.bytesToString ( options.file_size ) );
63+
this.$mode.removeClass().addClass( 'upload-mode' ).addClass( 'text-primary' );
64+
if ( options.file_mode == 'new' ) {
65+
this.$text.css( { 'width' : this.$el.width() - 16 + 'px', 'top' : this.$el.height() - 8 + 'px' } ).show();
66+
this.$el.height( this.$el.height() - 8 + this.$text.height() + 16 );
67+
this.$mode.addClass( 'fa fa-edit' );
68+
} else if ( options.file_mode == 'local' ) {
69+
this.$mode.addClass( 'fa fa-laptop' );
70+
} else if ( options.file_mode == 'ftp' ) {
71+
this.$mode.addClass( 'fa fa-folder-open-o' );
72+
}
73+
},
74+
75+
/** Refresh info text */
76+
_refreshInfo: function() {
77+
var info = this.model.get( 'info' );
78+
if ( info ) {
79+
this.$info_text.html( '<strong>Failed: </strong>' + info ).show();
80+
} else {
81+
this.$info_text.hide();
82+
}
83+
},
84+
85+
/** Refresh percentage status */
86+
_refreshPercentage : function() {
87+
var percentage = parseInt( this.model.get( 'percentage' ) );
88+
this.$progress_bar.css( { width : percentage + '%' } );
89+
this.$percentage.html( percentage != 100 ? percentage + '%' : 'Adding to history...' );
90+
},
91+
92+
/** Refresh status */
93+
_refreshStatus : function() {
94+
var status = this.model.get( 'status' );
95+
this.$symbol.removeClass().addClass( 'upload-symbol' ).addClass( this.status_classes[ status ] );
96+
this.model.set( 'enabled', status == 'init' );
97+
var enabled = this.model.get( 'enabled' );
98+
this.$text_content.attr( 'disabled', !enabled );
99+
if ( status == 'success' ) {
100+
this.$el.addClass( 'success' );
101+
this.$percentage.html( '100%' );
102+
}
103+
if ( status == 'error' ) {
104+
this.$el.addClass( 'danger' );
105+
this.$info_progress.hide();
106+
}
107+
},
108+
109+
/** Refresh file size */
110+
_refreshFileSize: function() {
111+
this.$size.html( Utils.bytesToString ( this.model.get( 'file_size' ) ) );
112+
},
113+
114+
/** Remove row */
115+
_removeRow: function() {
116+
if ( [ 'init', 'success', 'error' ].indexOf( this.model.get( 'status' ) ) !== -1 ) {
117+
this.app.collection.remove( this.model );
118+
}
119+
},
120+
121+
/** Attach file info popup */
122+
_showSettings : function() {
123+
if ( !this.settings.visible ) {
124+
this.settings.empty();
125+
this.settings.append( ( new UploadSettings( this ) ).$el );
126+
this.settings.show();
127+
} else {
128+
this.settings.hide();
129+
}
130+
},
131+
132+
/** View template */
133+
_template: function( options ) {
134+
return '<tr id="upload-row-' + options.id + '" class="upload-row">' +
135+
'<td>' +
136+
'<div class="upload-text-column">' +
137+
'<div class="upload-mode"/>' +
138+
'<div class="upload-title-extended"/>' +
139+
'<div class="upload-text">' +
140+
'<div class="upload-text-info">You can tell Galaxy to download data from web by entering URL in this box (one per line). You can also directly paste the contents of a file.</div>' +
141+
'<textarea class="upload-text-content form-control"/>' +
142+
'</div>' +
143+
'</div>' +
144+
'</td>' +
145+
'<td>' +
146+
'<div class="upload-size"/>' +
147+
'</td>' +
148+
'<td>' +
149+
'<div class="upload-info">' +
150+
'<div class="upload-info-text"/>' +
151+
'<div class="upload-info-progress progress">' +
152+
'<div class="upload-progress-bar progress-bar progress-bar-success"/>' +
153+
'<div class="upload-percentage">0%</div>' +
154+
'</div>' +
155+
'</div>' +
156+
'</td>' +
157+
'<td>' +
158+
'<div class="upload-symbol ' + this.status_classes.init + '"/>' +
159+
'</td>' +
160+
'</tr>';
161+
}
162+
});
163+
});

0 commit comments

Comments
 (0)