[galaxy-commits] commit/galaxy-central: natefoo: Merge stable to default

commits-noreply at bitbucket.org commits-noreply at bitbucket.org
Wed Apr 22 15:37:31 EDT 2015


1 new commit in galaxy-central:

https://bitbucket.org/galaxy/galaxy-central/commits/0aa4dd8af7cf/
Changeset:   0aa4dd8af7cf
User:        natefoo
Date:        2015-04-22 19:35:19+00:00
Summary:     Merge stable to default
Affected #:  61 files

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -25,4 +25,5 @@
 5cdf5dc395f16f47e88a5567775dcd21b4906f08 latest_2015.01.13
 738f4ad0eb62d5e4bcf0d22a2722ee6c570382b9 v15.03
 9f40ff3e3fe1f7fed7e055d4269fe83199cf5ed2 v15.03.1
-9f40ff3e3fe1f7fed7e055d4269fe83199cf5ed2 latest_15.03
+bfd4635011e39aa210b2b1498dd65831dd2a365e v15.03.2
+bfd4635011e39aa210b2b1498dd65831dd2a365e latest_15.03

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/history/history-model.js
--- a/client/galaxy/scripts/mvc/history/history-model.js
+++ b/client/galaxy/scripts/mvc/history/history-model.js
@@ -257,7 +257,7 @@
 
     setAsCurrent : function(){
         var history = this,
-            xhr = jQuery.getJSON( '/history/set_as_current?id=' + this.id );
+            xhr = jQuery.getJSON( galaxy_config.root + 'history/set_as_current?id=' + this.id );
 
         xhr.done( function(){
             history.trigger( 'set-as-current', history );
@@ -361,7 +361,7 @@
 var HistoryCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
 /** @lends HistoryCollection.prototype */{
     model   : History,
-    
+
     /** logger used to record this.log messages, commonly set to console */
     //logger              : console,
 

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/library/library-dataset-view.js
--- a/client/galaxy/scripts/mvc/library/library-dataset-view.js
+++ b/client/galaxy/scripts/mvc/library/library-dataset-view.js
@@ -116,7 +116,7 @@
   },
 
   downloadDataset: function(){
-    var url = '/api/libraries/datasets/download/uncompressed';
+    var url = ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/download/uncompressed';
     var data = {'ld_ids' : this.id};
     this.processDownload(url, data);
   },
@@ -232,7 +232,7 @@
 
     var self = this;
     if (this.options.fetched_permissions === undefined){
-      $.get( "/api/libraries/datasets/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
+      $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
         self.prepareSelectBoxes({fetched_permissions:fetched_permissions, is_admin:is_admin});
       }).fail(function(){
           mod_toastr.error('An error occurred while attempting to fetch dataset permissions.');
@@ -273,7 +273,7 @@
               placeholder: 'Click to select a role',
               container: self.$el.find('#access_perm'),
               ajax: {
-                  url: "/api/libraries/datasets/" + self.id + "/permissions?scope=available",
+                  url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available",
                   dataType: 'json',
                   quietMillis: 100,
                   data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -320,7 +320,7 @@
               placeholder: 'Click to select a role',
               container: self.$el.find('#modify_perm'),
               ajax: {
-                  url: "/api/libraries/datasets/" + self.id + "/permissions?scope=available",
+                  url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available",
                   dataType: 'json',
                   quietMillis: 100,
                   data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -367,7 +367,7 @@
               placeholder: 'Click to select a role',
               container: self.$el.find('#manage_perm'),
               ajax: {
-                  url: "/api/libraries/datasets/" + self.id + "/permissions?scope=available",
+                  url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available",
                   dataType: 'json',
                   quietMillis: 100,
                   data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -413,7 +413,7 @@
             self.manageSelectObject = new mod_select.View(manage_select_options);
         } else { // Non-admins have select with pre-loaded options
             var template = self.templateAccessSelect();
-            $.get( "/api/libraries/datasets/" + self.id + "/permissions?scope=available", function( data ) {
+            $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available", function( data ) {
                 $('.access_perm').html(template({options:data.roles}));
                 self.accessSelectObject = $('#access_select').select2();
             }).fail(function() {
@@ -436,7 +436,7 @@
 
   makeDatasetPrivate: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
       self.model.set({is_unrestricted:false});
       self.showPermissions({fetched_permissions:fetched_permissions})
       mod_toastr.success('The dataset is now private to you.');
@@ -447,7 +447,7 @@
 
   removeDatasetRestrictions: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
     .done(function(fetched_permissions) {
       self.model.set({is_unrestricted:true});
       self.showPermissions({fetched_permissions:fetched_permissions})
@@ -478,7 +478,7 @@
       modify_ids.push(modify_roles[i].id);
     };
 
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
     .done(function(fetched_permissions){
       //fetch dataset again
       self.showPermissions({fetched_permissions:fetched_permissions})

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/library/library-folder-view.js
--- a/client/galaxy/scripts/mvc/library/library-folder-view.js
+++ b/client/galaxy/scripts/mvc/library/library-folder-view.js
@@ -81,7 +81,7 @@
 
     var self = this;
     if (this.options.fetched_permissions === undefined){
-      $.get( "/api/folders/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
+      $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/folders/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
         self.prepareSelectBoxes({fetched_permissions:fetched_permissions});
       }).fail(function(){
           mod_toastr.error('An error occurred while attempting to fetch folder permissions.');
@@ -125,7 +125,7 @@
       placeholder: 'Click to select a role',
       container: self.$el.find('#' + id),
       ajax: {
-          url: "/api/folders/" + self.id + "/permissions?scope=available",
+          url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/folders/" + self.id + "/permissions?scope=available",
           dataType: 'json',
           quietMillis: 100,
           data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -195,7 +195,7 @@
     var manage_ids = this._extractIds(this.manageSelectObject.$el.select2('data'));
     var modify_ids = this._extractIds(this.modifySelectObject.$el.select2('data'));
 
-    $.post("/api/folders/" + self.id + "/permissions?action=set_permissions", { 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/folders/" + self.id + "/permissions?action=set_permissions", { 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
     .done(function(fetched_permissions){
       //fetch dataset again
       self.showPermissions({fetched_permissions:fetched_permissions})

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js
--- a/client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js
+++ b/client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js
@@ -294,7 +294,7 @@
                 dataset_ids.push( this.parentElement.parentElement.id );
             }
         } );
-    var url = '/api/libraries/datasets/download/' + format;
+    var url = ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/download/' + format;
     var data = { 'ld_ids' : dataset_ids };
     this.processDownload( url, data, 'get' );
   },
@@ -386,7 +386,7 @@
   fetchExtAndGenomes: function(){
     var that = this;
     mod_utils.get({
-        url      :  galaxy_config.root + "api/datatypes?extension_only=False",
+        url      :  ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/datatypes?extension_only=False",
         success  :  function( datatypes ) {
                         for (key in datatypes) {
                             that.list_extensions.push({
@@ -403,7 +403,7 @@
                     }
       });
     mod_utils.get({
-        url:    galaxy_config.root + "api/genomes",
+        url:    ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/genomes",
         success: function( genomes ) {
                     for ( key in genomes ) {
                         that.list_genomes.push({
@@ -689,7 +689,7 @@
       for ( var i = history_dataset_ids.length - 1; i >= 0; i-- ) {
         history_dataset_id = history_dataset_ids[i];
         var folder_item = new mod_library_model.Item();
-        folder_item.url = '/api/folders/' + this.options.id + '/contents';
+        folder_item.url = ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/folders/' + this.options.id + '/contents';
         folder_item.set( { 'from_hda_id':history_dataset_id } );
         hdas_to_add.push( folder_item );
       }
@@ -749,7 +749,7 @@
       }
       return true;
     }
-    var promise = $.when( $.post( '/api/libraries/datasets?encoded_folder_id=' + that.id + 
+    var promise = $.when( $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets?encoded_folder_id=' + that.id + 
                                                        '&source=' + options.source +
                                                        '&path=' + popped_item +
                                                        '&file_type=' + options.file_type +
@@ -788,7 +788,7 @@
       }
       return true;
     }
-    var promise = $.when( $.post( '/api/libraries/datasets?encoded_folder_id=' + that.id +
+    var promise = $.when( $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets?encoded_folder_id=' + that.id +
                                                           '&source=' + options.source +
                                                           '&path=' + popped_item +
                                                           '&preserve_dirs=' + options.preserve_dirs +

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/library/library-library-view.js
--- a/client/galaxy/scripts/mvc/library/library-library-view.js
+++ b/client/galaxy/scripts/mvc/library/library-library-view.js
@@ -87,7 +87,7 @@
 
     var self = this;
     if (this.options.fetched_permissions === undefined){
-      $.get( "/api/libraries/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
+      $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
         self.prepareSelectBoxes({fetched_permissions:fetched_permissions});
       }).fail(function(){
           mod_toastr.error('An error occurred while attempting to fetch library permissions.');
@@ -134,7 +134,7 @@
       placeholder: 'Click to select a role',
       container: self.$el.find('#' + id),
       ajax: {
-          url: "/api/libraries/" + self.id + "/permissions?scope=available&is_library_access=" + is_library_access,
+          url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/" + self.id + "/permissions?scope=available&is_library_access=" + is_library_access,
           dataType: 'json',
           quietMillis: 100,
           data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -193,7 +193,7 @@
 
   makeDatasetPrivate: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
       self.model.set({is_unrestricted:false});
       self.showPermissions({fetched_permissions:fetched_permissions})
       mod_toastr.success('The dataset is now private to you.');
@@ -204,7 +204,7 @@
 
   removeDatasetRestrictions: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
     .done(function(fetched_permissions) {
       self.model.set({is_unrestricted:true});
       self.showPermissions({fetched_permissions:fetched_permissions})
@@ -230,7 +230,7 @@
     var manage_ids = this._extractIds(this.manageSelectObject.$el.select2('data'));
     var modify_ids = this._extractIds(this.modifySelectObject.$el.select2('data'));
 
-    $.post("/api/libraries/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
     .done(function(fetched_permissions){
       //fetch dataset again
       self.showPermissions({fetched_permissions:fetched_permissions})

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/library/library-model.js
--- a/client/galaxy/scripts/mvc/library/library-model.js
+++ b/client/galaxy/scripts/mvc/library/library-model.js
@@ -4,7 +4,7 @@
 // LIBRARY RELATED MODELS
 
     var Library = Backbone.Model.extend({
-      urlRoot: '/api/libraries/',
+      urlRoot: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/',
 
       /** based on show_deleted would this lib show in the list of lib's?
        *  @param {Boolean} show_deleted are we including deleted libraries?
@@ -19,7 +19,7 @@
     });
 
     var Libraries = Backbone.Collection.extend({
-      url: '/api/libraries',
+      url: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries',
 
       model: Library,
 
@@ -84,15 +84,15 @@
 // FOLDER RELATED MODELS
 
     var Item = Backbone.Model.extend({
-      urlRoot : '/api/libraries/datasets/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/'
     });
 
     var Ldda = Backbone.Model.extend({
-      urlRoot : '/api/libraries/datasets/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/'
     });
 
     var FolderAsModel = Backbone.Model.extend({
-      urlRoot: '/api/folders'
+      urlRoot: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/folders'
     });
 
     var Folder = Backbone.Collection.extend({
@@ -152,7 +152,7 @@
     var FolderContainer = Backbone.Model.extend({
         defaults : {
             folder : new Folder(),
-            urlRoot : "/api/folders/",
+            urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/folders/',
             id : "unknown"
         },
     parse : function(obj) {
@@ -169,11 +169,11 @@
 // TODO UNITE
 
     var HistoryItem = Backbone.Model.extend({
-      urlRoot : '/api/histories/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories/'
     });
 
     var HistoryContents = Backbone.Collection.extend({
-      urlRoot : '/api/histories/',
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories/',
       initialize: function(options){
         this.id = options.id;
       },
@@ -184,11 +184,11 @@
     });
 
     var GalaxyHistory = Backbone.Model.extend({
-      urlRoot : '/api/histories/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories/'
     });
 
     var GalaxyHistories = Backbone.Collection.extend({
-      url : '/api/histories',
+      url : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories',
       model : GalaxyHistory
     });
 
@@ -199,7 +199,7 @@
      */
     
     var Jstree = Backbone.Model.extend({
-      urlRoot: '/api/remote_files'
+      urlRoot: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/remote_files'
     });
 
 return {

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/mvc/tools/tools-parameters.js
--- a/client/galaxy/scripts/mvc/tools/tools-parameters.js
+++ b/client/galaxy/scripts/mvc/tools/tools-parameters.js
@@ -145,6 +145,7 @@
                 data        : options,
                 error_text  : input_def.error_text || 'No options available',
                 multiple    : input_def.multiple,
+                optional    : input_def.optional,
                 searchable  : input_def.searchable,
                 onchange    : function() {
                     self.app.trigger('refresh');

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca client/galaxy/scripts/viz/circster.js
--- a/client/galaxy/scripts/viz/circster.js
+++ b/client/galaxy/scripts/viz/circster.js
@@ -1,16 +1,20 @@
 // load required libraries
-require(
-[
+require([
     'utils/utils',
-    'mvc/ui/icon-button',
-    'libs/farbtastic',
-], function(mod_utils, mod_icon_btn)
+], function(mod_utils)
 {
     // load css
     mod_utils.cssLoadFile("static/style/circster.css");
 });
 
-define(["libs/underscore", "libs/d3", "viz/visualization", "utils/config"], function(_, d3, visualization, config) {
+define([
+    "libs/underscore",
+    "libs/d3",
+    "viz/visualization",
+    "utils/config",
+    'mvc/ui/icon-button',
+    'libs/farbtastic'
+], function(_, d3, visualization, config, mod_icon_btn) {
 
 /**
  * Utility class for working with SVG.
@@ -71,7 +75,7 @@
         else {
             tick_coords = [1, 0, 4, 0];
             text_coords = [0, 4, ".35em", ""];
-            
+
         }
 
         ticks.append("line")
@@ -80,7 +84,7 @@
              .attr("x2", tick_coords[2])
              .attr("y1", tick_coords[3])
              .style("stroke", "#000");
-        
+
         return ticks.append("text")
                     .attr("x", text_coords[0])
                     .attr("y", text_coords[1])
@@ -98,11 +102,11 @@
         // Use default of 2 sig. digits.
         if (sigDigits === undefined)
             sigDigits = 2;
-       
+
         // Verify input number
         if (num === null)
             return null;
-       
+
         // Calculate return value
         var rval = null;
         if (Math.abs(num) < 1) {
@@ -141,7 +145,7 @@
  */
 var CircsterView = Backbone.View.extend({
     className: 'circster',
-    
+
     initialize: function(options) {
         this.genome = options.genome;
         this.label_arc_height = 50;
@@ -188,7 +192,7 @@
             track_gap = this.model.get('config').get_value('track_gap'),
             // Subtract 20 to make sure chrom labels are on screen.
             min_dimension = Math.min(this.$el.width(), this.$el.height()) - 20,
-            // Compute radius start based on model, will be centered 
+            // Compute radius start based on model, will be centered
             // and fit entirely inside element by default.
             radius_start = min_dimension / 2 -
                             circular_tracks.length * (dataset_arc_height + track_gap) +
@@ -198,14 +202,14 @@
 
             // Compute range of track starting radii.
             tracks_start_radii = d3.range(radius_start, min_dimension / 2, dataset_arc_height + track_gap);
-            
+
         // Map from track start to bounds.
         var self = this;
         return _.map(tracks_start_radii, function(radius) {
             return [radius, radius + dataset_arc_height];
         });
     },
-    
+
     /**
      * Renders circular tracks, chord tracks, and label tracks.
      */
@@ -254,7 +258,7 @@
                 }))
                 .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")")
               .append('svg:g').attr('class', 'tracks');
-                
+
         // -- Render circular tracks. --
 
         // Create a view for each track in the visualization and render.
@@ -266,12 +270,12 @@
                     genome: self.genome,
                     total_gap: total_gap
                 });
-            
+
             view.render();
-            
+
             return view;
         });
-        
+
         // -- Render chords tracks. --
 
         this.chords_views = chords_tracks.map(function(track) {
@@ -289,10 +293,10 @@
         });
 
         // -- Render label track. --
-        
+
         // Track bounds are:
         // (a) outer radius of last circular track;
-        // (b) 
+        // (b)
         var outermost_radius = this.circular_views[this.circular_views.length-1].radius_bounds[1],
             track_bounds = [
                 outermost_radius,
@@ -305,7 +309,7 @@
             genome: self.genome,
             total_gap: total_gap
         });
-        
+
         this.label_track_view.render();
     },
 
@@ -356,7 +360,7 @@
 
             // Update label track.
             /*
-            FIXME: should never have to update label track because vis always expands to fit area 
+            FIXME: should never have to update label track because vis always expands to fit area
             within label track.
             var track_bounds = new_track_bounds[ new_track_bounds.length-1 ];
             track_bounds[1] = track_bounds[0];
@@ -373,7 +377,7 @@
         var track_view = this.circular_views[options.index];
         this.circular_views.splice(options.index, 1);
         track_view.$el.remove();
-        
+
         // Recompute and update track bounds.
         var new_track_bounds = this.get_tracks_bounds();
         _.each(this.circular_views, function(track_view, i) {
@@ -392,7 +396,7 @@
         _.each(this.chords_views, function(track_view) {
             track_view.update_radius_bounds(new_track_bounds[0]);
         });
-        
+
     }
 });
 
@@ -455,7 +459,7 @@
 
             // Append titles to paths.
             chroms_paths.append("title").text(function(d) { return d.data.chrom; });
-            
+
         // -- Render track data and, when track data is rendered, apply preferences and update chrom_elts fill. --
 
         var self = this,
@@ -490,7 +494,7 @@
         var new_d = d3.svg.arc()
                         .innerRadius(this.radius_bounds[0])
                         .outerRadius(this.radius_bounds[1]);
-        
+
         this.parent_elt.selectAll('g>path.chrom-background').transition().duration(1000).attr('d', new_d);
 
         this._transition_chrom_data();
@@ -511,7 +515,7 @@
         }
 
         // -- Scale increased, so render visible data with more detail. --
-        
+
         var self = this,
             utils = new SVGUtils();
 
@@ -539,7 +543,7 @@
             $.when(data_deferred).then(function(data) {
                 // Remove current data path.
                 path_elt.remove();
-                
+
                 // Update data bounds with new data.
                 self._update_data_bounds();
 
@@ -598,12 +602,12 @@
     _transition_labels: function() {},
 
     /**
-     * Update data bounds. If there are new_bounds, use them; otherwise use 
+     * Update data bounds. If there are new_bounds, use them; otherwise use
      * default data bounds.
      */
     _update_data_bounds: function(new_bounds) {
         var old_bounds = this.data_bounds;
-        this.data_bounds = new_bounds || 
+        this.data_bounds = new_bounds ||
                            this.get_data_bounds(this.track.get('data_manager').get_genome_wide_data(this.genome));
         this._transition_chrom_data();
     },
@@ -624,7 +628,7 @@
 
             // Set min, max value in config so that they can be adjusted. Make this silent
             // because these attributes are watched for changes and the viz is updated
-            // accordingly (set up in initialize). Because we are setting up, we don't want 
+            // accordingly (set up in initialize). Because we are setting up, we don't want
             // the watch to trigger events here.
             track.get('config').set_value('min_value', self.data_bounds[0], {silent: true});
             track.get('config').set_value('max_value', self.data_bounds[1], {silent: true});
@@ -660,7 +664,7 @@
     _get_path_function: function(chrom_arc, chrom_data) {},
 
     /**
-     * Returns arc layouts for genome's chromosomes/contigs. Arcs are arranged in a circle 
+     * Returns arc layouts for genome's chromosomes/contigs. Arcs are arranged in a circle
      * separated by gaps.
      */
     _chroms_layout: function() {
@@ -700,14 +704,14 @@
      * Render labels.
      */
     _render_data: function(svg) {
-        // -- Add chromosome label where it will fit; an alternative labeling mechanism 
+        // -- Add chromosome label where it will fit; an alternative labeling mechanism
         // would be nice for small chromosomes. --
         var self = this,
             chrom_arcs = svg.selectAll('g');
 
         chrom_arcs.selectAll('path')
             .attr('id', function(d) { return 'label-' + d.data.chrom; });
-          
+
         chrom_arcs.append("svg:text")
             .filter(function(d) {
                 return d.endAngle - d.startAngle > self.min_arc_len;
@@ -857,12 +861,12 @@
                 return "rotate(90)";
             };
 
-        // FIXME: 
+        // FIXME:
         // (1) using min_max class below is needed for _update_min_max, which could be improved.
         // (2) showing config on tick click should be replaced by proper track config icon.
 
         // Draw min, max on first chrom only.
-        var ticks = this.drawTicks(this.parent_elt, [ this.chroms_layout[0] ], 
+        var ticks = this.drawTicks(this.parent_elt, [ this.chroms_layout[0] ],
                                    this._data_bounds_ticks_fn(), textTransform, true)
                         .classed('min_max', true);
 
@@ -872,7 +876,7 @@
                 var view = new config.ConfigSettingCollectionView({
                     collection: self.track.get('config')
                 });
-                view.render_in_modal('Configure Track'); 
+                view.render_in_modal('Configure Track');
             });
         });
 
@@ -951,7 +955,7 @@
 var CircsterBigWigTrackView = CircsterQuantitativeTrackView.extend({
 
     get_data_bounds: function(data) {
-        // Set max across dataset by extracting all values, flattening them into a 
+        // Set max across dataset by extracting all values, flattening them into a
         // single array, and getting third quartile.
         var values = _.flatten( _.map(data, function(d) {
             if (d) {
@@ -965,8 +969,8 @@
                 return 0;
             }
         }) );
-        
-        // For max, use 98% quantile in attempt to avoid very large values. However, this max may be 0 
+
+        // For max, use 98% quantile in attempt to avoid very large values. However, this max may be 0
         // for sparsely populated data, so use max in that case.
         return [ _.min(values), this._quantile(values, 0.98) || _.max(values) ];
     }
@@ -1068,13 +1072,13 @@
                 genome              : genome,
                 model               : vis
             });
-        
+
         // Render vizualization
         viz_view.render();
-        
+
         // setup title
         $('#center .unified-panel-header-inner').append(galaxy_config.app.viz_config.title + " " + galaxy_config.app.viz_config.dbkey);
-    
+
         // setup menu
         var menu = mod_icon_btn.create_icon_buttons_menu([
         {
@@ -1100,7 +1104,7 @@
             {
                 // show saving dialog box
                 Galaxy.modal.show({title: "Saving...", body: "progress" });
-     
+
                 // send to server
                 $.ajax({
                     url: galaxy_config.root + "visualization/save",
@@ -1132,11 +1136,11 @@
                 window.location = galaxy_config.root + "visualization/list";
             }
         }], { tooltip_config: { placement: 'bottom' } });
-            
+
         // add menu
         menu.$el.attr("style", "float: right");
         $("#center .unified-panel-header-inner").append(menu.$el);
-            
+
         // manual tooltip config because default gravity is S and cannot be changed
         $(".menu-button").tooltip( { placement: 'bottom' } );
     }

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca config/galaxy.ini.sample
--- a/config/galaxy.ini.sample
+++ b/config/galaxy.ini.sample
@@ -580,6 +580,13 @@
 # requests.
 #nginx_upload_path = False
 
+# Galaxy can also use nginx_upload_module to receive files staged out upon job
+# completion by remote job runners (i.e. Pulsar) that initiate staging
+# operations on the remote end.  See the Galaxy nginx documentation for the
+# corresponding nginx configuration.
+#nginx_upload_job_files_store = False
+#nginx_upload_job_files_path = False
+
 # Have Galaxy manage dynamic proxy component for routing requests to other
 # services based on Galaxy's session cookie.  It will attempt to do this by
 # default though you do need to install node+npm and do an npm install from
@@ -960,6 +967,17 @@
 # always, onsuccess, never
 #cleanup_job = always
 
+# For sites where all users in Galaxy match users on the system on which Galaxy
+# runs, the DRMAA job runner can be configured to submit jobs to the DRM as the
+# actual user instead of as the user running the Galaxy server process.  For
+# details on these options, see the documentation at:
+#
+# http://galaxyproject.org/wiki/Admin/Config/Performance/Cluster
+#
+#drmaa_external_runjob_script = scripts/drmaa_external_runner.py
+#drmaa_external_killjob_script = scripts/drmaa_external_killer.py
+#external_chown_script = scripts/external_chown_script.py
+
 # File to source to set up the environment when running jobs.  By default, the
 # environment in which the Galaxy server starts is used when running jobs
 # locally, and the environment set up per the DRM's submission method and

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca config/job_conf.xml.sample_advanced
--- a/config/job_conf.xml.sample_advanced
+++ b/config/job_conf.xml.sample_advanced
@@ -252,10 +252,7 @@
           --></destination><destination id="real_user_cluster" runner="drmaa">
-            <!-- TODO: The real user options should maybe not be considered runner params. -->
-            <param id="galaxy_external_runjob_script">scripts/drmaa_external_runner.py</param>
-            <param id="galaxy_external_killjob_script">scripts/drmaa_external_killer.py</param>
-            <param id="galaxy_external_chown_script">scripts/external_chown_script.py</param>
+            <!-- Make sure to setup 3 real user parameters in galaxy.ini. --></destination><destination id="dynamic" runner="dynamic"><!-- A destination that represents a method in the dynamic runner. -->

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -293,6 +293,8 @@
         self.nginx_x_archive_files_base = kwargs.get( 'nginx_x_archive_files_base', False )
         self.nginx_upload_store = kwargs.get( 'nginx_upload_store', False )
         self.nginx_upload_path = kwargs.get( 'nginx_upload_path', False )
+        self.nginx_upload_job_files_store = kwargs.get( 'nginx_upload_job_files_store', False )
+        self.nginx_upload_job_files_path = kwargs.get( 'nginx_upload_job_files_path', False )
         if self.nginx_upload_store:
             self.nginx_upload_store = os.path.abspath( self.nginx_upload_store )
         self.object_store = kwargs.get( 'object_store', 'disk' )
@@ -466,7 +468,7 @@
             datatypes_config_file=[ 'config/datatypes_conf.xml', 'datatypes_conf.xml', 'config/datatypes_conf.xml.sample' ],
             external_service_type_config_file=[ 'config/external_service_types_conf.xml', 'external_service_types_conf.xml', 'config/external_service_types_conf.xml.sample' ],
             job_config_file=[ 'config/job_conf.xml', 'job_conf.xml' ],
-            job_metrics_config_file=[ 'config/job_metrics_conf.xml', 'job_metrics_conf.xml' ],
+            job_metrics_config_file=[ 'config/job_metrics_conf.xml', 'job_metrics_conf.xml','config/job_metrics_conf.xml.sample' ],
             dependency_resolvers_config_file=[ 'config/dependency_resolvers_conf.xml', 'dependency_resolvers_conf.xml' ],
             job_resource_params_file=[ 'config/job_resource_params_conf.xml', 'job_resource_params_conf.xml' ],
             migrated_tools_config=[ 'migrated_tools_conf.xml', 'config/migrated_tools_conf.xml' ],

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -962,12 +962,11 @@
             job.set_state( job.states.PAUSED )
             self.sa_session.add( job )
 
-    def mark_as_resubmitted( self ):
+    def mark_as_resubmitted( self, info=None ):
         job = self.get_job()
         self.sa_session.refresh( job )
-        for dataset in [ dataset_assoc.dataset for dataset_assoc in job.output_datasets + job.output_library_datasets ]:
-            dataset._state = model.Dataset.states.RESUBMITTED
-            self.sa_session.add( dataset )
+        if info is not None:
+            job.info = info
         job.set_state( model.Job.states.RESUBMITTED )
         self.sa_session.add( job )
         self.sa_session.flush()
@@ -1251,6 +1250,16 @@
         if job.user:
             job.user.total_disk_usage += bytes
 
+        # Emperically, we need to update job.user and
+        # job.workflow_invocation_step.workflow_invocation in separate
+        # transactions. Best guess as to why is that the workflow_invocation
+        # may or may not exist when the job is first loaded by the handler -
+        # and depending on whether it is or not sqlalchemy orders the updates
+        # differently and deadlocks can occur (one thread updates user and
+        # waits on invocation and the other updates invocation and waits on
+        # user).
+        self.sa_session.flush()
+
         # fix permissions
         for path in [ dp.real_path for dp in self.get_mutable_output_fnames() ]:
             util.umask_fix_perms( path, self.app.config.umask, 0666, self.app.config.gid )

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/jobs/runners/__init__.py
--- a/lib/galaxy/jobs/runners/__init__.py
+++ b/lib/galaxy/jobs/runners/__init__.py
@@ -341,8 +341,8 @@
         except:
             log.exception('Caught exception in runner state handler:')
 
-    def mark_as_resubmitted( self, job_state ):
-        job_state.job_wrapper.mark_as_resubmitted()
+    def mark_as_resubmitted( self, job_state, info=None ):
+        job_state.job_wrapper.mark_as_resubmitted( info=info )
         if not self.app.config.track_jobs_in_database:
             job_state.job_wrapper.change_state( model.Job.states.QUEUED )
             self.app.job_manager.job_handler.dispatcher.put( job_state.job_wrapper )

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/jobs/runners/pulsar.py
--- a/lib/galaxy/jobs/runners/pulsar.py
+++ b/lib/galaxy/jobs/runners/pulsar.py
@@ -342,7 +342,12 @@
 
         encoded_job_id = self.app.security.encode_id(job_id)
         job_key = self.app.security.encode_id( job_id, kind="jobs_files" )
-        files_endpoint = "%s/api/jobs/%s/files?job_key=%s" % (
+        endpoint_base = "%s/api/jobs/%s?job_key=%s"
+        if self.app.config.nginx_upload_job_files_path:
+            endpoint_base = "%s" + \
+                            self.app.config.nginx_upload_job_files_path + \
+                            "?job_id=%s&job_key=%s"
+        files_endpoint = endpoint_base % (
             self.galaxy_url,
             encoded_job_id,
             job_key

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/jobs/runners/state_handlers/resubmit.py
--- a/lib/galaxy/jobs/runners/state_handlers/resubmit.py
+++ b/lib/galaxy/jobs/runners/state_handlers/resubmit.py
@@ -1,4 +1,5 @@
 import logging
+
 from galaxy import model
 
 
@@ -13,31 +14,45 @@
 
 
 def failure(app, job_runner, job_state):
-    if getattr( job_state, 'runner_state', None ) and job_state.runner_state in ( job_state.runner_states.WALLTIME_REACHED, job_state.runner_states.MEMORY_LIMIT_REACHED ):
-        # Intercept jobs that hit the walltime and have a walltime or nonspecific resubmit destination configured
+    if (getattr(job_state, 'runner_state', None)
+        and job_state.runner_state in
+        (job_state.runner_states.WALLTIME_REACHED,
+         job_state.runner_states.MEMORY_LIMIT_REACHED)):
+        # Intercept jobs that hit the walltime and have a walltime or
+        # nonspecific resubmit destination configured
         for resubmit in job_state.job_destination.get('resubmit'):
-            if resubmit.get('condition', None) and resubmit['condition'] != job_state.runner_state:
-                continue # There is a resubmit defined for the destination but its condition is not for walltime_reached
-            log.info("(%s/%s) Job will be resubmitted to '%s' because %s at the '%s' destination",
-                    job_state.job_wrapper.job_id,
-                    job_state.job_id,
-                    resubmit['destination'],
-                    MESSAGES[job_state.runner_state],
-                    job_state.job_wrapper.job_destination.id )
+            if (resubmit.get('condition', None) and resubmit['condition'] !=
+                job_state.runner_state):
+                # There is a resubmit defined for the destination but
+                # its condition is not for walltime_reached
+                continue
+            log.info("(%s/%s) Job will be resubmitted to '%s' because %s at "
+                     "the '%s' destination",
+                     job_state.job_wrapper.job_id,
+                     job_state.job_id,
+                     resubmit['destination'],
+                     MESSAGES[job_state.runner_state],
+                     job_state.job_wrapper.job_destination.id )
             # fetch JobDestination for the id or tag
-            new_destination = app.job_config.get_destination(resubmit['destination'])
+            new_destination = app.job_config.get_destination(
+                resubmit['destination'])
             # Resolve dynamic if necessary
-            new_destination = job_state.job_wrapper.job_runner_mapper.cache_job_destination( new_destination )
+            new_destination = (job_state.job_wrapper.job_runner_mapper
+                               .cache_job_destination(new_destination))
             # Reset job state
             job = job_state.job_wrapper.get_job()
             if resubmit.get('handler', None):
-                log.debug('(%s/%s) Job reassigned to handler %s', job_state.job_wrapper.job_id, job_state.job_id, resubmit['handler'])
+                log.debug('(%s/%s) Job reassigned to handler %s',
+                          job_state.job_wrapper.job_id, job_state.job_id,
+                          resubmit['handler'])
                 job.set_handler(resubmit['handler'])
                 job_runner.sa_session.add( job )
                 # Is this safe to do here?
                 job_runner.sa_session.flush()
-            # Cache the destination to prevent rerunning dynamic after resubmit
-            job_state.job_wrapper.job_runner_mapper.cached_job_destination = new_destination
+            # Cache the destination to prevent rerunning dynamic after
+            # resubmit
+            job_state.job_wrapper.job_runner_mapper \
+                .cached_job_destination = new_destination
             job_state.job_wrapper.set_job_destination(new_destination)
             # Clear external ID (state change below flushes the change)
             job.job_runner_external_id = None
@@ -45,5 +60,7 @@
             if job.params is None:
                 job.params = {}
             job_state.runner_state_handled = True
-            job_runner.mark_as_resubmitted( job_state )
+            info = "This job was resubmitted to the queue because %s on its " \
+                   "compute resource." % MESSAGES[job_state.runner_state]
+            job_runner.mark_as_resubmitted(job_state, info=info)
             return

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/managers/base.py
--- a/lib/galaxy/managers/base.py
+++ b/lib/galaxy/managers/base.py
@@ -700,8 +700,8 @@
             setattr( item, key, val )
         return val
 
-    def deserialize_basestring( self, trans, item, key, val ):
-        val = self.validate.basestring( key, val )
+    def deserialize_basestring( self, trans, item, key, val, convert_none_to_empty=False ):
+        val = '' if ( convert_none_to_empty and val is None ) else self.validate.basestring( key, val )
         return self.default_deserializer( trans, item, key, val )
 
     def deserialize_bool( self, trans, item, key, val ):

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/managers/hdas.py
--- a/lib/galaxy/managers/hdas.py
+++ b/lib/galaxy/managers/hdas.py
@@ -154,8 +154,9 @@
         # error here if disallowed - before jobs are stopped
         #TODO: poss. move to DatasetAssociationManager
         self.dataset_manager.error_unless_dataset_purge_allowed( trans, hda )
+        if trans.user:
+            trans.user.total_disk_usage -= hda.quota_amount( trans.user )
         super( HDAManager, self ).purge( trans, hda, flush=flush )
-
         if hda.creating_job_associations:
             job = hda.creating_job_associations[0].job
             if not job.finished:
@@ -195,6 +196,32 @@
             break
         return job
 
+    def _job_state_history_query( self, hda ):
+        """
+        Return a query of the job's state history for the job that created this hda.
+        """
+        session = self.app.model.context
+        JobToOutputDatasetAssociation = model.JobToOutputDatasetAssociation
+        JobStateHistory = model.JobStateHistory
+
+        # TODO: this does not play well with copied hdas
+        # NOTE: don't eagerload (JODA will load the hda were using!)
+        hda_id = hda.id
+        query = ( session.query( JobToOutputDatasetAssociation, JobStateHistory )
+            .filter( JobToOutputDatasetAssociation.dataset_id == hda_id )
+            .filter( JobStateHistory.job_id == JobToOutputDatasetAssociation.job_id )
+            .enable_eagerloads( False ) )
+        return query
+
+    def has_been_resubmitted( self, hda ):
+        """
+        Return True if the hda's job was resubmitted at any point.
+        """
+        job_states = model.Job.states
+        query = ( self._job_state_history_query( hda )
+            .filter( model.JobStateHistory.state == job_states.RESUBMITTED ) )
+        return self.app.model.context.query( query.exists() ).scalar()
+
     # .... serialization
     def get_display_apps( self, trans, hda ):
         """
@@ -324,7 +351,7 @@
             'history_content_type',
             'dataset_id',
             'state', 'extension',
-            'deleted', 'purged', 'visible', 'resubmitted',
+            'deleted', 'purged', 'visible',
             'type', 'url'
         ])
         self.add_view( 'detailed', [
@@ -340,7 +367,8 @@
             'file_ext', 'file_size',
 
             'create_time', 'update_time',
-            'metadata', 'meta_files', 'data_type',
+            'resubmitted',
+             'metadata', 'meta_files', 'data_type',
             'peek',
 
             #TODO: why is this named uuid!? The hda doesn't have a uuid - it's the underlying dataset's uuid!
@@ -388,7 +416,7 @@
             'hda_ldda'      : lambda *a: 'hda',
 
             # remapped
-            'info'          : lambda t, i, k: i.info.strip() if isinstance( i.info, basestring ) else i.info,
+            'info'          : lambda t, i, k: i.info.strip() if isinstance( i.info, basestring ) else '',
             'misc_info'     : lambda t, i, k: self.serializers[ 'info' ]( t, i, k ),
             'misc_blurb'    : lambda t, i, k: i.blurb,
             'genome_build'  : lambda t, i, k: i.dbkey,
@@ -400,7 +428,7 @@
             'copied_from_history_dataset_association_id'        : self.serialize_id,
             'copied_from_library_dataset_dataset_association_id': self.serialize_id,
 
-            'resubmitted'   : lambda t, i, k: i._state == t.app.model.Dataset.states.RESUBMITTED,
+            'resubmitted'   : lambda t, i, k: self.hda_manager.has_been_resubmitted( i ),
 
             'meta_files'    : self.serialize_meta_files,
             'file_path'     : self.serialize_file_path,
@@ -583,7 +611,8 @@
 
             # remapped
             'genome_build'  : lambda t, i, k, v: self.deserialize_genome_build( t, i, 'dbkey', v ),
-            'misc_info'     : lambda t, i, k, v: self.deserialize_basestring( t, i, 'info', v ),
+            'misc_info'     : lambda t, i, k, v: (
+                self.deserialize_basestring( t, i, 'info', v, convert_none_to_empty=True ) ),
 
             #TODO: mixin: deletable
             'deleted'       : self.deserialize_bool,

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/managers/workflows.py
--- a/lib/galaxy/managers/workflows.py
+++ b/lib/galaxy/managers/workflows.py
@@ -569,7 +569,7 @@
         for step_index in step_indices:
             step_dict = supplied_steps[ step_index ]
             uuid = step_dict.get("uuid", None)
-            if uuid:
+            if uuid and uuid != "None":
                 if uuid in discovered_uuids:
                     raise exceptions.DuplicatedIdentifierException("Duplicate step UUID in request.")
                 discovered_uuids.add(uuid)
@@ -586,10 +586,9 @@
         type-specific functionality from the incoming dicitionary.
         """
         step = model.WorkflowStep()
-
         # TODO: Consider handling position inside module.
         step.position = step_dict['position']
-        if "uuid" in step_dict:
+        if "uuid" in step_dict and step_dict['uuid'] != "None":
             step.uuid = step_dict["uuid"]
         if "label" in step_dict:
             step.label = step_dict["label"]

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1335,9 +1335,8 @@
                     DISCARDED = 'discarded',
                     PAUSED = 'paused',
                     SETTING_METADATA = 'setting_metadata',
-                    FAILED_METADATA = 'failed_metadata',
-                    RESUBMITTED = 'resubmitted' )
-    # failed_metadata and resubmitted are only valid as DatasetInstance states currently
+                    FAILED_METADATA = 'failed_metadata')
+    # failed_metadata is only valid as DatasetInstance state currently
 
     non_ready_states = (
         states.UPLOAD,

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/model/orm/logging_connection_proxy.py
--- a/lib/galaxy/model/orm/logging_connection_proxy.py
+++ b/lib/galaxy/model/orm/logging_connection_proxy.py
@@ -2,7 +2,7 @@
 import inspect
 import os
 
-from galaxy.model.orm import *
+from galaxy.model.orm import ConnectionProxy
 
 import logging
 

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -417,13 +417,14 @@
     dict_collection_visible_keys = ( 'id', 'name', 'version', 'description' )
     default_template = 'tool_form.mako'
 
-    def __init__( self, config_file, tool_source, app, guid=None, repository_id=None ):
+    def __init__( self, config_file, tool_source, app, guid=None, repository_id=None, allow_code_files=True ):
         """Load a tool from the config named by `config_file`"""
         # Determine the full path of the directory where the tool config is
         self.config_file = config_file
         self.tool_dir = os.path.dirname( config_file )
         self.app = app
         self.repository_id = repository_id
+        self._allow_code_files = allow_code_files
         #setup initial attribute values
         self.inputs = odict()
         self.stdio_exit_codes = list()
@@ -704,14 +705,15 @@
         # Load any tool specific code (optional) Edit: INS 5/29/2007,
         # allow code files to have access to the individual tool's
         # "module" if it has one.  Allows us to reuse code files, etc.
-        for code_elem in root.findall("code"):
-            for hook_elem in code_elem.findall("hook"):
-                for key, value in hook_elem.items():
-                    # map hook to function
-                    self.hook_map[key] = value
-            file_name = code_elem.get("file")
-            code_path = os.path.join( self.tool_dir, file_name )
-            execfile( code_path, self.code_namespace )
+        if self._allow_code_files:
+            for code_elem in root.findall("code"):
+                for hook_elem in code_elem.findall("hook"):
+                    for key, value in hook_elem.items():
+                        # map hook to function
+                        self.hook_map[key] = value
+                file_name = code_elem.get("file")
+                code_path = os.path.join( self.tool_dir, file_name )
+                execfile( code_path, self.code_namespace )
 
         # User interface hints
         uihints_elem = root.find( "uihints" )
@@ -2433,7 +2435,7 @@
                     continue
 
                 # state for subsection/group
-                group_state = state_inputs[input.name]
+                group_state = state_inputs.get(input.name, {})
 
                 # iterate and update values
                 if input.type == 'repeat':
@@ -2444,10 +2446,12 @@
                 elif input.type == 'conditional':
                     if 'test_param' in tool_dict:
                         test_param = tool_dict['test_param']
-                        test_param['value'] = jsonify(group_state[test_param['name']])
-                        if '__current_case__' in group_state:
-                            i = group_state['__current_case__']
-                            iterate(tool_dict['cases'][i]['inputs'], input.cases[i].inputs, group_state, other_values)
+                        test_param['value'] = jsonify(group_state.get(test_param['name'], None))
+                        for i in range (len ( tool_dict['cases'] ) ):
+                            current_state = {}
+                            if i == group_state.get('__current_case__', None):
+                                current_state = group_state
+                            iterate(tool_dict['cases'][i]['inputs'], input.cases[i].inputs, current_state, other_values)
                 else:
                     # create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options
                     try:
@@ -2459,11 +2463,15 @@
                     input_name = tool_dict.get('name')
                     if input_name:
                         # backup default value
-                        tool_dict['default_value'] = input.get_initial_value(trans, other_values)
+                        try:
+                            tool_dict['default_value'] = input.get_initial_value(trans, other_values)
+                        except Exception:
+                            # get initial value failed due to improper late validation
+                            tool_dict['default_value'] = None
+                            pass
 
                         # update input value from tool state
-                        if input_name in state_inputs:
-                            tool_dict['value'] = state_inputs[input_name]
+                        tool_dict['value'] = state_inputs.get(input_name, None)
 
                         # sanitize values
                         sanitize(tool_dict, 'value')
@@ -2584,28 +2592,44 @@
         # dataset used; parameter should be the analygous dataset in the
         # current history.
         history = trans.get_history()
-        hda_source_dict = {} # Mapping from HDA in history to source HDAs.
+
+        # Create index for hdas.
+        hda_source_dict = {}
         for hda in history.datasets:
-            source_hda = hda.copied_from_history_dataset_association
-            while source_hda:
-                if source_hda.dataset.id not in hda_source_dict or source_hda.hid == hda.hid:
-                    hda_source_dict[ source_hda.dataset.id ] = hda
-                source_hda = source_hda.copied_from_history_dataset_association
+            key = '%s_%s' % (hda.hid, hda.dataset.id)
+            hda_source_dict[ hda.dataset.id ] = hda_source_dict[ key ] = hda
 
         # Ditto for dataset collections.
         hdca_source_dict = {}
         for hdca in history.dataset_collections:
-            source_hdca = hdca.copied_from_history_dataset_collection_association
-            while source_hdca:
-                if source_hdca.collection.id not in hdca_source_dict or source_hdca.hid == hdca.hid:
-                    hdca_source_dict[ source_hdca.collection.id ] = hdca
-                source_hdca = source_hdca.copied_from_history_dataset_collection_association
+            key = '%s_%s' % (hdca.hid, hdca.collection.id)
+            hdca_source_dict[ hdca.collection.id ] = hdca_source_dict[ key ] = hdca
+
+        # Map dataset or collection to current history
+        def map_to_history(value):
+            id = None
+            source = None
+            if isinstance(value, trans.app.model.HistoryDatasetAssociation):
+                id = value.dataset.id
+                source = hda_source_dict
+            elif isinstance(value, trans.app.model.HistoryDatasetCollectionAssociation):
+                id = value.collection.id
+                source = hdca_source_dict
+            else:
+                return None
+            key = '%s_%s' % (value.hid, id)
+            if key in source:
+                return source[ key ]
+            elif id in source:
+                return source[ id ]
+            else:
+                return None
 
         # Unpack unvalidated values to strings, they'll be validated when the
         # form is submitted (this happens when re-running a job that was
         # initially run by a workflow)
         #This needs to be done recursively through grouping parameters
-        def rerun_callback( input, value, prefixed_name, prefixed_label ):
+        def mapping_callback( input, value, prefixed_name, prefixed_label ):
             if isinstance( value, UnvalidatedValue ):
                 try:
                     return input.to_html_value( value.value, trans.app )
@@ -2617,22 +2641,17 @@
                 if isinstance(value,list):
                     values = []
                     for val in value:
-                        if isinstance(val, trans.app.model.HistoryDatasetAssociation):
-                            if val.dataset.id in hda_source_dict:
-                                values.append( hda_source_dict[ val.dataset.id ] )
-                            else:
-                                values.append( val )
+                        new_val = map_to_history( val )
+                        if new_val:
+                            values.append( new_val )
+                        else:
+                            values.append( val )
                     return values
-                if isinstance(value, trans.app.model.HistoryDatasetAssociation):
-                    if value.dataset.id in hda_source_dict:
-                        return hda_source_dict[ value.dataset.id ]
-                if isinstance(value, trans.app.model.HistoryDatasetCollectionAssociation):
-                    if value.collection.id in hdca_source_dict:
-                        return hdca_source_dict[ value.collection.id ]
+                else:
+                    return map_to_history( value )
             elif isinstance( input, DataCollectionToolParameter ):
-                if value.collection.id in hdca_source_dict:
-                    return hdca_source_dict[ value.collection.id ]
-        visit_input_values( tool_inputs, params, rerun_callback )
+                return map_to_history( value )
+        visit_input_values( tool_inputs, params, mapping_callback )
 
     def _compare_tool_version( self, trans, job ):
         """

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -15,6 +15,7 @@
 from galaxy.util import string_as_bool, sanitize_param, unicodify
 from galaxy.util import listify
 from galaxy.util.odict import odict
+from galaxy.util.expressions import ExpressionContext
 from sanitize import ToolParameterSanitizer
 import validation
 import dynamic_options
@@ -802,8 +803,9 @@
         self.is_dynamic = ( ( self.dynamic_options is not None ) or ( self.options is not None ) )
 
     def _get_dynamic_options_call_other_values( self, trans, other_values ):
-        call_other_values = { "__trans__": trans }
+        call_other_values = ExpressionContext({ "__trans__": trans })
         if other_values:
+            call_other_values.parent = other_values.parent
             call_other_values.update( other_values.dict )
         return call_other_values
 
@@ -1505,8 +1507,9 @@
 
     def _get_options_from_code( self, trans=None, value=None, other_values=None ):
         assert self.dynamic_options, Exception( "dynamic_options was not specifed" )
-        call_other_values = { '__trans__': trans, '__value__': value }
+        call_other_values = ExpressionContext({ '__trans__': trans, '__value__': value })
         if other_values:
+            call_other_values.parent = other_values.parent
             call_other_values.update( other_values.dict )
         try:
             return eval( self.dynamic_options, self.tool.code_namespace, call_other_values )

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/tools/toolbox/base.py
--- a/lib/galaxy/tools/toolbox/base.py
+++ b/lib/galaxy/tools/toolbox/base.py
@@ -978,7 +978,9 @@
                     if tool_key in val.elems:
                         self._tool_panel[ key ].elems[ tool_key ] = new_tool
                         break
-            self._tools_by_id[ tool_id ] = new_tool
+            # (Re-)Register the reloaded tool, this will handle
+            #  _tools_by_id and _tool_versions_by_id
+            self.register_tool( new_tool )
             message = "Reloaded the tool:<br/>"
             message += "<b>name:</b> %s<br/>" % old_tool.name
             message += "<b>id:</b> %s<br/>" % old_tool.id

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/util/dbkeys.py
--- a/lib/galaxy/util/dbkeys.py
+++ b/lib/galaxy/util/dbkeys.py
@@ -38,7 +38,7 @@
                 for dataset in datasets:
                     rval.append( ( dataset.dbkey, "%s (%s) [History]" % ( dataset.name, dataset.dbkey ) ) )
             user = trans.user
-            if user and 'dbkeys' in user.preferences:
+            if user and hasattr( user, 'preferences' ) and 'dbkeys' in user.preferences:
                 user_keys = loads( user.preferences['dbkeys'] )
                 for key, chrom_dict in user_keys.iteritems():
                     rval.append( ( key, "%s (%s) [Custom]" % ( chrom_dict['name'], key ) ) )

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/version.py
--- a/lib/galaxy/version.py
+++ b/lib/galaxy/version.py
@@ -1,3 +1,3 @@
 VERSION_MAJOR = "15.03"
-VERSION_MINOR = "1"
+VERSION_MINOR = "2"
 VERSION = VERSION_MAJOR + ('.' + VERSION_MINOR if VERSION_MINOR else '')

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/web/framework/webapp.py
--- a/lib/galaxy/web/framework/webapp.py
+++ b/lib/galaxy/web/framework/webapp.py
@@ -668,7 +668,8 @@
         """
         history = None
         if self.galaxy_session:
-            history = self.galaxy_session.current_history
+            if hasattr( self.galaxy_session, 'current_history' ):
+                history = self.galaxy_session.current_history
         if not history and util.string_as_bool( create ):
             history = self.new_history()
         return history

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/api/job_files.py
--- a/lib/galaxy/webapps/galaxy/api/job_files.py
+++ b/lib/galaxy/webapps/galaxy/api/job_files.py
@@ -83,9 +83,21 @@
         self.__check_job_can_write_to_path( trans, job, path )
 
         # Is this writing an unneeded file? Should this just copy in Python?
-        input_file = payload.get( "file", payload.get( "__file", None ) ).file
+        if '__file_path' in payload:
+            file_path = payload.get( '__file_path' )
+            upload_store = trans.app.config.nginx_upload_job_files_store
+            assert upload_store, ( "Request appears to have been processed by"
+                                   " nginx_upload_module but Galaxy is not"
+                                   " configured to recognize it" )
+            assert file_path.startswith( upload_store ), \
+                    ( "Filename provided by nginx (%s) is not in correct"
+                      " directory (%s)" % ( file_path, upload_store ) )
+            input_file = open( file_path )
+        else:
+            input_file = payload.get( "file",
+                                      payload.get( "__file", None ) ).file
         try:
-            shutil.copyfile( input_file.name, path )
+            shutil.move( input_file.name, path )
         finally:
             input_file.close()
         return {"message": "ok"}

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/api/tools.py
--- a/lib/galaxy/webapps/galaxy/api/tools.py
+++ b/lib/galaxy/webapps/galaxy/api/tools.py
@@ -145,7 +145,6 @@
         if success:
             trans.response.set_content_type( 'application/x-gzip' )
             download_file = open( tool_tarball )
-            os.unlink( tool_tarball )
             tarball_path, filename = os.path.split( tool_tarball )
             trans.response.headers[ "Content-Disposition" ] = 'attachment; filename="%s.tgz"' % ( id )
             return download_file
@@ -332,7 +331,7 @@
         # job's previous parameters and incoming parameters. Incoming parameters
         # have priority.
         #
-        original_job = self.hda_manager.creating_job( original_dataset )
+        original_job = self.hda_manager.creating_job( trans, original_dataset )
         tool = trans.app.toolbox.get_tool( original_job.tool_id )
         if not tool or not tool.allow_user_access( trans.user ):
             return trans.app.model.Dataset.conversion_messages.NO_TOOL

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -106,13 +106,13 @@
         pack_scripts()
     # Close any pooled database connections before forking
     try:
-        galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose()
+        galaxy.model.mapping.metadata.bind.dispose()
     except:
-        pass
+        log.exception("Unable to dispose of pooled galaxy model database connections.")
     try:
-        galaxy.model.tool_shed_install.mapping.metadata.engine.connection_provider._pool.dispose()
+        galaxy.model.tool_shed_install.mapping.metadata.bind.dispose()
     except:
-        pass
+        log.exception("Unable to dispose of pooled toolshed install model database connections.")
 
     if not app.config.is_uwsgi:
         postfork_setup()

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/controllers/dataset.py
--- a/lib/galaxy/webapps/galaxy/controllers/dataset.py
+++ b/lib/galaxy/webapps/galaxy/controllers/dataset.py
@@ -852,22 +852,24 @@
         status = 'done'
         try:
             id = trans.app.security.decode_id( dataset_id )
-            history = trans.get_history()
             user = trans.get_user()
             hda = trans.sa_session.query( self.app.model.HistoryDatasetAssociation ).get( id )
             # Invalid HDA
             assert hda, 'Invalid history dataset ID'
+
             # Walk up parent datasets to find the containing history
+            history = trans.get_history()
             topmost_parent = hda
             while topmost_parent.parent:
                 topmost_parent = topmost_parent.parent
-            assert topmost_parent in history.datasets, "Data does not belong to current history"
             # If the user is anonymous, make sure the HDA is owned by the current session.
             if not user:
-                assert trans.galaxy_session.current_history_id == trans.history.id, 'Invalid history dataset ID'
+                current_history_id = trans.galaxy_session.current_history_id
+                assert topmost_parent.history.id == current_history_id, 'Data does not belong to current user'
             # If the user is known, make sure the HDA is owned by the current user.
             else:
-                assert topmost_parent.history.user == trans.user, 'Invalid history dataset ID'
+                assert topmost_parent.history.user == user, 'Data does not belong to current user'
+
             # Ensure HDA is deleted
             hda.deleted = True
             # HDA is purgeable
@@ -890,8 +892,8 @@
                 except:
                     log.exception( 'Unable to purge dataset (%s) on purge of HDA (%s):' % ( hda.dataset.id, hda.id ) )
             trans.sa_session.flush()
-        except Exception:
-            msg = 'HDA purge failed (encoded: %s, decoded: %s)' % ( dataset_id, id )
+        except Exception, exc:
+            msg = 'HDA purge failed (encoded: %s, decoded: %s): %s' % ( dataset_id, id, exc )
             log.exception( msg )
             trans.log_event( msg )
             message = 'Dataset removal from disk failed'

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -605,9 +605,13 @@
 
         except Exception, exc:
             user_id = str( trans.user.id ) if trans.user else '(anonymous)'
-            log.exception( 'Error bootstrapping history for user %s: %s', user_id, str( exc ) )
-            history_dictionary[ 'error' ] = ( 'An error occurred getting the history data from the server. '
-                                            + 'Please contact a Galaxy administrator if the problem persists.' )
+            log.exception( 'Error bootstrapping history for user %s: %s', user_id, exc )
+            if isinstance( exc, exceptions.ItemAccessibilityException ):
+                error_msg = 'You do not have permission to view this history.'
+            else:
+                error_msg = ( 'An error occurred getting the history data from the server. '
+                              + 'Please contact a Galaxy administrator if the problem persists.' )
+            return trans.show_error_message( error_msg, use_panels=use_panels )
 
         return trans.fill_template_mako( "history/view.mako",
             history=history_dictionary, hdas=hda_dictionaries, user_is_owner=user_is_owner,

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/controllers/library_common.py
--- a/lib/galaxy/webapps/galaxy/controllers/library_common.py
+++ b/lib/galaxy/webapps/galaxy/controllers/library_common.py
@@ -1136,7 +1136,7 @@
     def make_library_uploaded_dataset( self, trans, cntrller, params, name, path, type, library_bunch, in_folder=None ):
         link_data_only = params.get( 'link_data_only', 'copy_files' )
         uuid_str =  params.get( 'uuid', None )
-        file_type = params.get( 'file_type' )
+        file_type = params.get( 'file_type', None )
         library_bunch.replace_dataset = None # not valid for these types of upload
         uploaded_dataset = util.bunch.Bunch()
         new_name = name
@@ -1152,8 +1152,8 @@
         uploaded_dataset.type = type
         uploaded_dataset.ext = None
         uploaded_dataset.file_type = file_type
-        uploaded_dataset.dbkey = params.get( 'dbkey' )
-        uploaded_dataset.space_to_tab = params.get( 'space_to_tab' )
+        uploaded_dataset.dbkey = params.get( 'dbkey', None )
+        uploaded_dataset.space_to_tab = params.get( 'space_to_tab', None )
         if in_folder:
             uploaded_dataset.in_folder = in_folder
         uploaded_dataset.data = upload_common.new_upload( trans, cntrller, uploaded_dataset, library_bunch )

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/controllers/tag.py
--- a/lib/galaxy/webapps/galaxy/controllers/tag.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tag.py
@@ -42,7 +42,7 @@
         # Apply tag.
         item = self._get_item( trans, item_class, trans.security.decode_id( item_id ) )
         user = trans.user
-        self.get_tag_handler( trans ).apply_item_tags( trans, user, item, new_tag.encode( 'utf-8' ) )
+        self.get_tag_handler( trans ).apply_item_tags( user, item, new_tag.encode( 'utf-8' ) )
         trans.sa_session.flush()
         # Log.
         params = dict( item_id=item.id, item_class=item_class, tag=new_tag )
@@ -57,7 +57,7 @@
         # Remove tag.
         item = self._get_item( trans, item_class, trans.security.decode_id( item_id ) )
         user = trans.user
-        self.get_tag_handler( trans ).remove_item_tag( trans, user, item, tag_name.encode( 'utf-8' ) )
+        self.get_tag_handler( trans ).remove_item_tag( user, item, tag_name.encode( 'utf-8' ) )
         trans.sa_session.flush()
         # Log.
         params = dict( item_id=item.id, item_class=item_class, tag=tag_name )
@@ -73,8 +73,8 @@
         # Apply tags.
         item = self._get_item( trans, item_class, trans.security.decode_id( item_id ) )
         user = trans.user
-        self.get_tag_handler( trans ).delete_item_tags( trans, user, item )
-        self.get_tag_handler( trans ).apply_item_tags( trans, user, item, new_tags.encode( 'utf-8' ) )
+        self.get_tag_handler( trans ).delete_item_tags( user, item )
+        self.get_tag_handler( trans ).apply_item_tags( user, item, new_tags.encode( 'utf-8' ) )
         trans.sa_session.flush()
 
     @web.expose

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/galaxy/controllers/visualization.py
--- a/lib/galaxy/webapps/galaxy/controllers/visualization.py
+++ b/lib/galaxy/webapps/galaxy/controllers/visualization.py
@@ -985,7 +985,7 @@
         else:
             # Loading new visualization.
             dataset = self.get_hda_or_ldda( trans, hda_ldda, dataset_id )
-            job = self.hda_manager.creating_job( dataset )
+            job = self.hda_manager.creating_job( trans, dataset )
             viz_config = {
                 'dataset_id': dataset_id,
                 'tool_id': job.tool_id,
@@ -1017,7 +1017,7 @@
         if dataset_id:
             decoded_id = self.decode_id( dataset_id )
             hda = self.hda_manager.get_accessible( trans, decoded_id, trans.user )
-            hda = self.hda_manager.error_if_uploading( hda )
+            hda = self.hda_manager.error_if_uploading( trans, hda )
         else:
             return trans.show_message( "Phyloviz couldn't find a dataset_id" )
 

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/reports/buildapp.py
--- a/lib/galaxy/webapps/reports/buildapp.py
+++ b/lib/galaxy/webapps/reports/buildapp.py
@@ -70,12 +70,13 @@
         webapp = wrap_in_static( webapp, global_conf, **kwargs )
     # Close any pooled database connections before forking
     try:
-        galaxy.model.mapping.metadata.engine.connection_provider._pool.dispose()
+        galaxy.model.mapping.metadata.bind.dispose()
     except:
-        pass
+        log.exception("Unable to dispose of pooled galaxy model database connections.")
     # Return
     return webapp
 
+
 def wrap_in_middleware( app, global_conf, **local_conf ):
     """Based on the configuration wrap `app` in a set of common and useful middleware."""
     # Merge the global and local configurations

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/galaxy/webapps/tool_shed/buildapp.py
--- a/lib/galaxy/webapps/tool_shed/buildapp.py
+++ b/lib/galaxy/webapps/tool_shed/buildapp.py
@@ -134,13 +134,28 @@
     # Wrap the webapp in some useful middleware
     if kwargs.get( 'middleware', True ):
         webapp = wrap_in_middleware( webapp, global_conf, **kwargs )
-    if asbool( kwargs.get( 'static_enabled', True ) ):
-        webapp = wrap_in_static( webapp, global_conf, **kwargs )
+    # TEST FOR UWSGI -- TODO save this somewhere so we only have to do it once.
+    is_uwsgi = False
+    try:
+        # The uwsgi module is automatically injected by the parent uwsgi
+        # process and only exists that way.  If anything works, this is a
+        # uwsgi-managed process.
+        import uwsgi
+        is_uwsgi = uwsgi.numproc
+        is_uwsgi = True
+    except ImportError:
+        # This is not a uwsgi process, or something went horribly wrong.
+        pass
+    if asbool( kwargs.get( 'static_enabled', True) ):
+        if is_uwsgi:
+            log.error("Static middleware is enabled in your configuration but this is a uwsgi process.  Refusing to wrap in static middleware.")
+        else:
+            webapp = wrap_in_static( webapp, global_conf, **kwargs )
     # Close any pooled database connections before forking
     try:
-        galaxy.webapps.tool_shed.model.mapping.metadata.engine.connection_provider._pool.dispose()
+        galaxy.webapps.tool_shed.model.mapping.metadata.bind.dispose()
     except:
-        pass
+        log.exception("Unable to dispose of pooled tool_shed model database connections.")
     # Return
     return webapp
 

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/tool_shed/metadata/metadata_generator.py
--- a/lib/tool_shed/metadata/metadata_generator.py
+++ b/lib/tool_shed/metadata/metadata_generator.py
@@ -456,8 +456,8 @@
                                 try:
                                     exported_workflow_dict = json.loads( workflow_text )
                                 except Exception, e:
-                                    log.exception( "Skipping file %s since it does not seem to be a valid exported Galaxy workflow: %s" \
-                                                   % str( relative_path ), str( e ) )
+                                    log.exception( "Skipping file %s since it does not seem to be a valid exported Galaxy workflow: %s"
+                                                   % ( str( relative_path ), str( e ) ) )
                                     valid_exported_galaxy_workflow = False
                             if valid_exported_galaxy_workflow and \
                                 'a_galaxy_workflow' in exported_workflow_dict and \

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/tool_shed/tools/tool_validator.py
--- a/lib/tool_shed/tools/tool_validator.py
+++ b/lib/tool_shed/tools/tool_validator.py
@@ -292,7 +292,7 @@
 
     def load_tool_from_config( self, repository_id, full_path ):
         try:
-            tool = self.app.toolbox.load_tool( full_path, repository_id=repository_id )
+            tool = self.app.toolbox.load_tool( full_path, repository_id=repository_id, allow_code_files=False )
             valid = True
             error_message = None
         except KeyError, e:

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca lib/tool_shed/util/tool_util.py
--- a/lib/tool_shed/util/tool_util.py
+++ b/lib/tool_shed/util/tool_util.py
@@ -237,12 +237,19 @@
     if invalid:
         # We're attempting to display a tool in the tool shed that has been determined to have errors, so is invalid.
         return state
+    try:
+        # Attempt to generate the tool state using the standard Galaxy-side code
+        return tool.new_state( trans )
+    except Exception, e:
+        # Fall back to building tool state as below
+        log.debug( 'Failed to build tool state for tool "%s" using standard method, will try to fall back on custom method: %s', tool.id, e )
     inputs = tool.inputs_by_page[ 0 ]
     context = ExpressionContext( state.inputs, parent=None )
     for input in inputs.itervalues():
         try:
             state.inputs[ input.name ] = input.get_initial_value( trans, context )
         except:
+            # FIXME: not all values should be an empty list
             state.inputs[ input.name ] = []
     return state
 

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/history/history-model.js
--- a/static/scripts/mvc/history/history-model.js
+++ b/static/scripts/mvc/history/history-model.js
@@ -257,7 +257,7 @@
 
     setAsCurrent : function(){
         var history = this,
-            xhr = jQuery.getJSON( '/history/set_as_current?id=' + this.id );
+            xhr = jQuery.getJSON( galaxy_config.root + 'history/set_as_current?id=' + this.id );
 
         xhr.done( function(){
             history.trigger( 'set-as-current', history );
@@ -361,7 +361,7 @@
 var HistoryCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
 /** @lends HistoryCollection.prototype */{
     model   : History,
-    
+
     /** logger used to record this.log messages, commonly set to console */
     //logger              : console,
 

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/library/library-dataset-view.js
--- a/static/scripts/mvc/library/library-dataset-view.js
+++ b/static/scripts/mvc/library/library-dataset-view.js
@@ -116,7 +116,7 @@
   },
 
   downloadDataset: function(){
-    var url = '/api/libraries/datasets/download/uncompressed';
+    var url = ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/download/uncompressed';
     var data = {'ld_ids' : this.id};
     this.processDownload(url, data);
   },
@@ -232,7 +232,7 @@
 
     var self = this;
     if (this.options.fetched_permissions === undefined){
-      $.get( "/api/libraries/datasets/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
+      $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
         self.prepareSelectBoxes({fetched_permissions:fetched_permissions, is_admin:is_admin});
       }).fail(function(){
           mod_toastr.error('An error occurred while attempting to fetch dataset permissions.');
@@ -273,7 +273,7 @@
               placeholder: 'Click to select a role',
               container: self.$el.find('#access_perm'),
               ajax: {
-                  url: "/api/libraries/datasets/" + self.id + "/permissions?scope=available",
+                  url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available",
                   dataType: 'json',
                   quietMillis: 100,
                   data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -320,7 +320,7 @@
               placeholder: 'Click to select a role',
               container: self.$el.find('#modify_perm'),
               ajax: {
-                  url: "/api/libraries/datasets/" + self.id + "/permissions?scope=available",
+                  url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available",
                   dataType: 'json',
                   quietMillis: 100,
                   data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -367,7 +367,7 @@
               placeholder: 'Click to select a role',
               container: self.$el.find('#manage_perm'),
               ajax: {
-                  url: "/api/libraries/datasets/" + self.id + "/permissions?scope=available",
+                  url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available",
                   dataType: 'json',
                   quietMillis: 100,
                   data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -413,7 +413,7 @@
             self.manageSelectObject = new mod_select.View(manage_select_options);
         } else { // Non-admins have select with pre-loaded options
             var template = self.templateAccessSelect();
-            $.get( "/api/libraries/datasets/" + self.id + "/permissions?scope=available", function( data ) {
+            $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?scope=available", function( data ) {
                 $('.access_perm').html(template({options:data.roles}));
                 self.accessSelectObject = $('#access_select').select2();
             }).fail(function() {
@@ -436,7 +436,7 @@
 
   makeDatasetPrivate: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
       self.model.set({is_unrestricted:false});
       self.showPermissions({fetched_permissions:fetched_permissions})
       mod_toastr.success('The dataset is now private to you.');
@@ -447,7 +447,7 @@
 
   removeDatasetRestrictions: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
     .done(function(fetched_permissions) {
       self.model.set({is_unrestricted:true});
       self.showPermissions({fetched_permissions:fetched_permissions})
@@ -478,7 +478,7 @@
       modify_ids.push(modify_roles[i].id);
     };
 
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
     .done(function(fetched_permissions){
       //fetch dataset again
       self.showPermissions({fetched_permissions:fetched_permissions})

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/library/library-folder-view.js
--- a/static/scripts/mvc/library/library-folder-view.js
+++ b/static/scripts/mvc/library/library-folder-view.js
@@ -81,7 +81,7 @@
 
     var self = this;
     if (this.options.fetched_permissions === undefined){
-      $.get( "/api/folders/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
+      $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/folders/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
         self.prepareSelectBoxes({fetched_permissions:fetched_permissions});
       }).fail(function(){
           mod_toastr.error('An error occurred while attempting to fetch folder permissions.');
@@ -125,7 +125,7 @@
       placeholder: 'Click to select a role',
       container: self.$el.find('#' + id),
       ajax: {
-          url: "/api/folders/" + self.id + "/permissions?scope=available",
+          url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/folders/" + self.id + "/permissions?scope=available",
           dataType: 'json',
           quietMillis: 100,
           data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -195,7 +195,7 @@
     var manage_ids = this._extractIds(this.manageSelectObject.$el.select2('data'));
     var modify_ids = this._extractIds(this.modifySelectObject.$el.select2('data'));
 
-    $.post("/api/folders/" + self.id + "/permissions?action=set_permissions", { 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/folders/" + self.id + "/permissions?action=set_permissions", { 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
     .done(function(fetched_permissions){
       //fetch dataset again
       self.showPermissions({fetched_permissions:fetched_permissions})

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/mvc/library/library-foldertoolbar-view.js
@@ -294,7 +294,7 @@
                 dataset_ids.push( this.parentElement.parentElement.id );
             }
         } );
-    var url = '/api/libraries/datasets/download/' + format;
+    var url = ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/download/' + format;
     var data = { 'ld_ids' : dataset_ids };
     this.processDownload( url, data, 'get' );
   },
@@ -386,7 +386,7 @@
   fetchExtAndGenomes: function(){
     var that = this;
     mod_utils.get({
-        url      :  galaxy_config.root + "api/datatypes?extension_only=False",
+        url      :  ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/datatypes?extension_only=False",
         success  :  function( datatypes ) {
                         for (key in datatypes) {
                             that.list_extensions.push({
@@ -403,7 +403,7 @@
                     }
       });
     mod_utils.get({
-        url:    galaxy_config.root + "api/genomes",
+        url:    ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/genomes",
         success: function( genomes ) {
                     for ( key in genomes ) {
                         that.list_genomes.push({
@@ -689,7 +689,7 @@
       for ( var i = history_dataset_ids.length - 1; i >= 0; i-- ) {
         history_dataset_id = history_dataset_ids[i];
         var folder_item = new mod_library_model.Item();
-        folder_item.url = '/api/folders/' + this.options.id + '/contents';
+        folder_item.url = ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/folders/' + this.options.id + '/contents';
         folder_item.set( { 'from_hda_id':history_dataset_id } );
         hdas_to_add.push( folder_item );
       }
@@ -749,7 +749,7 @@
       }
       return true;
     }
-    var promise = $.when( $.post( '/api/libraries/datasets?encoded_folder_id=' + that.id + 
+    var promise = $.when( $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets?encoded_folder_id=' + that.id + 
                                                        '&source=' + options.source +
                                                        '&path=' + popped_item +
                                                        '&file_type=' + options.file_type +
@@ -788,7 +788,7 @@
       }
       return true;
     }
-    var promise = $.when( $.post( '/api/libraries/datasets?encoded_folder_id=' + that.id +
+    var promise = $.when( $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets?encoded_folder_id=' + that.id +
                                                           '&source=' + options.source +
                                                           '&path=' + popped_item +
                                                           '&preserve_dirs=' + options.preserve_dirs +

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/library/library-library-view.js
--- a/static/scripts/mvc/library/library-library-view.js
+++ b/static/scripts/mvc/library/library-library-view.js
@@ -87,7 +87,7 @@
 
     var self = this;
     if (this.options.fetched_permissions === undefined){
-      $.get( "/api/libraries/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
+      $.get( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/" + self.id + "/permissions?scope=current").done(function(fetched_permissions) {
         self.prepareSelectBoxes({fetched_permissions:fetched_permissions});
       }).fail(function(){
           mod_toastr.error('An error occurred while attempting to fetch library permissions.');
@@ -134,7 +134,7 @@
       placeholder: 'Click to select a role',
       container: self.$el.find('#' + id),
       ajax: {
-          url: "/api/libraries/" + self.id + "/permissions?scope=available&is_library_access=" + is_library_access,
+          url: ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/" + self.id + "/permissions?scope=available&is_library_access=" + is_library_access,
           dataType: 'json',
           quietMillis: 100,
           data: function (term, page) { // page is the one-based page number tracked by Select2
@@ -193,7 +193,7 @@
 
   makeDatasetPrivate: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=make_private").done(function(fetched_permissions) {
       self.model.set({is_unrestricted:false});
       self.showPermissions({fetched_permissions:fetched_permissions})
       mod_toastr.success('The dataset is now private to you.');
@@ -204,7 +204,7 @@
 
   removeDatasetRestrictions: function(){
     var self = this;
-    $.post("/api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/datasets/" + self.id + "/permissions?action=remove_restrictions")
     .done(function(fetched_permissions) {
       self.model.set({is_unrestricted:true});
       self.showPermissions({fetched_permissions:fetched_permissions})
@@ -230,7 +230,7 @@
     var manage_ids = this._extractIds(this.manageSelectObject.$el.select2('data'));
     var modify_ids = this._extractIds(this.modifySelectObject.$el.select2('data'));
 
-    $.post("/api/libraries/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
+    $.post( ( window.galaxy_config ? galaxy_config.root : '/' ) + "api/libraries/" + self.id + "/permissions?action=set_permissions", { 'access_ids[]': access_ids, 'add_ids[]': add_ids, 'manage_ids[]': manage_ids, 'modify_ids[]': modify_ids, } )
     .done(function(fetched_permissions){
       //fetch dataset again
       self.showPermissions({fetched_permissions:fetched_permissions})

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/library/library-model.js
--- a/static/scripts/mvc/library/library-model.js
+++ b/static/scripts/mvc/library/library-model.js
@@ -4,7 +4,7 @@
 // LIBRARY RELATED MODELS
 
     var Library = Backbone.Model.extend({
-      urlRoot: '/api/libraries/',
+      urlRoot: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/',
 
       /** based on show_deleted would this lib show in the list of lib's?
        *  @param {Boolean} show_deleted are we including deleted libraries?
@@ -19,7 +19,7 @@
     });
 
     var Libraries = Backbone.Collection.extend({
-      url: '/api/libraries',
+      url: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries',
 
       model: Library,
 
@@ -84,15 +84,15 @@
 // FOLDER RELATED MODELS
 
     var Item = Backbone.Model.extend({
-      urlRoot : '/api/libraries/datasets/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/'
     });
 
     var Ldda = Backbone.Model.extend({
-      urlRoot : '/api/libraries/datasets/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/libraries/datasets/'
     });
 
     var FolderAsModel = Backbone.Model.extend({
-      urlRoot: '/api/folders'
+      urlRoot: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/folders'
     });
 
     var Folder = Backbone.Collection.extend({
@@ -152,7 +152,7 @@
     var FolderContainer = Backbone.Model.extend({
         defaults : {
             folder : new Folder(),
-            urlRoot : "/api/folders/",
+            urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/folders/',
             id : "unknown"
         },
     parse : function(obj) {
@@ -169,11 +169,11 @@
 // TODO UNITE
 
     var HistoryItem = Backbone.Model.extend({
-      urlRoot : '/api/histories/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories/'
     });
 
     var HistoryContents = Backbone.Collection.extend({
-      urlRoot : '/api/histories/',
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories/',
       initialize: function(options){
         this.id = options.id;
       },
@@ -184,11 +184,11 @@
     });
 
     var GalaxyHistory = Backbone.Model.extend({
-      urlRoot : '/api/histories/'
+      urlRoot : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories/'
     });
 
     var GalaxyHistories = Backbone.Collection.extend({
-      url : '/api/histories',
+      url : ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/histories',
       model : GalaxyHistory
     });
 
@@ -199,7 +199,7 @@
      */
     
     var Jstree = Backbone.Model.extend({
-      urlRoot: '/api/remote_files'
+      urlRoot: ( window.galaxy_config ? galaxy_config.root : '/' ) + 'api/remote_files'
     });
 
 return {

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/mvc/tools/tools-parameters.js
--- a/static/scripts/mvc/tools/tools-parameters.js
+++ b/static/scripts/mvc/tools/tools-parameters.js
@@ -145,6 +145,7 @@
                 data        : options,
                 error_text  : input_def.error_text || 'No options available',
                 multiple    : input_def.multiple,
+                optional    : input_def.optional,
                 searchable  : input_def.searchable,
                 onchange    : function() {
                     self.app.trigger('refresh');

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/packed/mvc/history/history-model.js
--- a/static/scripts/packed/mvc/history/history-model.js
+++ b/static/scripts/packed/mvc/history/history-model.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-contents","mvc/base-mvc","utils/localization"],function(h,i,d){var e=Backbone.Model.extend(i.LoggableMixin).extend(i.mixin(i.SearchableModelMixin,{defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",initialize:function(k,l,j){j=j||{};this.logger=j.logger||null;this.log(this+".initialize:",k,l,j);this.log("creating history contents:",l);this.contents=new h.HistoryContents(l||[],{historyId:this.get("id")});this._setUpListeners();this.updateTimeoutId=null},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});if(this.contents){this.listenTo(this.contents,"error",function(){this.trigger.apply(this,["error:contents"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(k,j){if(this.contents){this.contents.historyId=j}},this)},errorHandler:function(k,n,j,m,l){this.clearUpdateTimeout()},ownedByCurrUser:function(){if(!Galaxy||!Galaxy.currUser){return false}if(Galaxy.currUser.isAnonymous()||Galaxy.currUser.id!==this.get("user_id")){return false}return true},contentsCount:function(){return _.reduce(_.values(this.get("state_details")),function(j,k){return j+k},0)},searchAttributes:["name","annotation","tags"],searchAliases:{title:"name",tag:"tags"},checkForUpdates:function(j){if(this.contents.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(j)){j.call(this)}}return this},setUpdateTimeout:function(j){j=j||e.UPDATE_DELAY;var k=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){k.refresh()},j);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(k,j){k=k||[];j=j||{};var l=this;j.data=j.data||{};if(k.length){j.data.details=k.join(",")}var m=this.contents.fetch(j);m.done(function(n){l.checkForUpdates(function(){this.fetch()})});return m},_delete:function(j){if(this.get("deleted")){return jQuery.when()}return this.save({deleted:true},j)},purge:function(j){if(this.get("purged")){return jQuery.when()}return this.save({deleted:true,purged:true},j)},undelete:function(j){if(!this.get("deleted")){return jQuery.when()}return this.save({deleted:false},j)},copy:function(m,k){m=(m!==undefined)?(m):(true);if(!this.id){throw new Error("You must set the history ID before copying it.")}var j={history_id:this.id};if(m){j.current=true}if(k){j.name=k}var l=this,n=jQuery.post(this.urlRoot,j);if(m){return n.then(function(o){var p=new e(o);return p.setAsCurrent().done(function(){l.trigger("copied",l,o)})})}return n.done(function(o){l.trigger("copied",l,o)})},setAsCurrent:function(){var j=this,k=jQuery.getJSON("/history/set_as_current?id="+this.id);k.done(function(){j.trigger("set-as-current",j)});return k},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}}));e.UPDATE_DELAY=4000;e.getHistoryData=function c(j,v){v=v||{};var r=v.detailIdsFn||[];var m=v.hdcaDetailIds||[];var s=jQuery.Deferred(),p=null;function k(w){if(j==="current"){return jQuery.getJSON(galaxy_config.root+"history/current_history_json")}return jQuery.ajax(galaxy_config.root+"api/histories/"+j)}function o(w){return w&&w.empty}function q(x){if(o(x)){return[]}if(_.isFunction(r)){r=r(x)}if(_.isFunction(m)){m=m(x)}var w={};if(r.length){w.dataset_details=r.join(",")}if(m.length){w.dataset_collection_details=m.join(",")}return jQuery.ajax(galaxy_config.root+"api/histories/"+x.id+"/contents",{data:w})}var t=v.historyFn||k,u=v.contentsFn||q;var n=t(j);n.done(function(w){p=w;s.notify({status:"history data retrieved",historyJSON:p})});n.fail(function(y,w,x){s.reject(y,"loading the history")});var l=n.then(u);l.then(function(w){s.notify({status:"contents data retrieved",historyJSON:p,contentsJSON:w});s.resolve(p,w)});l.fail(function(y,w,x){s.reject(y,"loading the contents",{history:p})});return s};var f=Backbone.Collection.extend(i.LoggableMixin).extend({model:e,urlRoot:(window.galaxy_config?galaxy_config.root:"/")+"api/histories",initialize:function(k,j){j=j||{};this.log("HistoryCollection.initialize",arguments);this.includeDeleted=j.includeDeleted||false;this.setUpListeners()},setUpListeners:function a(){var j=this;this.on("change:deleted",function(k){this.debug("change:deleted",j.includeDeleted,k.get("deleted"));if(!j.includeDeleted&&k.get("deleted")){j.remove(k)}});this.on("copied",function(k,l){this.unshift(new e(l,[]))})},create:function g(m,k,j,l){var o=this,n=jQuery.getJSON(galaxy_config.root+"history/create_new_current");return n.done(function(p){var q=new e(p,[],j||{});o.unshift(q);o.trigger("new-current")})},toString:function b(){return"HistoryCollection("+this.length+")"}});return{History:e,HistoryCollection:f}});
\ No newline at end of file
+define(["mvc/history/history-contents","mvc/base-mvc","utils/localization"],function(h,i,d){var e=Backbone.Model.extend(i.LoggableMixin).extend(i.mixin(i.SearchableModelMixin,{defaults:{model_class:"History",id:null,name:"Unnamed History",state:"new",diskSize:0,deleted:false},urlRoot:galaxy_config.root+"api/histories",initialize:function(k,l,j){j=j||{};this.logger=j.logger||null;this.log(this+".initialize:",k,l,j);this.log("creating history contents:",l);this.contents=new h.HistoryContents(l||[],{historyId:this.get("id")});this._setUpListeners();this.updateTimeoutId=null},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});if(this.contents){this.listenTo(this.contents,"error",function(){this.trigger.apply(this,["error:contents"].concat(jQuery.makeArray(arguments)))})}this.on("change:id",function(k,j){if(this.contents){this.contents.historyId=j}},this)},errorHandler:function(k,n,j,m,l){this.clearUpdateTimeout()},ownedByCurrUser:function(){if(!Galaxy||!Galaxy.currUser){return false}if(Galaxy.currUser.isAnonymous()||Galaxy.currUser.id!==this.get("user_id")){return false}return true},contentsCount:function(){return _.reduce(_.values(this.get("state_details")),function(j,k){return j+k},0)},searchAttributes:["name","annotation","tags"],searchAliases:{title:"name",tag:"tags"},checkForUpdates:function(j){if(this.contents.running().length){this.setUpdateTimeout()}else{this.trigger("ready");if(_.isFunction(j)){j.call(this)}}return this},setUpdateTimeout:function(j){j=j||e.UPDATE_DELAY;var k=this;this.clearUpdateTimeout();this.updateTimeoutId=setTimeout(function(){k.refresh()},j);return this.updateTimeoutId},clearUpdateTimeout:function(){if(this.updateTimeoutId){clearTimeout(this.updateTimeoutId);this.updateTimeoutId=null}},refresh:function(k,j){k=k||[];j=j||{};var l=this;j.data=j.data||{};if(k.length){j.data.details=k.join(",")}var m=this.contents.fetch(j);m.done(function(n){l.checkForUpdates(function(){this.fetch()})});return m},_delete:function(j){if(this.get("deleted")){return jQuery.when()}return this.save({deleted:true},j)},purge:function(j){if(this.get("purged")){return jQuery.when()}return this.save({deleted:true,purged:true},j)},undelete:function(j){if(!this.get("deleted")){return jQuery.when()}return this.save({deleted:false},j)},copy:function(m,k){m=(m!==undefined)?(m):(true);if(!this.id){throw new Error("You must set the history ID before copying it.")}var j={history_id:this.id};if(m){j.current=true}if(k){j.name=k}var l=this,n=jQuery.post(this.urlRoot,j);if(m){return n.then(function(o){var p=new e(o);return p.setAsCurrent().done(function(){l.trigger("copied",l,o)})})}return n.done(function(o){l.trigger("copied",l,o)})},setAsCurrent:function(){var j=this,k=jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+this.id);k.done(function(){j.trigger("set-as-current",j)});return k},toString:function(){return"History("+this.get("id")+","+this.get("name")+")"}}));e.UPDATE_DELAY=4000;e.getHistoryData=function c(j,v){v=v||{};var r=v.detailIdsFn||[];var m=v.hdcaDetailIds||[];var s=jQuery.Deferred(),p=null;function k(w){if(j==="current"){return jQuery.getJSON(galaxy_config.root+"history/current_history_json")}return jQuery.ajax(galaxy_config.root+"api/histories/"+j)}function o(w){return w&&w.empty}function q(x){if(o(x)){return[]}if(_.isFunction(r)){r=r(x)}if(_.isFunction(m)){m=m(x)}var w={};if(r.length){w.dataset_details=r.join(",")}if(m.length){w.dataset_collection_details=m.join(",")}return jQuery.ajax(galaxy_config.root+"api/histories/"+x.id+"/contents",{data:w})}var t=v.historyFn||k,u=v.contentsFn||q;var n=t(j);n.done(function(w){p=w;s.notify({status:"history data retrieved",historyJSON:p})});n.fail(function(y,w,x){s.reject(y,"loading the history")});var l=n.then(u);l.then(function(w){s.notify({status:"contents data retrieved",historyJSON:p,contentsJSON:w});s.resolve(p,w)});l.fail(function(y,w,x){s.reject(y,"loading the contents",{history:p})});return s};var f=Backbone.Collection.extend(i.LoggableMixin).extend({model:e,urlRoot:(window.galaxy_config?galaxy_config.root:"/")+"api/histories",initialize:function(k,j){j=j||{};this.log("HistoryCollection.initialize",arguments);this.includeDeleted=j.includeDeleted||false;this.setUpListeners()},setUpListeners:function a(){var j=this;this.on("change:deleted",function(k){this.debug("change:deleted",j.includeDeleted,k.get("deleted"));if(!j.includeDeleted&&k.get("deleted")){j.remove(k)}});this.on("copied",function(k,l){this.unshift(new e(l,[]))})},create:function g(m,k,j,l){var o=this,n=jQuery.getJSON(galaxy_config.root+"history/create_new_current");return n.done(function(p){var q=new e(p,[],j||{});o.unshift(q);o.trigger("new-current")})},toString:function b(){return"HistoryCollection("+this.length+")"}});return{History:e,HistoryCollection:f}});
\ No newline at end of file

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/packed/mvc/library/library-dataset-view.js
--- a/static/scripts/packed/mvc/library/library-dataset-view.js
+++ b/static/scripts/packed/mvc/library/library-dataset-view.js
@@ -1,1 +1,1 @@
-define(["libs/toastr","mvc/library/library-model","mvc/ui/ui-select"],function(d,c,b){var a=Backbone.View.extend({el:"#center",model:null,options:{},events:{"click .toolbtn_modify_dataset":"enableModification","click .toolbtn_cancel_modifications":"render","click .toolbtn-download-dataset":"downloadDataset","click .toolbtn-import-dataset":"importIntoHistory","click .toolbtn-share-dataset":"shareDataset","click .btn-copy-link-to-clipboard":"copyToClipboard","click .btn-make-private":"makeDatasetPrivate","click .btn-remove-restrictions":"removeDatasetRestrictions","click .toolbtn_save_permissions":"savePermissions","click .toolbtn_save_modifications":"comingSoon",},initialize:function(e){this.options=_.extend(this.options,e);if(this.options.id){this.fetchDataset()}},fetchDataset:function(e){this.options=_.extend(this.options,e);this.model=new c.Item({id:this.options.id});var f=this;this.model.fetch({success:function(){if(f.options.show_permissions){f.showPermissions()}else{if(f.options.show_version){f.fetchVersion()}else{f.render()}}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{d.error("An error ocurred. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(e){this.options=_.extend(this.options,e);$(".tooltip").remove();var f=this.templateDataset();this.$el.html(f({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},fetchVersion:function(e){this.options=_.extend(this.options,e);that=this;if(!this.options.ldda_id){this.render();d.error("Library dataset version requested but no id provided.")}else{this.ldda=new c.Ldda({id:this.options.ldda_id});this.ldda.url=this.ldda.urlRoot+this.model.id+"/versions/"+this.ldda.id;this.ldda.fetch({success:function(){that.renderVersion()},error:function(g,f){if(typeof f.responseJSON!=="undefined"){d.error(f.responseJSON.err_msg)}else{d.error("An error ocurred.")}}})}},renderVersion:function(){$(".tooltip").remove();var e=this.templateVersion();this.$el.html(e({item:this.model,ldda:this.ldda}));$(".peek").html(this.ldda.get("peek"))},enableModification:function(){$(".tooltip").remove();var e=this.templateModifyDataset();this.$el.html(e({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},downloadDataset:function(){var e="/api/libraries/datasets/download/uncompressed";var f={ld_ids:this.id};this.processDownload(e,f)},processDownload:function(f,g,h){if(f&&g){g=typeof g=="string"?g:$.param(g);var e="";$.each(g.split("&"),function(){var i=this.split("=");e+='<input type="hidden" name="'+i[0]+'" value="'+i[1]+'" />'});$('<form action="'+f+'" method="'+(h||"post")+'">'+e+"</form>").appendTo("body").submit().remove();d.info("Your download will begin soon.")}},importIntoHistory:function(){this.refreshUserHistoriesList(function(e){var f=e.templateBulkImportInModal();e.modal=Galaxy.modal;e.modal.show({closing_events:true,title:"Import into History",body:f({histories:e.histories.models}),buttons:{Import:function(){e.importCurrentIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})},refreshUserHistoriesList:function(f){var e=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(g){if(g.length===0){d.warning("You have to create history first. Click this to do so.","",{onclick:function(){window.location="/"}})}else{f(e)}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg)}else{d.error("An error ocurred.")}}})},importCurrentIntoHistory:function(){var e=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();var f=new c.HistoryItem();f.url=f.urlRoot+e+"/contents";jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+e);f.save({content:this.id,source:"library"},{success:function(){Galaxy.modal.hide();d.success("Dataset imported. Click this to start analysing it.","",{onclick:function(){window.location="/"}})},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error("Dataset not imported. "+g.responseJSON.err_msg)}else{d.error("An error occured. Dataset not imported. Please try again.")}}})},shareDataset:function(){d.info("Feature coming soon.")},goBack:function(){Galaxy.libraries.library_router.back()},showPermissions:function(f){this.options=_.extend(this.options,f);$(".tooltip").remove();if(this.options.fetched_permissions!==undefined){if(this.options.fetched_permissions.access_dataset_roles.length===0){this.model.set({is_unrestricted:true})}else{this.model.set({is_unrestricted:false})}}var h=false;if(Galaxy.currUser){h=Galaxy.currUser.isAdmin()}var g=this.templateDatasetPermissions();this.$el.html(g({item:this.model,is_admin:h}));var e=this;if(this.options.fetched_permissions===undefined){$.get("/api/libraries/datasets/"+e.id+"/permissions?scope=current").done(function(i){e.prepareSelectBoxes({fetched_permissions:i,is_admin:h})}).fail(function(){d.error("An error occurred while attempting to fetch dataset permissions.")})}else{this.prepareSelectBoxes({is_admin:h})}$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},prepareSelectBoxes:function(r){this.options=_.extend(this.options,r);var s=this.options.fetched_permissions;var k=this.options.is_admin;var q=this;var m=[];for(var h=0;h<s.access_dataset_roles.length;h++){m.push(s.access_dataset_roles[h]+":"+s.access_dataset_roles[h])}var f=[];for(var h=0;h<s.modify_item_roles.length;h++){f.push(s.modify_item_roles[h]+":"+s.modify_item_roles[h])}var g=[];for(var h=0;h<s.manage_dataset_roles.length;h++){g.push(s.manage_dataset_roles[h]+":"+s.manage_dataset_roles[h])}if(k){var o={minimumInputLength:0,css:"access_perm",multiple:true,placeholder:"Click to select a role",container:q.$el.find("#access_perm"),ajax:{url:"/api/libraries/datasets/"+q.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(i,t){return{q:i,page_limit:10,page:t}},results:function(u,t){var i=(t*10)<u.total;return{results:u.roles,more:i}}},formatResult:function j(i){return i.name+" type: "+i.type},formatSelection:function e(i){return i.name},initSelection:function(i,u){var t=[];$(i.val().split(",")).each(function(){var v=this.split(":");t.push({id:v[1],name:v[1]})});u(t)},initialData:m.join(","),dropdownCssClass:"bigdrop"};var l={minimumInputLength:0,css:"modify_perm",multiple:true,placeholder:"Click to select a role",container:q.$el.find("#modify_perm"),ajax:{url:"/api/libraries/datasets/"+q.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(i,t){return{q:i,page_limit:10,page:t}},results:function(u,t){var i=(t*10)<u.total;return{results:u.roles,more:i}}},formatResult:function j(i){return i.name+" type: "+i.type},formatSelection:function e(i){return i.name},initSelection:function(i,u){var t=[];$(i.val().split(",")).each(function(){var v=this.split(":");t.push({id:v[1],name:v[1]})});u(t)},initialData:f.join(","),dropdownCssClass:"bigdrop"};var p={minimumInputLength:0,css:"manage_perm",multiple:true,placeholder:"Click to select a role",container:q.$el.find("#manage_perm"),ajax:{url:"/api/libraries/datasets/"+q.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(i,t){return{q:i,page_limit:10,page:t}},results:function(u,t){var i=(t*10)<u.total;return{results:u.roles,more:i}}},formatResult:function j(i){return i.name+" type: "+i.type},formatSelection:function e(i){return i.name},initSelection:function(i,u){var t=[];$(i.val().split(",")).each(function(){var v=this.split(":");t.push({id:v[1],name:v[1]})});u(t)},initialData:g.join(","),dropdownCssClass:"bigdrop"};q.accessSelectObject=new b.View(o);q.modifySelectObject=new b.View(l);q.manageSelectObject=new b.View(p)}else{var n=q.templateAccessSelect();$.get("/api/libraries/datasets/"+q.id+"/permissions?scope=available",function(i){$(".access_perm").html(n({options:i.roles}));q.accessSelectObject=$("#access_select").select2()}).fail(function(){d.error("An error occurred while attempting to fetch dataset permissions.")})}},comingSoon:function(){d.warning("Feature coming soon.")},copyToClipboard:function(){var e=Backbone.history.location.href;if(e.lastIndexOf("/permissions")!==-1){e=e.substr(0,e.lastIndexOf("/permissions"))}window.prompt("Copy to clipboard: Ctrl+C, Enter",e)},makeDatasetPrivate:function(){var e=this;$.post("/api/libraries/datasets/"+e.id+"/permissions?action=make_private").done(function(f){e.model.set({is_unrestricted:false});e.showPermissions({fetched_permissions:f});d.success("The dataset is now private to you.")}).fail(function(){d.error("An error occurred while attempting to make dataset private.")})},removeDatasetRestrictions:function(){var e=this;$.post("/api/libraries/datasets/"+e.id+"/permissions?action=remove_restrictions").done(function(f){e.model.set({is_unrestricted:true});e.showPermissions({fetched_permissions:f});d.success("Access to this dataset is now unrestricted.")}).fail(function(){d.error("An error occurred while attempting to make dataset unrestricted.")})},savePermissions:function(e){var n=this;var k=this.accessSelectObject.$el.select2("data");var f=this.manageSelectObject.$el.select2("data");var m=this.modifySelectObject.$el.select2("data");var g=[];var j=[];var l=[];for(var h=k.length-1;h>=0;h--){g.push(k[h].id)}for(var h=f.length-1;h>=0;h--){j.push(f[h].id)}for(var h=m.length-1;h>=0;h--){l.push(m[h].id)}$.post("/api/libraries/datasets/"+n.id+"/permissions?action=set_permissions",{"access_ids[]":g,"manage_ids[]":j,"modify_ids[]":l,}).done(function(i){n.showPermissions({fetched_permissions:i});d.success("Permissions saved.")}).fail(function(){d.error("An error occurred while attempting to set dataset permissions.")})},templateDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <button data-toggle="tooltip" data-placement="top" title="Download dataset" class="btn btn-default toolbtn-download-dataset primary-button" type="button"><span class="fa fa-download"></span> Download</span></button>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Import dataset into history" class="btn btn-default toolbtn-import-dataset primary-button" type="button"><span class="fa fa-book"></span> to History</span></button>');e.push('   <% if (item.get("can_user_modify")) { %>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Modify library item" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');e.push("   <% } %>");e.push('   <% if (item.get("can_user_manage")) { %>');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" title="Manage permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button></a>');e.push("   <% } %>");e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('<% if (item.get("is_unrestricted")) { %>');e.push('  <div class="alert alert-info">');e.push("  This dataset is unrestricted so everybody can access it. Just share the URL of this page. ");e.push('  <button data-toggle="tooltip" data-placement="top" title="Copy to clipboard" class="btn btn-default btn-copy-link-to-clipboard primary-button" type="button"><span class="fa fa-clipboard"></span> To Clipboard</span></button> ');e.push("  </div>");e.push("<% } %>");e.push('<div class="dataset_table">');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push('           <td><%= _.escape(item.get("name")) %></td>');e.push("       </tr>");e.push('   <% if (item.get("file_ext")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(item.get("file_ext")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("genome_build")) { %>');e.push("       <tr>");e.push('           <th scope="row">Genome build</th>');e.push('           <td><%= _.escape(item.get("genome_build")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("file_size")) { %>');e.push("       <tr>");e.push('           <th scope="row">Size</th>');e.push('           <td><%= _.escape(item.get("file_size")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("date_uploaded")) { %>');e.push("       <tr>");e.push('           <th scope="row">Date uploaded (UTC)</th>');e.push('           <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("uploaded_by")) { %>');e.push("       <tr>");e.push('           <th scope="row">Uploaded by</th>');e.push('           <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_data_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data Lines</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_comment_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Comment Lines</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_columns")) { %>');e.push("       <tr>");e.push('           <th scope="row">Number of Columns</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_column_types")) { %>');e.push("       <tr>");e.push('           <th scope="row">Column Types</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("message")) { %>');e.push("       <tr>");e.push('           <th scope="row">Message</th>');e.push('           <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("misc_blurb")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous blurb</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("misc_info")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous information</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push("    </table>");e.push("    <div>");e.push('        <pre class="peek">');e.push("        </pre>");e.push("    </div>");e.push('   <% if (item.get("has_versions")) { %>');e.push("      <div>");e.push("      <h3>Expired versions:</h3>");e.push("      <ul>");e.push('      <% _.each(item.get("expired_versions"), function(version) { %>');e.push('        <li><a title="See details of this version" href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/versions/<%- version[0] %>"><%- version[1] %></a></li>');e.push("      <% }) %>");e.push("      <ul>");e.push("      </div>");e.push("   <% } %>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateVersion:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>"><button data-toggle="tooltip" data-placement="top" title="Go to latest dataset" class="btn btn-default primary-button" type="button"><span class="fa fa-caret-left fa-lg"></span> Latest dataset</span></button><a>');e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('  <div class="alert alert-warning">This is an expired version of the library dataset: <%= _.escape(item.get("name")) %></div>');e.push('<div class="dataset_table">');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(ldda.id) %>">Name</th>');e.push('           <td><%= _.escape(ldda.get("name")) %></td>');e.push("       </tr>");e.push('   <% if (ldda.get("file_ext")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(ldda.get("file_ext")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("genome_build")) { %>');e.push("       <tr>");e.push('           <th scope="row">Genome build</th>');e.push('           <td><%= _.escape(ldda.get("genome_build")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("file_size")) { %>');e.push("       <tr>");e.push('           <th scope="row">Size</th>');e.push('           <td><%= _.escape(ldda.get("file_size")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("date_uploaded")) { %>');e.push("       <tr>");e.push('           <th scope="row">Date uploaded (UTC)</th>');e.push('           <td><%= _.escape(ldda.get("date_uploaded")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("uploaded_by")) { %>');e.push("       <tr>");e.push('           <th scope="row">Uploaded by</th>');e.push('           <td><%= _.escape(ldda.get("uploaded_by")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_data_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data Lines</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_data_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_comment_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Comment Lines</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_comment_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_columns")) { %>');e.push("       <tr>");e.push('           <th scope="row">Number of Columns</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_columns")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_column_types")) { %>');e.push("       <tr>");e.push('           <th scope="row">Column Types</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_column_types")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("message")) { %>');e.push("       <tr>");e.push('           <th scope="row">Message</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("message")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("misc_blurb")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous blurb</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("misc_blurb")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("misc_info")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous information</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("misc_info")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push("    </table>");e.push("    <div>");e.push('        <pre class="peek">');e.push("        </pre>");e.push("    </div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateModifyDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('<div class="dataset_table">');e.push('<p>For more editing options please import the dataset to history and use "Edit attributes" on it.</p>');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push('           <td><input class="input_dataset_name form-control" type="text" placeholder="name" value="<%= _.escape(item.get("name")) %>"></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(item.get("file_ext")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Genome build</th>');e.push('           <td><%= _.escape(item.get("genome_build")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Size</th>');e.push('           <td><%= _.escape(item.get("file_size")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Date uploaded (UTC)</th>');e.push('           <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Uploaded by</th>');e.push('           <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push("       </tr>");e.push('           <tr scope="row">');e.push('           <th scope="row">Data Lines</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push("       </tr>");e.push('       <th scope="row">Comment Lines</th>');e.push('           <% if (item.get("metadata_comment_lines") === "") { %>');e.push('               <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push("           <% } else { %>");e.push('               <td scope="row">unknown</td>');e.push("           <% } %>");e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Number of Columns</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Column Types</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Message</th>');e.push('           <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Miscellaneous information</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Miscellaneous blurb</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push("       </tr>");e.push("   </table>");e.push("<div>");e.push('   <pre class="peek">');e.push("   </pre>");e.push("</div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateDatasetPermissions:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <a href="#folders/<%- item.get("folder_id") %>"><button data-toggle="tooltip" data-placement="top" title="Go back to containing folder" class="btn btn-default primary-button" type="button"><span class="fa fa-folder-open-o"></span> Containing Folder</span></button></a>');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>"><button data-toggle="tooltip" data-placement="top" title="Go back to dataset" class="btn btn-default primary-button" type="button"><span class="fa fa-file-o"></span> Dataset Details</span></button><a>');e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('<h1>Dataset: <%= _.escape(item.get("name")) %></h1>');e.push('<div class="alert alert-warning">');e.push("<% if (is_admin) { %>");e.push("You are logged in as an <strong>administrator</strong> therefore you can manage any dataset on this Galaxy instance. Please make sure you understand the consequences.");e.push("<% } else { %>");e.push("You can assign any number of roles to any of the following permission types. However please read carefully the implications of such actions.");e.push("<% } %>");e.push("</div>");e.push('<div class="dataset_table">');e.push("<h2>Library-related permissions</h2>");e.push("<h4>Roles that can modify the library item</h4>");e.push('<div id="modify_perm" class="modify_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can modify name, metadata, and other information about this library item.</div>');e.push("<hr/>");e.push("<h2>Dataset-related permissions</h2>");e.push('<div class="alert alert-warning">Changes made below will affect <strong>every</strong> library item that was created from this dataset and also every history this dataset is part of.</div>');e.push('<% if (!item.get("is_unrestricted")) { %>');e.push(" <p>You can remove all access restrictions on this dataset. ");e.push(' <button data-toggle="tooltip" data-placement="top" title="Everybody will be able to access the dataset." class="btn btn-default btn-remove-restrictions primary-button" type="button">');e.push(' <span class="fa fa-globe"> Remove restrictions</span>');e.push(" </button>");e.push(" </p>");e.push("<% } else { %>");e.push("  This dataset is unrestricted so everybody can access it. Just share the URL of this page.");e.push('  <button data-toggle="tooltip" data-placement="top" title="Copy to clipboard" class="btn btn-default btn-copy-link-to-clipboard primary-button" type="button"><span class="fa fa-clipboard"> To Clipboard</span></button> ');e.push("  <p>You can make this dataset private to you. ");e.push(' <button data-toggle="tooltip" data-placement="top" title="Only you will be able to access the dataset." class="btn btn-default btn-make-private primary-button" type="button"><span class="fa fa-key"> Make Private</span></button>');e.push(" </p>");e.push("<% } %>");e.push("<h4>Roles that can access the dataset</h4>");e.push('<div id="access_perm" class="access_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User has to have <strong>all these roles</strong> in order to access this dataset. Users without access permission <strong>cannot</strong> have other permissions on this dataset. If there are no access roles set on the dataset it is considered <strong>unrestricted</strong>.</div>');e.push("<h4>Roles that can manage permissions on the dataset</h4>");e.push('<div id="manage_perm" class="manage_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can manage permissions of this dataset. If you remove yourself you will loose the ability manage this dataset unless you are an admin.</div>');e.push('<button data-toggle="tooltip" data-placement="top" title="Save modifications made on this page" class="btn btn-default toolbtn_save_permissions primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateBulkImportInModal:function(){var e=[];e.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');e.push("Select history: ");e.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');e.push("   <% _.each(histories, function(history) { %>");e.push('       <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');e.push("   <% }); %>");e.push("</select>");e.push("</span>");return _.template(e.join(""))},templateAccessSelect:function(){var e=[];e.push('<select id="access_select" multiple>');e.push("   <% _.each(options, function(option) { %>");e.push('       <option value="<%- option.name %>"><%- option.name %></option>');e.push("   <% }); %>");e.push("</select>");return _.template(e.join(""))}});return{LibraryDatasetView:a}});
\ No newline at end of file
+define(["libs/toastr","mvc/library/library-model","mvc/ui/ui-select"],function(d,c,b){var a=Backbone.View.extend({el:"#center",model:null,options:{},events:{"click .toolbtn_modify_dataset":"enableModification","click .toolbtn_cancel_modifications":"render","click .toolbtn-download-dataset":"downloadDataset","click .toolbtn-import-dataset":"importIntoHistory","click .toolbtn-share-dataset":"shareDataset","click .btn-copy-link-to-clipboard":"copyToClipboard","click .btn-make-private":"makeDatasetPrivate","click .btn-remove-restrictions":"removeDatasetRestrictions","click .toolbtn_save_permissions":"savePermissions","click .toolbtn_save_modifications":"comingSoon",},initialize:function(e){this.options=_.extend(this.options,e);if(this.options.id){this.fetchDataset()}},fetchDataset:function(e){this.options=_.extend(this.options,e);this.model=new c.Item({id:this.options.id});var f=this;this.model.fetch({success:function(){if(f.options.show_permissions){f.showPermissions()}else{if(f.options.show_version){f.fetchVersion()}else{f.render()}}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{d.error("An error ocurred. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(e){this.options=_.extend(this.options,e);$(".tooltip").remove();var f=this.templateDataset();this.$el.html(f({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},fetchVersion:function(e){this.options=_.extend(this.options,e);that=this;if(!this.options.ldda_id){this.render();d.error("Library dataset version requested but no id provided.")}else{this.ldda=new c.Ldda({id:this.options.ldda_id});this.ldda.url=this.ldda.urlRoot+this.model.id+"/versions/"+this.ldda.id;this.ldda.fetch({success:function(){that.renderVersion()},error:function(g,f){if(typeof f.responseJSON!=="undefined"){d.error(f.responseJSON.err_msg)}else{d.error("An error ocurred.")}}})}},renderVersion:function(){$(".tooltip").remove();var e=this.templateVersion();this.$el.html(e({item:this.model,ldda:this.ldda}));$(".peek").html(this.ldda.get("peek"))},enableModification:function(){$(".tooltip").remove();var e=this.templateModifyDataset();this.$el.html(e({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},downloadDataset:function(){var e=(window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/download/uncompressed";var f={ld_ids:this.id};this.processDownload(e,f)},processDownload:function(f,g,h){if(f&&g){g=typeof g=="string"?g:$.param(g);var e="";$.each(g.split("&"),function(){var i=this.split("=");e+='<input type="hidden" name="'+i[0]+'" value="'+i[1]+'" />'});$('<form action="'+f+'" method="'+(h||"post")+'">'+e+"</form>").appendTo("body").submit().remove();d.info("Your download will begin soon.")}},importIntoHistory:function(){this.refreshUserHistoriesList(function(e){var f=e.templateBulkImportInModal();e.modal=Galaxy.modal;e.modal.show({closing_events:true,title:"Import into History",body:f({histories:e.histories.models}),buttons:{Import:function(){e.importCurrentIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})},refreshUserHistoriesList:function(f){var e=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(g){if(g.length===0){d.warning("You have to create history first. Click this to do so.","",{onclick:function(){window.location="/"}})}else{f(e)}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg)}else{d.error("An error ocurred.")}}})},importCurrentIntoHistory:function(){var e=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();var f=new c.HistoryItem();f.url=f.urlRoot+e+"/contents";jQuery.getJSON(galaxy_config.root+"history/set_as_current?id="+e);f.save({content:this.id,source:"library"},{success:function(){Galaxy.modal.hide();d.success("Dataset imported. Click this to start analysing it.","",{onclick:function(){window.location="/"}})},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error("Dataset not imported. "+g.responseJSON.err_msg)}else{d.error("An error occured. Dataset not imported. Please try again.")}}})},shareDataset:function(){d.info("Feature coming soon.")},goBack:function(){Galaxy.libraries.library_router.back()},showPermissions:function(f){this.options=_.extend(this.options,f);$(".tooltip").remove();if(this.options.fetched_permissions!==undefined){if(this.options.fetched_permissions.access_dataset_roles.length===0){this.model.set({is_unrestricted:true})}else{this.model.set({is_unrestricted:false})}}var h=false;if(Galaxy.currUser){h=Galaxy.currUser.isAdmin()}var g=this.templateDatasetPermissions();this.$el.html(g({item:this.model,is_admin:h}));var e=this;if(this.options.fetched_permissions===undefined){$.get((window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+e.id+"/permissions?scope=current").done(function(i){e.prepareSelectBoxes({fetched_permissions:i,is_admin:h})}).fail(function(){d.error("An error occurred while attempting to fetch dataset permissions.")})}else{this.prepareSelectBoxes({is_admin:h})}$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},prepareSelectBoxes:function(r){this.options=_.extend(this.options,r);var s=this.options.fetched_permissions;var k=this.options.is_admin;var q=this;var m=[];for(var h=0;h<s.access_dataset_roles.length;h++){m.push(s.access_dataset_roles[h]+":"+s.access_dataset_roles[h])}var f=[];for(var h=0;h<s.modify_item_roles.length;h++){f.push(s.modify_item_roles[h]+":"+s.modify_item_roles[h])}var g=[];for(var h=0;h<s.manage_dataset_roles.length;h++){g.push(s.manage_dataset_roles[h]+":"+s.manage_dataset_roles[h])}if(k){var o={minimumInputLength:0,css:"access_perm",multiple:true,placeholder:"Click to select a role",container:q.$el.find("#access_perm"),ajax:{url:(window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+q.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(i,t){return{q:i,page_limit:10,page:t}},results:function(u,t){var i=(t*10)<u.total;return{results:u.roles,more:i}}},formatResult:function j(i){return i.name+" type: "+i.type},formatSelection:function e(i){return i.name},initSelection:function(i,u){var t=[];$(i.val().split(",")).each(function(){var v=this.split(":");t.push({id:v[1],name:v[1]})});u(t)},initialData:m.join(","),dropdownCssClass:"bigdrop"};var l={minimumInputLength:0,css:"modify_perm",multiple:true,placeholder:"Click to select a role",container:q.$el.find("#modify_perm"),ajax:{url:(window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+q.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(i,t){return{q:i,page_limit:10,page:t}},results:function(u,t){var i=(t*10)<u.total;return{results:u.roles,more:i}}},formatResult:function j(i){return i.name+" type: "+i.type},formatSelection:function e(i){return i.name},initSelection:function(i,u){var t=[];$(i.val().split(",")).each(function(){var v=this.split(":");t.push({id:v[1],name:v[1]})});u(t)},initialData:f.join(","),dropdownCssClass:"bigdrop"};var p={minimumInputLength:0,css:"manage_perm",multiple:true,placeholder:"Click to select a role",container:q.$el.find("#manage_perm"),ajax:{url:(window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+q.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(i,t){return{q:i,page_limit:10,page:t}},results:function(u,t){var i=(t*10)<u.total;return{results:u.roles,more:i}}},formatResult:function j(i){return i.name+" type: "+i.type},formatSelection:function e(i){return i.name},initSelection:function(i,u){var t=[];$(i.val().split(",")).each(function(){var v=this.split(":");t.push({id:v[1],name:v[1]})});u(t)},initialData:g.join(","),dropdownCssClass:"bigdrop"};q.accessSelectObject=new b.View(o);q.modifySelectObject=new b.View(l);q.manageSelectObject=new b.View(p)}else{var n=q.templateAccessSelect();$.get((window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+q.id+"/permissions?scope=available",function(i){$(".access_perm").html(n({options:i.roles}));q.accessSelectObject=$("#access_select").select2()}).fail(function(){d.error("An error occurred while attempting to fetch dataset permissions.")})}},comingSoon:function(){d.warning("Feature coming soon.")},copyToClipboard:function(){var e=Backbone.history.location.href;if(e.lastIndexOf("/permissions")!==-1){e=e.substr(0,e.lastIndexOf("/permissions"))}window.prompt("Copy to clipboard: Ctrl+C, Enter",e)},makeDatasetPrivate:function(){var e=this;$.post((window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+e.id+"/permissions?action=make_private").done(function(f){e.model.set({is_unrestricted:false});e.showPermissions({fetched_permissions:f});d.success("The dataset is now private to you.")}).fail(function(){d.error("An error occurred while attempting to make dataset private.")})},removeDatasetRestrictions:function(){var e=this;$.post((window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+e.id+"/permissions?action=remove_restrictions").done(function(f){e.model.set({is_unrestricted:true});e.showPermissions({fetched_permissions:f});d.success("Access to this dataset is now unrestricted.")}).fail(function(){d.error("An error occurred while attempting to make dataset unrestricted.")})},savePermissions:function(e){var n=this;var k=this.accessSelectObject.$el.select2("data");var f=this.manageSelectObject.$el.select2("data");var m=this.modifySelectObject.$el.select2("data");var g=[];var j=[];var l=[];for(var h=k.length-1;h>=0;h--){g.push(k[h].id)}for(var h=f.length-1;h>=0;h--){j.push(f[h].id)}for(var h=m.length-1;h>=0;h--){l.push(m[h].id)}$.post((window.galaxy_config?galaxy_config.root:"/")+"api/libraries/datasets/"+n.id+"/permissions?action=set_permissions",{"access_ids[]":g,"manage_ids[]":j,"modify_ids[]":l,}).done(function(i){n.showPermissions({fetched_permissions:i});d.success("Permissions saved.")}).fail(function(){d.error("An error occurred while attempting to set dataset permissions.")})},templateDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <button data-toggle="tooltip" data-placement="top" title="Download dataset" class="btn btn-default toolbtn-download-dataset primary-button" type="button"><span class="fa fa-download"></span> Download</span></button>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Import dataset into history" class="btn btn-default toolbtn-import-dataset primary-button" type="button"><span class="fa fa-book"></span> to History</span></button>');e.push('   <% if (item.get("can_user_modify")) { %>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Modify library item" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');e.push("   <% } %>");e.push('   <% if (item.get("can_user_manage")) { %>');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" title="Manage permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button></a>');e.push("   <% } %>");e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('<% if (item.get("is_unrestricted")) { %>');e.push('  <div class="alert alert-info">');e.push("  This dataset is unrestricted so everybody can access it. Just share the URL of this page. ");e.push('  <button data-toggle="tooltip" data-placement="top" title="Copy to clipboard" class="btn btn-default btn-copy-link-to-clipboard primary-button" type="button"><span class="fa fa-clipboard"></span> To Clipboard</span></button> ');e.push("  </div>");e.push("<% } %>");e.push('<div class="dataset_table">');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push('           <td><%= _.escape(item.get("name")) %></td>');e.push("       </tr>");e.push('   <% if (item.get("file_ext")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(item.get("file_ext")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("genome_build")) { %>');e.push("       <tr>");e.push('           <th scope="row">Genome build</th>');e.push('           <td><%= _.escape(item.get("genome_build")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("file_size")) { %>');e.push("       <tr>");e.push('           <th scope="row">Size</th>');e.push('           <td><%= _.escape(item.get("file_size")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("date_uploaded")) { %>');e.push("       <tr>");e.push('           <th scope="row">Date uploaded (UTC)</th>');e.push('           <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("uploaded_by")) { %>');e.push("       <tr>");e.push('           <th scope="row">Uploaded by</th>');e.push('           <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_data_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data Lines</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_comment_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Comment Lines</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_columns")) { %>');e.push("       <tr>");e.push('           <th scope="row">Number of Columns</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("metadata_column_types")) { %>');e.push("       <tr>");e.push('           <th scope="row">Column Types</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("message")) { %>');e.push("       <tr>");e.push('           <th scope="row">Message</th>');e.push('           <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("misc_blurb")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous blurb</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (item.get("misc_info")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous information</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push("    </table>");e.push("    <div>");e.push('        <pre class="peek">');e.push("        </pre>");e.push("    </div>");e.push('   <% if (item.get("has_versions")) { %>');e.push("      <div>");e.push("      <h3>Expired versions:</h3>");e.push("      <ul>");e.push('      <% _.each(item.get("expired_versions"), function(version) { %>');e.push('        <li><a title="See details of this version" href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/versions/<%- version[0] %>"><%- version[1] %></a></li>');e.push("      <% }) %>");e.push("      <ul>");e.push("      </div>");e.push("   <% } %>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateVersion:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>"><button data-toggle="tooltip" data-placement="top" title="Go to latest dataset" class="btn btn-default primary-button" type="button"><span class="fa fa-caret-left fa-lg"></span> Latest dataset</span></button><a>');e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('  <div class="alert alert-warning">This is an expired version of the library dataset: <%= _.escape(item.get("name")) %></div>');e.push('<div class="dataset_table">');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(ldda.id) %>">Name</th>');e.push('           <td><%= _.escape(ldda.get("name")) %></td>');e.push("       </tr>");e.push('   <% if (ldda.get("file_ext")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(ldda.get("file_ext")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("genome_build")) { %>');e.push("       <tr>");e.push('           <th scope="row">Genome build</th>');e.push('           <td><%= _.escape(ldda.get("genome_build")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("file_size")) { %>');e.push("       <tr>");e.push('           <th scope="row">Size</th>');e.push('           <td><%= _.escape(ldda.get("file_size")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("date_uploaded")) { %>');e.push("       <tr>");e.push('           <th scope="row">Date uploaded (UTC)</th>');e.push('           <td><%= _.escape(ldda.get("date_uploaded")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("uploaded_by")) { %>');e.push("       <tr>");e.push('           <th scope="row">Uploaded by</th>');e.push('           <td><%= _.escape(ldda.get("uploaded_by")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_data_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data Lines</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_data_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_comment_lines")) { %>');e.push("       <tr>");e.push('           <th scope="row">Comment Lines</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_comment_lines")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_columns")) { %>');e.push("       <tr>");e.push('           <th scope="row">Number of Columns</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_columns")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("metadata_column_types")) { %>');e.push("       <tr>");e.push('           <th scope="row">Column Types</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("metadata_column_types")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("message")) { %>');e.push("       <tr>");e.push('           <th scope="row">Message</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("message")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("misc_blurb")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous blurb</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("misc_blurb")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push('   <% if (ldda.get("misc_info")) { %>');e.push("       <tr>");e.push('           <th scope="row">Miscellaneous information</th>');e.push('           <td scope="row"><%= _.escape(ldda.get("misc_info")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push("    </table>");e.push("    <div>");e.push('        <pre class="peek">');e.push("        </pre>");e.push("    </div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateModifyDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('<div class="dataset_table">');e.push('<p>For more editing options please import the dataset to history and use "Edit attributes" on it.</p>');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push('           <td><input class="input_dataset_name form-control" type="text" placeholder="name" value="<%= _.escape(item.get("name")) %>"></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(item.get("file_ext")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Genome build</th>');e.push('           <td><%= _.escape(item.get("genome_build")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Size</th>');e.push('           <td><%= _.escape(item.get("file_size")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Date uploaded (UTC)</th>');e.push('           <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Uploaded by</th>');e.push('           <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push("       </tr>");e.push('           <tr scope="row">');e.push('           <th scope="row">Data Lines</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push("       </tr>");e.push('       <th scope="row">Comment Lines</th>');e.push('           <% if (item.get("metadata_comment_lines") === "") { %>');e.push('               <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push("           <% } else { %>");e.push('               <td scope="row">unknown</td>');e.push("           <% } %>");e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Number of Columns</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Column Types</th>');e.push('           <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Message</th>');e.push('           <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Miscellaneous information</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push("       </tr>");e.push("       <tr>");e.push('           <th scope="row">Miscellaneous blurb</th>');e.push('           <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push("       </tr>");e.push("   </table>");e.push("<div>");e.push('   <pre class="peek">');e.push("   </pre>");e.push("</div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateDatasetPermissions:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <a href="#folders/<%- item.get("folder_id") %>"><button data-toggle="tooltip" data-placement="top" title="Go back to containing folder" class="btn btn-default primary-button" type="button"><span class="fa fa-folder-open-o"></span> Containing Folder</span></button></a>');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>"><button data-toggle="tooltip" data-placement="top" title="Go back to dataset" class="btn btn-default primary-button" type="button"><span class="fa fa-file-o"></span> Dataset Details</span></button><a>');e.push("  </div>");e.push('<ol class="breadcrumb">');e.push('   <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push('   <% _.each(item.get("full_path"), function(path_item) { %>');e.push("   <% if (path_item[0] != item.id) { %>");e.push('   <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push('   <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push("   <% } %>");e.push("   <% }); %>");e.push("</ol>");e.push('<h1>Dataset: <%= _.escape(item.get("name")) %></h1>');e.push('<div class="alert alert-warning">');e.push("<% if (is_admin) { %>");e.push("You are logged in as an <strong>administrator</strong> therefore you can manage any dataset on this Galaxy instance. Please make sure you understand the consequences.");e.push("<% } else { %>");e.push("You can assign any number of roles to any of the following permission types. However please read carefully the implications of such actions.");e.push("<% } %>");e.push("</div>");e.push('<div class="dataset_table">');e.push("<h2>Library-related permissions</h2>");e.push("<h4>Roles that can modify the library item</h4>");e.push('<div id="modify_perm" class="modify_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can modify name, metadata, and other information about this library item.</div>');e.push("<hr/>");e.push("<h2>Dataset-related permissions</h2>");e.push('<div class="alert alert-warning">Changes made below will affect <strong>every</strong> library item that was created from this dataset and also every history this dataset is part of.</div>');e.push('<% if (!item.get("is_unrestricted")) { %>');e.push(" <p>You can remove all access restrictions on this dataset. ");e.push(' <button data-toggle="tooltip" data-placement="top" title="Everybody will be able to access the dataset." class="btn btn-default btn-remove-restrictions primary-button" type="button">');e.push(' <span class="fa fa-globe"> Remove restrictions</span>');e.push(" </button>");e.push(" </p>");e.push("<% } else { %>");e.push("  This dataset is unrestricted so everybody can access it. Just share the URL of this page.");e.push('  <button data-toggle="tooltip" data-placement="top" title="Copy to clipboard" class="btn btn-default btn-copy-link-to-clipboard primary-button" type="button"><span class="fa fa-clipboard"> To Clipboard</span></button> ');e.push("  <p>You can make this dataset private to you. ");e.push(' <button data-toggle="tooltip" data-placement="top" title="Only you will be able to access the dataset." class="btn btn-default btn-make-private primary-button" type="button"><span class="fa fa-key"> Make Private</span></button>');e.push(" </p>");e.push("<% } %>");e.push("<h4>Roles that can access the dataset</h4>");e.push('<div id="access_perm" class="access_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User has to have <strong>all these roles</strong> in order to access this dataset. Users without access permission <strong>cannot</strong> have other permissions on this dataset. If there are no access roles set on the dataset it is considered <strong>unrestricted</strong>.</div>');e.push("<h4>Roles that can manage permissions on the dataset</h4>");e.push('<div id="manage_perm" class="manage_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can manage permissions of this dataset. If you remove yourself you will loose the ability manage this dataset unless you are an admin.</div>');e.push('<button data-toggle="tooltip" data-placement="top" title="Save modifications made on this page" class="btn btn-default toolbtn_save_permissions primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateBulkImportInModal:function(){var e=[];e.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');e.push("Select history: ");e.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');e.push("   <% _.each(histories, function(history) { %>");e.push('       <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');e.push("   <% }); %>");e.push("</select>");e.push("</span>");return _.template(e.join(""))},templateAccessSelect:function(){var e=[];e.push('<select id="access_select" multiple>');e.push("   <% _.each(options, function(option) { %>");e.push('       <option value="<%- option.name %>"><%- option.name %></option>');e.push("   <% }); %>");e.push("</select>");return _.template(e.join(""))}});return{LibraryDatasetView:a}});
\ No newline at end of file

diff -r 6395e70351435911f7ab75863c1b48b54e20a919 -r 0aa4dd8af7cf8303ef9dd9af95c2e2676854ecca static/scripts/packed/mvc/library/library-folder-view.js
--- a/static/scripts/packed/mvc/library/library-folder-view.js
+++ b/static/scripts/packed/mvc/library/library-folder-view.js
@@ -1,1 +1,1 @@
-define(["libs/toastr","mvc/library/library-model","mvc/ui/ui-select"],function(d,c,a){var b=Backbone.View.extend({el:"#center",model:null,options:{},events:{"click .toolbtn_save_permissions":"savePermissions"},initialize:function(e){this.options=_.extend(this.options,e);if(this.options.id){this.fetchFolder()}},fetchFolder:function(e){this.options=_.extend(this.options,e);this.model=new c.FolderAsModel({id:this.options.id});var f=this;this.model.fetch({success:function(){if(f.options.show_permissions){f.showPermissions()}else{f.render()}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{d.error("An error ocurred. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(e){$(".tooltip").remove();this.options=_.extend(this.options,e);var f=this.templateFolder();this.$el.html(f({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},shareFolder:function(){d.info("Feature coming soon.")},goBack:function(){Galaxy.libraries.library_router.back()},showPermissions:function(f){this.options=_.extend(this.options,f);$(".tooltip").remove();var h=false;if(Galaxy.currUser){h=Galaxy.currUser.isAdmin()}var g=this.templateFolderPermissions();this.$el.html(g({folder:this.model,is_admin:h}));var e=this;if(this.options.fetched_permissions===undefined){$.get("/api/folders/"+e.id+"/permissions?scope=current").done(function(i){e.prepareSelectBoxes({fetched_permissions:i})}).fail(function(){d.error("An error occurred while attempting to fetch folder permissions.")})}else{this.prepareSelectBoxes({})}$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},_serializeRoles:function(g){var e=[];for(var f=0;f<g.length;f++){e.push(g[f]+":"+g[f])}return e},prepareSelectBoxes:function(h){this.options=_.extend(this.options,h);var f=this.options.fetched_permissions;var g=this;var i=this._serializeRoles(f.add_library_item_role_list);var j=this._serializeRoles(f.manage_folder_role_list);var e=this._serializeRoles(f.modify_folder_role_list);g.addSelectObject=new a.View(this._createSelectOptions(this,"add_perm",i,false));g.manageSelectObject=new a.View(this._createSelectOptions(this,"manage_perm",j,false));g.modifySelectObject=new a.View(this._createSelectOptions(this,"modify_perm",e,false))},_createSelectOptions:function(e,j,h){var i={minimumInputLength:0,css:j,multiple:true,placeholder:"Click to select a role",container:e.$el.find("#"+j),ajax:{url:"/api/folders/"+e.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(k,l){return{q:k,page_limit:10,page:l}},results:function(m,l){var k=(l*10)<m.total;return{results:m.roles,more:k}}},formatResult:function f(k){return k.name+" type: "+k.type},formatSelection:function g(k){return k.name},initSelection:function(k,m){var l=[];$(k.val().split(",")).each(function(){var n=this.split(":");l.push({id:n[1],name:n[1]})});m(l)},initialData:h.join(","),dropdownCssClass:"bigdrop"};return i},comingSoon:function(){d.warning("Feature coming soon.")},copyToClipboard:function(){var e=Backbone.history.location.href;if(e.lastIndexOf("/permissions")!==-1){e=e.substr(0,e.lastIndexOf("/permissions"))}window.prompt("Copy to clipboard: Ctrl+C, Enter",e)},_extractIds:function(e){ids_list=[];for(var f=e.length-1;f>=0;f--){ids_list.push(e[f].id)}return ids_list},savePermissions:function(h){var g=this;var e=this._extractIds(this.addSelectObject.$el.select2("data"));var i=this._extractIds(this.manageSelectObject.$el.select2("data"));var f=this._extractIds(this.modifySelectObject.$el.select2("data"));$.post("/api/folders/"+g.id+"/permissions?action=set_permissions",{"add_ids[]":e,"manage_ids[]":i,"modify_ids[]":f,}).done(function(j){g.showPermissions({fetched_permissions:j});d.success("Permissions saved.")}).fail(function(){d.error("An error occurred while attempting to set folder permissions.")})},templateFolder:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <button data-toggle="tooltip" data-placement="top" title="Modify library item" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" title="Manage permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button></a>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Share dataset" class="btn btn-default toolbtn-share-dataset primary-button" type="button"><span class="fa fa-share"></span> Share</span></button>');e.push("  </div>");e.push("  <p>");e.push("  This dataset is unrestricted so everybody can access it. Just share the URL of this page. ");e.push('  <button data-toggle="tooltip" data-placement="top" title="Copy to clipboard" class="btn btn-default btn-copy-link-to-clipboard primary-button" type="button"><span class="fa fa-clipboard"></span> To Clipboard</span></button> ');e.push("  </p>");e.push('<div class="dataset_table">');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push('           <td><%= _.escape(item.get("name")) %></td>');e.push("       </tr>");e.push('   <% if (item.get("file_ext")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(item.get("file_ext")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push("    </table>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateFolderPermissions:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <a href="#/folders/<%= folder.get("parent_id") %>"><button data-toggle="tooltip" data-placement="top" title="Go back to the parent folder" class="btn btn-default primary-button" type="button"><span class="fa fa-caret-left fa-lg"></span> Parent folder</span></button></a>');e.push("  </div>");e.push('<h1>Folder: <%= _.escape(folder.get("name")) %></h1>');e.push('<div class="alert alert-warning">');e.push("<% if (is_admin) { %>");e.push("You are logged in as an <strong>administrator</strong> therefore you can manage any folder on this Galaxy instance. Please make sure you understand the consequences.");e.push("<% } else { %>");e.push("You can assign any number of roles to any of the following permission types. However please read carefully the implications of such actions.");e.push("<% }%>");e.push("</div>");e.push('<div class="dataset_table">');e.push("<h2>Folder permissions</h2>");e.push("<h4>Roles that can manage permissions on this folder</h4>");e.push('<div id="manage_perm" class="manage_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can manage permissions on this folder.</div>');e.push("<h4>Roles that can add items to this folder</h4>");e.push('<div id="add_perm" class="add_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can add items to this folder (folders and datasets).</div>');e.push("<h4>Roles that can modify this folder</h4>");e.push('<div id="modify_perm" class="modify_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can modify this folder (name, etc.).</div>');e.push('<button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_permissions primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push("</div>");e.push("</div>");return _.template(e.join(""))}});return{FolderView:b}});
\ No newline at end of file
+define(["libs/toastr","mvc/library/library-model","mvc/ui/ui-select"],function(d,c,a){var b=Backbone.View.extend({el:"#center",model:null,options:{},events:{"click .toolbtn_save_permissions":"savePermissions"},initialize:function(e){this.options=_.extend(this.options,e);if(this.options.id){this.fetchFolder()}},fetchFolder:function(e){this.options=_.extend(this.options,e);this.model=new c.FolderAsModel({id:this.options.id});var f=this;this.model.fetch({success:function(){if(f.options.show_permissions){f.showPermissions()}else{f.render()}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{d.error("An error ocurred. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(e){$(".tooltip").remove();this.options=_.extend(this.options,e);var f=this.templateFolder();this.$el.html(f({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},shareFolder:function(){d.info("Feature coming soon.")},goBack:function(){Galaxy.libraries.library_router.back()},showPermissions:function(f){this.options=_.extend(this.options,f);$(".tooltip").remove();var h=false;if(Galaxy.currUser){h=Galaxy.currUser.isAdmin()}var g=this.templateFolderPermissions();this.$el.html(g({folder:this.model,is_admin:h}));var e=this;if(this.options.fetched_permissions===undefined){$.get((window.galaxy_config?galaxy_config.root:"/")+"api/folders/"+e.id+"/permissions?scope=current").done(function(i){e.prepareSelectBoxes({fetched_permissions:i})}).fail(function(){d.error("An error occurred while attempting to fetch folder permissions.")})}else{this.prepareSelectBoxes({})}$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},_serializeRoles:function(g){var e=[];for(var f=0;f<g.length;f++){e.push(g[f]+":"+g[f])}return e},prepareSelectBoxes:function(h){this.options=_.extend(this.options,h);var f=this.options.fetched_permissions;var g=this;var i=this._serializeRoles(f.add_library_item_role_list);var j=this._serializeRoles(f.manage_folder_role_list);var e=this._serializeRoles(f.modify_folder_role_list);g.addSelectObject=new a.View(this._createSelectOptions(this,"add_perm",i,false));g.manageSelectObject=new a.View(this._createSelectOptions(this,"manage_perm",j,false));g.modifySelectObject=new a.View(this._createSelectOptions(this,"modify_perm",e,false))},_createSelectOptions:function(e,j,h){var i={minimumInputLength:0,css:j,multiple:true,placeholder:"Click to select a role",container:e.$el.find("#"+j),ajax:{url:(window.galaxy_config?galaxy_config.root:"/")+"api/folders/"+e.id+"/permissions?scope=available",dataType:"json",quietMillis:100,data:function(k,l){return{q:k,page_limit:10,page:l}},results:function(m,l){var k=(l*10)<m.total;return{results:m.roles,more:k}}},formatResult:function f(k){return k.name+" type: "+k.type},formatSelection:function g(k){return k.name},initSelection:function(k,m){var l=[];$(k.val().split(",")).each(function(){var n=this.split(":");l.push({id:n[1],name:n[1]})});m(l)},initialData:h.join(","),dropdownCssClass:"bigdrop"};return i},comingSoon:function(){d.warning("Feature coming soon.")},copyToClipboard:function(){var e=Backbone.history.location.href;if(e.lastIndexOf("/permissions")!==-1){e=e.substr(0,e.lastIndexOf("/permissions"))}window.prompt("Copy to clipboard: Ctrl+C, Enter",e)},_extractIds:function(e){ids_list=[];for(var f=e.length-1;f>=0;f--){ids_list.push(e[f].id)}return ids_list},savePermissions:function(h){var g=this;var e=this._extractIds(this.addSelectObject.$el.select2("data"));var i=this._extractIds(this.manageSelectObject.$el.select2("data"));var f=this._extractIds(this.modifySelectObject.$el.select2("data"));$.post((window.galaxy_config?galaxy_config.root:"/")+"api/folders/"+g.id+"/permissions?action=set_permissions",{"add_ids[]":e,"manage_ids[]":i,"modify_ids[]":f,}).done(function(j){g.showPermissions({fetched_permissions:j});d.success("Permissions saved.")}).fail(function(){d.error("An error occurred while attempting to set folder permissions.")})},templateFolder:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <button data-toggle="tooltip" data-placement="top" title="Modify library item" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');e.push('   <a href="#folders/<%- item.get("folder_id") %>/datasets/<%- item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" title="Manage permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button></a>');e.push('   <button data-toggle="tooltip" data-placement="top" title="Share dataset" class="btn btn-default toolbtn-share-dataset primary-button" type="button"><span class="fa fa-share"></span> Share</span></button>');e.push("  </div>");e.push("  <p>");e.push("  This dataset is unrestricted so everybody can access it. Just share the URL of this page. ");e.push('  <button data-toggle="tooltip" data-placement="top" title="Copy to clipboard" class="btn btn-default btn-copy-link-to-clipboard primary-button" type="button"><span class="fa fa-clipboard"></span> To Clipboard</span></button> ');e.push("  </p>");e.push('<div class="dataset_table">');e.push('   <table class="grid table table-striped table-condensed">');e.push("       <tr>");e.push('           <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push('           <td><%= _.escape(item.get("name")) %></td>');e.push("       </tr>");e.push('   <% if (item.get("file_ext")) { %>');e.push("       <tr>");e.push('           <th scope="row">Data type</th>');e.push('           <td><%= _.escape(item.get("file_ext")) %></td>');e.push("       </tr>");e.push("   <% } %>");e.push("    </table>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateFolderPermissions:function(){var e=[];e.push('<div class="library_style_container">');e.push('  <div id="library_toolbar">');e.push('   <a href="#/folders/<%= folder.get("parent_id") %>"><button data-toggle="tooltip" data-placement="top" title="Go back to the parent folder" class="btn btn-default primary-button" type="button"><span class="fa fa-caret-left fa-lg"></span> Parent folder</span></button></a>');e.push("  </div>");e.push('<h1>Folder: <%= _.escape(folder.get("name")) %></h1>');e.push('<div class="alert alert-warning">');e.push("<% if (is_admin) { %>");e.push("You are logged in as an <strong>administrator</strong> therefore you can manage any folder on this Galaxy instance. Please make sure you understand the consequences.");e.push("<% } else { %>");e.push("You can assign any number of roles to any of the following permission types. However please read carefully the implications of such actions.");e.push("<% }%>");e.push("</div>");e.push('<div class="dataset_table">');e.push("<h2>Folder permissions</h2>");e.push("<h4>Roles that can manage permissions on this folder</h4>");e.push('<div id="manage_perm" class="manage_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can manage permissions on this folder.</div>');e.push("<h4>Roles that can add items to this folder</h4>");e.push('<div id="add_perm" class="add_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can add items to this folder (folders and datasets).</div>');e.push("<h4>Roles that can modify this folder</h4>");e.push('<div id="modify_perm" class="modify_perm roles-selection"></div>');e.push('<div class="alert alert-info roles-selection">User with <strong>any</strong> of these roles can modify this folder (name, etc.).</div>');e.push('<button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_permissions primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push("</div>");e.push("</div>");return _.template(e.join(""))}});return{FolderView:b}});
\ No newline at end of file

This diff is so big that we needed to truncate the remainder.

Repository URL: https://bitbucket.org/galaxy/galaxy-central/

--

This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.



More information about the galaxy-commits mailing list