1 new commit in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/c1b54085c3ae/ Changeset: c1b54085c3ae Branch: next-stable User: natefoo Date: 2014-11-18 15:19:00+00:00 Summary: Open next-stable for release_2014.12.01 Affected #: 388 files diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 .hgignore --- a/.hgignore +++ b/.hgignore @@ -67,6 +67,7 @@ shed_data_manager_conf.xml object_store_conf.xml job_metrics_conf.xml +workflow_schedulers_conf.xml config/* static/welcome.html.* static/welcome.html diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 .hgtags --- a/.hgtags +++ b/.hgtags @@ -19,3 +19,5 @@ 2a756ca2cb1826db7796018e77d12e2dd7b67603 latest_2014.02.10 ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11 548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11 +2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06 +011c8b2118be778eaf1ba952730ff876d6447ba9 latest_2014.10.06 diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 buildbot_setup.sh --- a/buildbot_setup.sh +++ b/buildbot_setup.sh @@ -126,5 +126,3 @@ echo "Appending tool-data/shared/ucsc/builds.txt.buildbot to tool-data/shared/ucsc/builds.txt" cat tool-data/shared/ucsc/builds.txt.buildbot >> tool-data/shared/ucsc/builds.txt - -python ./scripts/fetch_eggs.py all diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/galaxy.frame.js --- a/client/galaxy/scripts/galaxy.frame.js +++ b/client/galaxy/scripts/galaxy.frame.js @@ -1,9 +1,8 @@ // dependencies define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) { -// frame manager -var GalaxyFrame = Backbone.View.extend( -{ +/** Frame manager uses the ui-frames to create the scratch book masthead icon and functionality **/ +var GalaxyFrame = Backbone.View.extend({ // base element el_main: 'body', @@ -17,8 +16,7 @@ button_load : null, // initialize - initialize : function(options) - { + initialize : function(options) { // add to masthead menu var self = this; @@ -28,8 +26,7 @@ }); // add activate icon - this.button_active = new mod_masthead.GalaxyMastheadIcon ( - { + this.button_active = new mod_masthead.GalaxyMastheadIcon({ icon : 'fa-th', tooltip : 'Enable/Disable Scratchbook', onclick : function() { self._activate(); }, @@ -44,8 +41,7 @@ Galaxy.masthead.append(this.button_active); // add load icon - this.button_load = new mod_masthead.GalaxyMastheadIcon ( - { + this.button_load = new mod_masthead.GalaxyMastheadIcon({ icon : 'fa-eye', tooltip : 'Show/Hide Scratchbook', onclick : function(e) { @@ -122,35 +118,77 @@ }); }, + + /** + * Add a trackster visualization to the frames. + */ + add_trackster_viz: function(viz_id) { + var self = this; + require(['viz/visualization', 'viz/trackster'], function(visualization, trackster) { + var viz = new visualization.Visualization({id: viz_id}); + $.when( viz.fetch() ).then( function() { + var ui = new trackster.TracksterUI(galaxy_config.root); + + // Construct frame config based on dataset's type. + var frame_config = { + title: viz.get('name'), + type: 'other', + content: function(parent_elt) { + // Create view config. + var view_config = { + container: parent_elt, + name: viz.get('title'), + id: viz.id, + // FIXME: this will not work with custom builds b/c the dbkey needed to be encoded. + dbkey: viz.get('dbkey'), + stand_alone: false + }, + latest_revision = viz.get('latest_revision'), + drawables = latest_revision.config.view.drawables; + + // Set up datasets in drawables. + _.each(drawables, function(d) { + d.dataset = { + hda_ldda: d.hda_ldda, + id: d.dataset_id + }; + }); + + view = ui.create_visualization(view_config, + latest_revision.config.viewport, + latest_revision.config.view.drawables, + latest_revision.config.bookmarks, + false); + } + }; + + self.add(frame_config); + }); + }); + }, /** * Add and display a new frame/window based on options. */ - add: function(options) - { + add: function(options){ // open new tab - if (options.target == '_blank') - { + if (options.target == '_blank'){ window.open(options.content); return; } // reload entire window - if (options.target == '_top' || options.target == '_parent' || options.target == '_self') - { + if (options.target == '_top' || options.target == '_parent' || options.target == '_self'){ window.location = options.content; return; } // validate - if (!this.active) - { + if (!this.active){ // fix url if main frame is unavailable var $galaxy_main = $(window.parent.document).find('#galaxy_main'); - if (options.target == 'galaxy_main' || options.target == 'center') - { - if ($galaxy_main.length === 0) - { + if (options.target == 'galaxy_main' || options.target == 'center'){ + if ($galaxy_main.length === 0){ var href = options.content; if (href.indexOf('?') == -1) href += '?'; @@ -173,11 +211,9 @@ }, // activate/disable panel - _activate: function () - { + _activate: function (){ // check - if (this.active) - { + if (this.active){ // disable this.active = false; @@ -196,8 +232,7 @@ }, // update frame counter - _refresh: function() - { + _refresh: function(){ // update on screen counter this.button_load.number(this.frames.length()); diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/galaxy.interactive_environments.js --- /dev/null +++ b/client/galaxy/scripts/galaxy.interactive_environments.js @@ -0,0 +1,59 @@ +/** + * Internal function to remove content from the main area and add the notebook. + * Not idempotent + */ +function append_notebook(url){ + clear_main_area(); + $('#main').append('<iframe frameBorder="0" seamless="seamless" style="width: 100%; height: 100%; overflow:hidden;" scrolling="no" src="'+ url +'"></iframe>' + ); +} + +function clear_main_area(){ + $('#spinner').remove(); + $('#main').children().remove(); +} + +function display_spinner(){ + $('#main').append('<img id="spinner" src="' + galaxy_root + '/static/style/largespinner.gif" style="position:absolute;margin:auto;top:0;left:0;right:0;bottom:0;">'); +} + + +/** + * Test availability of a URL, and call a callback when done. + * http://stackoverflow.com/q/25390206/347368 + * @param {String} url: URL to test availability of. Must return a 200 (302->200 is OK). + * @param {String} callback: function to call once successfully connected. + * + */ +function test_ie_availability(url, success_callback){ + var request_count = 0; + display_spinner(); + interval = setInterval(function(){ + $.ajax({ + url: url, + xhrFields: { + withCredentials: true + }, + type: "GET", + timeout: 500, + success: function(){ + console.log("Connected to IE, returning"); + clearInterval(interval); + success_callback(); + }, + error: function(jqxhr, status, error){ + request_count++; + console.log("Request " + request_count); + if(request_count > 30){ + clearInterval(interval); + clear_main_area(); + toastr.error( + "Could not connect to IE, contact your administrator", + "Error", + {'closeButton': true, 'timeOut': 20000, 'tapToDismiss': false} + ); + } + } + }); + }, 1000); +} diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/galaxy.library.js --- a/client/galaxy/scripts/galaxy.library.js +++ b/client/galaxy/scripts/galaxy.library.js @@ -16,19 +16,19 @@ "mvc/library/library-library-view", "mvc/library/library-folder-view" ], -function(mod_masthead, - mod_utils, - mod_toastr, - mod_baseMVC, - mod_library_model, - mod_folderlist_view, - mod_librarylist_view, - mod_librarytoolbar_view, - mod_foldertoolbar_view, - mod_library_dataset_view, - mod_library_library_view, - mod_library_folder_view - ) { + function(mod_masthead, + mod_utils, + mod_toastr, + mod_baseMVC, + mod_library_model, + mod_folderlist_view, + mod_librarylist_view, + mod_librarytoolbar_view, + mod_foldertoolbar_view, + mod_library_dataset_view, + mod_library_library_view, + mod_library_folder_view + ) { // ============================================================================ // ROUTER @@ -37,10 +37,11 @@ this.routesHit = 0; //keep count of number of routes handled by the application Backbone.history.on('route', function() { this.routesHit++; }, this); - }, +}, - routes: { +routes: { "" : "libraries", + "page/:show_page" : "libraries_page", "library/:library_id/permissions" : "library_permissions", "folders/:folder_id/permissions" : "folder_permissions", "folders/:id" : "folder_content", @@ -49,27 +50,28 @@ "folders/:folder_id/datasets/:dataset_id/versions/:ldda_id" : "dataset_version", "folders/:folder_id/download/:format" : "download", "folders/:folder_id/import/:source" : "import_datasets" - }, +}, - back: function() { +back: function() { if(this.routesHit > 1) { //more than one route hit -> user did not land to current page directly window.history.back(); - } else { + } else { //otherwise go to the home page. Use replaceState if available so //the navigation doesn't create an extra history entry this.navigate('#', {trigger:true, replace:true}); - } } +} }); // ============================================================================ /** session storage for library preferences */ var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({ defaults : { - with_deleted : false, - sort_order : 'asc', - sort_by : 'name' + with_deleted : false, + sort_order : 'asc', + sort_by : 'name', + library_page_size : 20 } }); @@ -88,77 +90,86 @@ initialize : function(){ Galaxy.libraries = this; - this.preferences = new LibraryPrefs( {id: 'global-lib-prefs'} ); + this.preferences = new LibraryPrefs( { id: 'global-lib-prefs' } ); this.library_router = new LibraryRouter(); this.library_router.on('route:libraries', function() { Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView(); Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView(); + }); + + this.library_router.on('route:libraries_page', function( show_page ) { + if ( Galaxy.libraries.libraryToolbarView === null ){ + Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView(); + Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView( { show_page: show_page } ); + } else { + Galaxy.libraries.libraryListView.render( { show_page: show_page } ) + } }); this.library_router.on('route:folder_content', function(id) { if (Galaxy.libraries.folderToolbarView){ Galaxy.libraries.folderToolbarView.$el.unbind('click'); - } - Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id}); - Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id}); - }); + } + Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id}); + Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id}); + }); - this.library_router.on('route:download', function(folder_id, format) { + this.library_router.on('route:download', function(folder_id, format) { if ($('#folder_list_body').find(':checked').length === 0) { mod_toastr.info( 'You must select at least one dataset to download' ); Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true}); - } else { + } else { Galaxy.libraries.folderToolbarView.download(folder_id, format); Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true}); - } - }); + } + }); - this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){ + this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){ if (Galaxy.libraries.datasetView){ Galaxy.libraries.datasetView.$el.unbind('click'); - } - Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id}); - }); - this.library_router.on('route:dataset_version', function(folder_id, dataset_id, ldda_id){ + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id}); + }); + this.library_router.on('route:dataset_version', function(folder_id, dataset_id, ldda_id){ if (Galaxy.libraries.datasetView){ Galaxy.libraries.datasetView.$el.unbind('click'); - } - Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true}); - }); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true}); + }); - this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){ + this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){ if (Galaxy.libraries.datasetView){ Galaxy.libraries.datasetView.$el.unbind('click'); - } - Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true}); - }); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true}); + }); - this.library_router.on('route:library_permissions', function(library_id){ + this.library_router.on('route:library_permissions', function(library_id){ if (Galaxy.libraries.libraryView){ Galaxy.libraries.libraryView.$el.unbind('click'); - } - Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true}); - }); + } + Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true}); + }); - this.library_router.on('route:folder_permissions', function(folder_id){ + this.library_router.on('route:folder_permissions', function(folder_id){ if (Galaxy.libraries.folderView){ Galaxy.libraries.folderView.$el.unbind('click'); - } - Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true}); - }); - this.library_router.on('route:import_datasets', function(folder_id, source){ + } + Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true}); + }); + this.library_router.on('route:import_datasets', function(folder_id, source){ if (Galaxy.libraries.folderToolbarView && Galaxy.libraries.folderListView){ Galaxy.libraries.folderToolbarView.showImportModal({source:source}); - } else { + } else { Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: folder_id}); Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id}); Galaxy.libraries.folderToolbarView.showImportModal({source: source}); - } - }); + } + }); - Backbone.history.start({pushState: false}); + Backbone.history.start({pushState: false}); } }); diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/galaxy.masthead.js --- a/client/galaxy/scripts/galaxy.masthead.js +++ b/client/galaxy/scripts/galaxy.masthead.js @@ -1,9 +1,8 @@ // dependencies define([], function() { -// masthead -var GalaxyMasthead = Backbone.View.extend( -{ +/** Masthead **/ +var GalaxyMasthead = Backbone.View.extend({ // base element el_masthead: '#everything', @@ -17,8 +16,7 @@ list: [], // initialize - initialize : function(options) - { + initialize : function(options) { // update options this.options = options; @@ -51,27 +49,23 @@ }, // configure events - events: - { + events: { 'click' : '_click', 'mousedown' : function(e) { e.preventDefault() } }, // adds a new item to the masthead - append : function(item) - { + append : function(item) { return this._add(item, true); }, // adds a new item to the masthead - prepend : function(item) - { + prepend : function(item) { return this._add(item, false); }, // activate - highlight: function(id) - { + highlight: function(id) { var current = $(this.el).find('#' + id + '> li'); if (current) { current.addClass('active'); @@ -79,11 +73,9 @@ }, // adds a new item to the masthead - _add : function(item, append) - { + _add : function(item, append) { var $loc = $(this.el).find('#' + item.location); - if ($loc) - { + if ($loc){ // create frame for new item var $current = $(item.el); @@ -106,8 +98,7 @@ }, // handle click event - _click: function(e) - { + _click: function(e) { // close all popups var $all = $(this.el).find('.popup'); if ($all) { @@ -129,8 +120,7 @@ */ // fill template - _template: function(options) - { + _template: function(options) { var brand_text = options.brand ? ("/ " + options.brand) : "" ; return '<div><div id="masthead" class="navbar navbar-fixed-top navbar-inverse">' + '<div style="position: relative; right: -50%; float: left;">' + @@ -150,12 +140,10 @@ } }); -// icon -var GalaxyMastheadIcon = Backbone.View.extend( -{ +/** Masthead icon **/ +var GalaxyMastheadIcon = Backbone.View.extend({ // icon options - options: - { + options:{ id : '', icon : 'fa-cog', tooltip : '', @@ -169,8 +157,7 @@ location: 'iconbar', // initialize - initialize: function (options) - { + initialize: function (options){ // read in defaults if (options) this.options = _.defaults(options, this.options); @@ -189,20 +176,17 @@ }, // show - show: function() - { + show: function(){ $(this.el).css({visibility : 'visible'}); }, // show - hide: function() - { + hide: function(){ $(this.el).css({visibility : 'hidden'}); }, // switch icon - icon: function (new_icon) - { + icon: function (new_icon){ // update icon class $(this.el).find('.icon').removeClass(this.options.icon) .addClass(new_icon); @@ -212,26 +196,22 @@ }, // toggle - toggle: function() - { + toggle: function(){ $(this.el).addClass('toggle'); }, // untoggle - untoggle: function() - { + untoggle: function(){ $(this.el).removeClass('toggle'); }, // set/get number - number: function(new_number) - { + number: function(new_number){ $(this.el).find('.number').text(new_number); }, // fill template icon - _template: function (options) - { + _template: function (options){ var tmpl = '<div id="' + options.id + '" class="symbol">' + '<div class="icon fa fa-2x ' + options.icon + '"></div>'; if (options.with_number) @@ -243,12 +223,10 @@ } }); -// tab -var GalaxyMastheadTab = Backbone.View.extend( -{ +/** Masthead tab **/ +var GalaxyMastheadTab = Backbone.View.extend({ // main options - options: - { + options:{ id : '', title : '', target : '_parent', @@ -268,14 +246,12 @@ $menu: null, // events - events: - { + events:{ 'click .head' : '_head' }, // initialize - initialize: function (options) - { + initialize: function (options){ // read in defaults if (options) this.options = _.defaults(options, this.options); @@ -300,20 +276,17 @@ }, // show - show: function() - { + show: function(){ $(this.el).css({visibility : 'visible'}); }, // show - hide: function() - { + hide: function(){ $(this.el).css({visibility : 'hidden'}); }, // add menu item - add: function (options) - { + add: function (options){ // menu option defaults var menuOptions = { title : 'Title', @@ -333,8 +306,7 @@ menuOptions.content = galaxy_config.root + menuOptions.content; // check if submenu element is available - if (!this.$menu) - { + if (!this.$menu){ // insert submenu element into root $(this.el).find('.root').append(this._templateMenu()); @@ -353,8 +325,7 @@ // add events var self = this; - $item.on('click', function(e) - { + $item.on('click', function(e){ // prevent default e.preventDefault(); @@ -372,8 +343,7 @@ }, // show menu on header click - _head: function(e) - { + _head: function(e){ // prevent default e.preventDefault(); @@ -387,12 +357,11 @@ } }, - _attachPopover : function() - { + _attachPopover : function(){ var $popover_element = $(this.el).find('.head'); $popover_element.popover({ html: true, - content: 'Please <a href="/user/login">log in</a> or <a href="/user/create">register</a> to use this feature.', + content: 'Please <a href="' + galaxy_config.root + '/user/login">log in</a> or <a href="' + galaxy_config.root + '/user/create">register</a> to use this feature.', placement: 'bottom' }).on('shown.bs.popover', function() { // hooking on bootstrap event to automatically hide popovers after delay setTimeout(function() { @@ -402,25 +371,21 @@ }, // fill template header - _templateMenuItem: function (options) - { + _templateMenuItem: function (options){ return '<li><a href="' + options.content + '" target="' + options.target + '">' + options.title + '</a></li>'; }, // fill template header - _templateMenu: function () - { + _templateMenu: function (){ return '<ul class="popup dropdown-menu"></ul>'; }, - _templateDivider: function() - { + _templateDivider: function(){ return '<li class="divider"></li>'; }, // fill template - _template: function (options) - { + _template: function (options){ // start template var tmpl = '<ul id="' + options.id + '" class="nav navbar-nav" border="0" cellspacing="0">' + '<li class="root dropdown" style="">' + diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/galaxy.menu.js --- a/client/galaxy/scripts/galaxy.menu.js +++ b/client/galaxy/scripts/galaxy.menu.js @@ -1,13 +1,8 @@ -/* - galaxy menu -*/ - // dependencies define(["galaxy.masthead"], function(mod_masthead) { -// frame manager -var GalaxyMenu = Backbone.Model.extend( -{ +/** GalaxyMenu uses the GalaxyMasthead class in order to add menu items and icons to the Masthead **/ +var GalaxyMenu = Backbone.Model.extend({ // options options: null, @@ -15,16 +10,14 @@ masthead: null, // initialize - initialize: function(options) - { + initialize: function(options) { this.options = options.config; this.masthead = options.masthead; this.create(); }, // default menu - create: function() - { + create: function(){ // // Analyze data tab. // @@ -137,8 +130,7 @@ var tab_visualization = new mod_masthead.GalaxyMastheadTab(visualization_options); - if (this.options.user.valid) //add submenu only when user is logged in - { + if (this.options.user.valid){ //add submenu only when user is logged in tab_visualization.add({ title : "New Track Browser", content : "visualization/trackster", @@ -155,8 +147,7 @@ // // Cloud menu. // - if (this.options.enable_cloud_launch) - { + if (this.options.enable_cloud_launch){ var tab_cloud = new mod_masthead.GalaxyMastheadTab({ id : "cloud", title : "Cloud", @@ -172,8 +163,7 @@ // // Admin. // - if (this.options.is_admin_user) - { + if (this.options.is_admin_user) { var tab_admin = new mod_masthead.GalaxyMastheadTab({ id : "admin", title : "Admin", @@ -192,8 +182,7 @@ title : "Help", title_attribute : 'Support, contact, and community hubs' }); - if (this.options.biostar_url) - { + if (this.options.biostar_url){ tab_help.add({ title : "Galaxy Biostar", content : this.options.biostar_url_redirect, @@ -235,8 +224,7 @@ content : this.options.citation_url, target : "_blank" }); - if (this.options.terms_url) - { + if (this.options.terms_url){ tab_help.add({ title : "Terms and Conditions", content : this.options.terms_url, @@ -248,8 +236,7 @@ // // User tab. // - if (!this.options.user.valid) - { + if (!this.options.user.valid){ var tab_user = new mod_masthead.GalaxyMastheadTab({ id : "user", title : "User", @@ -265,8 +252,7 @@ }); // register - if (this.options.allow_user_creation) - { + if (this.options.allow_user_creation){ tab_user.add({ title : "Register", content : "user/create", @@ -331,8 +317,7 @@ target : "galaxy_main" }); - if (this.options.use_remote_user) - { + if (this.options.use_remote_user){ tab_user.add({ title : "Public Name", content : "user/edit_username?cntrller=user", diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/base-mvc.js --- a/client/galaxy/scripts/mvc/base-mvc.js +++ b/client/galaxy/scripts/mvc/base-mvc.js @@ -380,11 +380,6 @@ /** allow the view to be dragged, set up event handlers */ draggableOn : function(){ this.draggable = true; - //TODO: I have no idea why this doesn't work with the events hash or jq.on()... - //this.$el.find( '.title-bar' ) - // .attr( 'draggable', true ) - // .bind( 'dragstart', this.dragStartHandler, false ) - // .bind( 'dragend', this.dragEndHandler, false ); this.dragStartHandler = _.bind( this._dragStartHandler, this ); this.dragEndHandler = _.bind( this._dragEndHandler, this ); @@ -402,23 +397,22 @@ }, /** sets the dataTransfer data to the model's toJSON - * @fires dragstart (bbone event) which is passed this view + * @fires draggable:dragstart (bbone event) which is passed the event and this view */ _dragStartHandler : function( event ){ - //this.debug( 'dragStartHandler:', this, event, arguments ) - this.trigger( 'dragstart', this ); event.dataTransfer.effectAllowed = 'move'; + //ASSUMES: this.model //TODO: all except IE: should be 'application/json', IE: must be 'text' event.dataTransfer.setData( 'text', JSON.stringify( this.model.toJSON() ) ); + this.trigger( 'draggable:dragstart', event, this ); return false; }, /** handle the dragend - * @fires dragend (bbone event) which is passed this view + * @fires draggable:dragend (bbone event) which is passed the event and this view */ _dragEndHandler : function( event ){ - this.trigger( 'dragend', this ); - //this.debug( 'dragEndHandler:', event ) + this.trigger( 'draggable:dragend', event, this ); return false; } }; diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/citation/citation-view.js --- a/client/galaxy/scripts/mvc/citation/citation-view.js +++ b/client/galaxy/scripts/mvc/citation/citation-view.js @@ -58,11 +58,11 @@ var doiUrl = ""; if( fields.doi ) { doiUrl = 'http://dx.doi.org/' + fields.doi; - ref += '[<a href="' + doiUrl + '">doi:' + fields.doi + "</a>]"; + ref += '[<a href="' + doiUrl + '" target="_blank">doi:' + fields.doi + "</a>]"; } var url = fields.url || doiUrl; if( url ) { - ref += '[<a href="' + url + '">Link</a>]'; + ref += '[<a href="' + url + '" target="_blank">Link</a>]'; } return ref; }, @@ -185,4 +185,4 @@ CitationListView : CitationListView }; -}); \ No newline at end of file +}); diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/collection/collection-li.js --- a/client/galaxy/scripts/mvc/collection/collection-li.js +++ b/client/galaxy/scripts/mvc/collection/collection-li.js @@ -100,8 +100,6 @@ /** add the DCE class to the list item */ className : ListItemView.prototype.className + " dataset-collection-element", - /** jq fx speed for this view */ - fxSpeed : 'fast', /** set up */ initialize : function( attributes ){ diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/collection/paired-collection-creator.js --- a/client/galaxy/scripts/mvc/collection/paired-collection-creator.js +++ b/client/galaxy/scripts/mvc/collection/paired-collection-creator.js @@ -1298,7 +1298,7 @@ _clickPairName : function( ev ){ ev.stopPropagation(); var $control = $( ev.currentTarget ), - pair = this.paired[ $control.parent().index() ], + pair = this.paired[ $control.parent().parent().index() / 2 ], response = prompt( 'Enter a new name for the pair:', pair.name ); if( response ){ pair.name = response; diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/dataset/dataset-li-edit.js --- a/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js +++ b/client/galaxy/scripts/mvc/dataset/dataset-li-edit.js @@ -181,6 +181,8 @@ } var $visualizations = $( this.templates.visualizations( visualizations, this ) ); + //HACK: need to re-write those directed at galaxy_main with linkTarget + $visualizations.find( '[target="galaxy_main"]').attr( 'target', this.linkTarget ); // use addBack here to include the root $visualizations elem (for the case of 1 visualization) this._addScratchBookFn( $visualizations.find( '.visualization-link' ).addBack( '.visualization-link' ) ); return $visualizations; @@ -188,6 +190,7 @@ /** add scratchbook functionality to visualization links */ _addScratchBookFn : function( $links ){ + var li = this; $links.click( function( ev ){ if( Galaxy.frame && Galaxy.frame.active ){ Galaxy.frame.add({ diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/dataset/dataset-li.js --- a/client/galaxy/scripts/mvc/dataset/dataset-li.js +++ b/client/galaxy/scripts/mvc/dataset/dataset-li.js @@ -160,7 +160,7 @@ // add frame manager option onclick event var self = this; displayBtnData.onclick = function( ev ){ - if( Galaxy.frame && Galaxy.frame.active ){ + if (Galaxy.frame && Galaxy.frame.active) { // Add dataset to frames. Galaxy.frame.add_dataset(self.model.get('id')); ev.preventDefault(); diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/dataset/dataset-model.js --- a/client/galaxy/scripts/mvc/dataset/dataset-model.js +++ b/client/galaxy/scripts/mvc/dataset/dataset-model.js @@ -94,10 +94,7 @@ this.trigger( 'state:ready', currModel, newState, this.previous( 'state' ) ); } }); - this.on( 'change:urls', function(){ - console.warn( 'change:urls', arguments ); - }); - // the download url (currenlty) relies on having a correct file extension + // the download url (currently) relies on having a correct file extension this.on( 'change:id change:file_ext', function( currModel ){ this._generateUrls(); }); @@ -139,8 +136,15 @@ }, // ........................................................................ ajax + fetch : function( options ){ + var dataset = this; + return Backbone.Model.prototype.fetch.call( this, options ) + .always( function(){ + dataset._generateUrls(); + }); + }, + //NOTE: subclasses of DA's will need to implement url and urlRoot in order to have these work properly - /** save this dataset, _Mark_ing it as deleted (just a flag) */ 'delete' : function( options ){ if( this.get( 'deleted' ) ){ return jQuery.when(); } @@ -359,74 +363,11 @@ Backbone.Collection.prototype.set.call( this, models, options ); }, -// /** Convert this ad-hoc collection of hdas to a formal collection tracked -// by the server. -// **/ -// promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){ -////TODO: seems like this would be better in mvc/collections -// options = options || {}; -// options.url = this.url(); -// options.type = "POST"; -// var full_collection_type = collection_type; -// var element_identifiers = [], -// name = null; -// -// // This mechanism is rough - no error handling, allows invalid selections, no way -// // for user to pick/override element identifiers. This is only really meant -// if( collection_type === "list" ) { -// this.chain().each( function( hda ) { -// // TODO: Handle duplicate names. -// var name = hda.attributes.name; -// var id = hda.get('id'); -// var content_type = hda.attributes.history_content_type; -// if( content_type === "dataset" ) { -// if( full_collection_type !== "list" ) { -// this.log( "Invalid collection type" ); -// } -// element_identifiers.push( { name: name, src: "hda", id: id } ); -// } else { -// if( full_collection_type === "list" ) { -// full_collection_type = "list:" + hda.attributes.collection_type; -// } else { -// if( full_collection_type !== "list:" + hda.attributes.collection_type ) { -// this.log( "Invalid collection type" ); -// } -// } -// element_identifiers.push( { name: name, src: "hdca", id: id } ); -// } -// }); -// name = "New Dataset List"; -// } else if( collection_type === "paired" ) { -// var ids = this.ids(); -// if( ids.length !== 2 ){ -// // TODO: Do something... -// } -// element_identifiers.push( { name: "forward", src: "hda", id: ids[ 0 ] } ); -// element_identifiers.push( { name: "reverse", src: "hda", id: ids[ 1 ] } ); -// name = "New Dataset Pair"; -// } -// options.data = { -// type: "dataset_collection", -// name: name, -// collection_type: full_collection_type, -// element_identifiers: JSON.stringify( element_identifiers ) -// }; -// -// var xhr = jQuery.ajax( options ); -// xhr.done( function( message, status, responseObj ){ -// history.refresh( ); -// }); -// xhr.fail( function( xhr, status, message ){ -// if( xhr.responseJSON && xhr.responseJSON.error ){ -// error = xhr.responseJSON.error; -// } else { -// error = xhr.responseJSON; -// } -// xhr.responseText = error; -// // Do something? -// }); -// return xhr; -// }, + ///** Convert this ad-hoc collection of hdas to a formal collection tracked + // by the server. + //**/ + //promoteToHistoryDatasetCollection : function _promote( history, collection_type, options ){ + //}, /** String representation. */ toString : function(){ diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/history/history-contents.js --- a/client/galaxy/scripts/mvc/history/history-contents.js +++ b/client/galaxy/scripts/mvc/history/history-contents.js @@ -187,6 +187,7 @@ /** copy an existing, accessible hda into this collection */ copy : function( id ){ +//TODO: incorp collections var collection = this, xhr = jQuery.post( this.url(), { source : 'hda', diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 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 @@ -14,7 +14,7 @@ * @constructs */ var History = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend( -/** @lends History.prototype */{ + BASE_MVC.mixin( BASE_MVC.SearchableModelMixin, /** @lends History.prototype */{ /** logger used to record this.log messages, commonly set to console */ //logger : console, @@ -117,7 +117,19 @@ return _.reduce( _.values( this.get( 'state_details' ) ), function( memo, num ){ return memo + num; }, 0 ); }, - // ........................................................................ ajax + // ........................................................................ search + /** What model fields to search with */ + searchAttributes : [ + 'name', 'annotation', 'tags' + ], + + /** Adding title and singular tag */ + searchAliases : { + title : 'name', + tag : 'tags' + }, + + // ........................................................................ updates /** does the contents collection indicate they're still running and need to be updated later? * delay + update if needed * @param {Function} onReadyCallback function to run when all contents are in the ready state @@ -187,6 +199,18 @@ return xhr; }, + // ........................................................................ ajax + /** save this history, _Mark_ing it as deleted (just a flag) */ + _delete : function( options ){ + if( this.get( 'deleted' ) ){ return jQuery.when(); } + return this.save( { deleted: true }, options ); + }, + /** save this history, _Mark_ing it as undeleted */ + undelete : function( options ){ + if( !this.get( 'deleted' ) ){ return jQuery.when(); } + return this.save( { deleted: false }, options ); + }, + /** Make a copy of this history on the server * @param {Boolean} current if true, set the copy as the new current history (default: true) * @param {String} name name of new history (default: none - server sets to: Copy of <current name>) @@ -210,9 +234,28 @@ //TODO:?? all datasets? var history = this, - xhr = jQuery.post( this.urlRoot, postData ); - xhr.done( function( newData ){ - history.trigger( 'copied', history, newData ); + copy = jQuery.post( this.urlRoot, postData ); + // if current - queue to setAsCurrent before firing 'copied' + if( current ){ + return copy.then( function( response ){ + var newHistory = new History( response ); + return newHistory.setAsCurrent() + .done( function(){ + history.trigger( 'copied', history, response ); + }); + }); + } + return copy.done( function( response ){ + history.trigger( 'copied', history, response ); + }); + }, + + setAsCurrent : function(){ + var history = this, + xhr = jQuery.getJSON( '/history/set_as_current?id=' + this.id ); + + xhr.done( function(){ + history.trigger( 'set-as-current', history ); }); return xhr; }, @@ -221,7 +264,7 @@ toString : function(){ return 'History(' + this.get( 'id' ) + ',' + this.get( 'name' ) + ')'; } -}); +})); //------------------------------------------------------------------------------ CLASS VARS /** When the history has running hdas, @@ -351,12 +394,15 @@ create : function create( data, hdas, historyOptions, xhrOptions ){ var collection = this, - history = new History( data || {}, hdas || [], historyOptions || {} ); - return history.save( xhrOptions ).done( function( newData ){ + xhr = jQuery.getJSON( galaxy_config.root + 'history/create_new_current' ); + return xhr.done( function( newData ){ + var history = new History( newData, [], historyOptions || {} ); // new histories go in the front //TODO: (implicit ordering by update time...) collection.unshift( history ); + collection.trigger( 'new-current' ); }); +//TODO: move back to using history.save (via Deferred.then w/ set_as_current) }, toString: function toString(){ diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/history/history-panel-edit-current.js --- a/client/galaxy/scripts/mvc/history/history-panel-edit-current.js +++ b/client/galaxy/scripts/mvc/history/history-panel-edit-current.js @@ -164,12 +164,13 @@ _setUpCollectionListeners : function(){ _super.prototype._setUpCollectionListeners.call( this ); + //TODO:?? may not be needed? see history-panel-edit, 369 // if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state, // then: remove it from the collection if the panel is set to NOT show hidden datasets this.collection.on( 'state:ready', function( model, newState, oldState ){ if( ( !model.get( 'visible' ) ) && ( !this.storage.get( 'show_hidden' ) ) ){ - this.removeItemView( this.viewFromModel( model ) ); + this.removeItemView( model ); } }, this ); }, @@ -226,7 +227,7 @@ '</a>' ].join('') ); $emptyMsg.find( '.uploader-link' ).click( function( ev ){ - Galaxy.upload._eventShow( ev ); + Galaxy.upload.show( ev ); }); $emptyMsg.find( '.get-data-link' ).click( function( ev ){ $toolMenu.parent().scrollTop( 0 ); @@ -288,51 +289,23 @@ }, // ------------------------------------------------------------------------ sub-views - // reverse HID order - /** Override to reverse order of views - newest contents on top - * and add the current-content highlight class to currentContentId's view - */ + /** Override to add the current-content highlight class to currentContentId's view */ _attachItems : function( $whereTo ){ - var panel = this; - this.$list( $whereTo ).append( this.views.reverse().map( function( view ){ - // add current content - if( panel.currentContentId && view.model.id === panel.currentContentId ){ - panel.setCurrentContent( view ); - } - return view.$el; - })); + _super.prototype._attachItems.call( this, $whereTo ); + var panel = this, + currentContentView; + if( panel.currentContentId + && ( currentContentView = panel.viewFromModelId( panel.currentContentId ) ) ){ + panel.setCurrentContent( currentContentView ); + } return this; }, - /** Override to add datasets at the top */ + /** Override to remove any drill down panels */ addItemView : function( model, collection, options ){ - this.log( this + '.addItemView:', model ); - var panel = this; - if( !panel._filterItem( model ) ){ return undefined; } -//TODO: alternately, call collapse drilldown - // if this panel is currently hidden, return undefined - if( panel.panelStack.length ){ return this._collapseDrilldownPanel(); } - - var view = panel._createItemView( model ); - // use unshift and prepend to preserve reversed order - panel.views.unshift( view ); - - panel.scrollToTop(); - $({}).queue([ - function fadeOutEmptyMsg( next ){ - var $emptyMsg = panel.$emptyMessage(); - if( $emptyMsg.is( ':visible' ) ){ - $emptyMsg.fadeOut( panel.fxSpeed, next ); - } else { - next(); - } - }, - function createAndPrepend( next ){ - // render as hidden then slide down - panel.$list().prepend( view.render( 0 ).$el.hide() ); - view.$el.slideDown( panel.fxSpeed ); - } - ]); + var view = _super.prototype.addItemView.call( this, model, collection, options ); + if( !view ){ return view; } + if( this.panelStack.length ){ return this._collapseDrilldownPanel(); } return view; }, @@ -423,22 +396,6 @@ if( !msg.is( ':hidden' ) ){ msg.slideUp( this.fxSpeed ); } }, -//TODO: move show_deleted/hidden into panel from opt menu and remove this - /** add listeners to an external options menu (templates/webapps/galaxy/root/index.mako) */ - connectToOptionsMenu : function( optionsMenu ){ - if( !optionsMenu ){ - return this; - } - // set a visible indication in the popupmenu for show_hidden/deleted based on the currHistoryPanel's settings - this.on( 'new-storage', function( storage, panel ){ - if( optionsMenu && storage ){ - optionsMenu.findItemByHtml( _l( 'Include Deleted Datasets' ) ).checked = storage.get( 'show_deleted' ); - optionsMenu.findItemByHtml( _l( 'Include Hidden Datasets' ) ).checked = storage.get( 'show_hidden' ); - } - }); - return this; - }, - /** Return a string rep of the history */ toString : function(){ diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/history/history-panel-edit.js --- a/client/galaxy/scripts/mvc/history/history-panel-edit.js +++ b/client/galaxy/scripts/mvc/history/history-panel-edit.js @@ -69,7 +69,18 @@ this.multiselectActions = attributes.multiselectActions || this._getActions(); }, - // ------------------------------------------------------------------------ panel rendering + /** Override to handle history as drag-drop target */ + _setUpListeners : function(){ + _super.prototype._setUpListeners.call( this ); + + this.on( 'drop', function( ev, data ){ + this.dataDropped( data ); + // remove the drop target + this.dropTargetOff(); + }); + }, + + // ------------------------------------------------------------------------ listeners /** listening for collection events */ _setUpCollectionListeners : function(){ _super.prototype._setUpCollectionListeners.call( this ); @@ -104,6 +115,42 @@ return $newRender; }, + /** override to render counts when the items are rendered */ + renderItems : function( $whereTo ){ + var views = _super.prototype.renderItems.call( this, $whereTo ); + this._renderCounts( $whereTo ); + return views; + }, + + /** override to show counts, what's deleted/hidden, and links to toggle those */ + _renderCounts : function( $whereTo ){ +//TODO: too complicated + function toggleLink( _class, text ){ + return [ '<a class="', _class, '" href="javascript:void(0);">', text, '</a>' ].join( '' ); + } + $whereTo = $whereTo || this.$el; + var deleted = this.collection.where({ deleted: true }), + hidden = this.collection.where({ visible: false }), + msgs = []; + + if( this.views.length ){ + msgs.push( [ this.views.length, _l( 'shown' ) ].join( ' ' ) ); + } + if( deleted.length ){ + msgs.push( ( !this.showDeleted )? + ([ deleted.length, toggleLink( 'toggle-deleted-link', _l( 'deleted' ) ) ].join( ' ' )) + :( toggleLink( 'toggle-deleted-link', _l( 'hide deleted' ) ) ) + ); + } + if( hidden.length ){ + msgs.push( ( !this.showHidden )? + ([ hidden.length, toggleLink( 'toggle-hidden-link', _l( 'hidden' ) ) ].join( ' ' )) + :( toggleLink( 'toggle-hidden-link', _l( 'hide hidden' ) ) ) + ); + } + return $whereTo.find( '> .controls .subtitle' ).html( msgs.join( ', ' ) ); + }, + /** render the tags sub-view controller */ _renderTags : function( $where ){ var panel = this; @@ -266,6 +313,24 @@ }, // ------------------------------------------------------------------------ sub-views + // reverse HID order + /** Override to reverse order of views - newest contents on top */ + _attachItems : function( $whereTo ){ + this.$list( $whereTo ).append( this.views.reverse().map( function( view ){ + return view.$el; + })); + return this; + }, + + /** Override to add new contents at the top */ + _attachView : function( view ){ + var panel = this; + // override to control where the view is added, how/whether it's rendered + panel.views.unshift( view ); + panel.$list().prepend( view.render( 0 ).$el.hide() ); + view.$el.slideDown( panel.fxSpeed ); + }, + /** In this override, add purgeAllowed and whether tags/annotation editors should be shown */ _getItemViewOptions : function( model ){ var options = _super.prototype._getItemViewOptions.call( this, model ); @@ -278,22 +343,31 @@ return options; }, + ///** Override to alter data in drag based on multiselection */ + //_setUpItemViewListeners : function( view ){ + // var panel = this; + // _super.prototype._setUpItemViewListeners.call( panel, view ); + // + //}, + /** If this item is deleted and we're not showing deleted items, remove the view * @param {Model} the item model to check */ _handleHdaDeletionChange : function( itemModel ){ - if( itemModel.get( 'deleted' ) && !this.storage.get( 'show_deleted' ) ){ + if( itemModel.get( 'deleted' ) && !this.showDeleted ){ this.removeItemView( itemModel ); } + this._renderCounts(); }, /** If this item is hidden and we're not showing hidden items, remove the view * @param {Model} the item model to check */ _handleHdaVisibleChange : function( itemModel ){ - if( itemModel.hidden() && !this.storage.get( 'show_hidden' ) ){ + if( itemModel.hidden() && !this.storage.showHidden ){ this.removeItemView( itemModel ); } + this._renderCounts(); }, /** toggle the visibility of each content's tagsEditor applying all the args sent to this function */ @@ -319,7 +393,9 @@ // ------------------------------------------------------------------------ panel events /** event map */ events : _.extend( _.clone( _super.prototype.events ), { - 'click .show-selectors-btn' : 'toggleSelectors' + 'click .show-selectors-btn' : 'toggleSelectors', + 'click .toggle-deleted-link' : function( ev ){ this.toggleShowDeleted(); }, + 'click .toggle-hidden-link' : function( ev ){ this.toggleShowHidden(); } }), /** Update the history size display (curr. upper right of panel). @@ -328,6 +404,132 @@ this.$el.find( '.history-size' ).text( this.model.get( 'nice_size' ) ); }, + // ------------------------------------------------------------------------ as drop target + /** */ + dropTargetOn : function(){ + if( this.dropTarget ){ return this; } + this.dropTarget = true; + + //TODO: to init + var dropHandlers = { + 'dragenter' : _.bind( this.dragenter, this ), + 'dragover' : _.bind( this.dragover, this ), + 'dragleave' : _.bind( this.dragleave, this ), + 'drop' : _.bind( this.drop, this ) + }; +//TODO: scroll to top + var $dropTarget = this._renderDropTarget(); + this.$list().before([ this._renderDropTargetHelp(), $dropTarget ]); + for( var evName in dropHandlers ){ + if( dropHandlers.hasOwnProperty( evName ) ){ + //console.debug( evName, dropHandlers[ evName ] ); + $dropTarget.on( evName, dropHandlers[ evName ] ); + } + } + return this; + }, + + /** */ + _renderDropTarget : function(){ + return $( '<div/>' ).addClass( 'history-drop-target' ) + .css({ + 'height': '64px', + 'margin': '0px 10px 10px 10px', + 'border': '1px dashed black', + 'border-radius' : '3px' + }); + }, + + /** */ + _renderDropTargetHelp : function(){ + return $( '<div/>' ).addClass( 'history-drop-target-help' ) + .css({ + 'margin' : '10px 10px 4px 10px', + 'color' : 'grey', + 'font-size' : '80%', + 'font-style' : 'italic' + }) + .text( _l( 'Drag datasets here to copy them to the current history' ) ); + }, + + /** */ + dropTargetOff : function(){ + if( !this.dropTarget ){ return this; } + //this.log( 'dropTargetOff' ); + this.dropTarget = false; + // + //var dropTarget = this.$( '.history-drop-target' ).get(0); + //for( var evName in this._dropHandlers ){ + // if( this._dropHandlers.hasOwnProperty( evName ) ){ + // console.debug( evName, this._dropHandlers[ evName ] ); + // dropTarget.off( evName, this._dropHandlers[ evName ] ); + // } + //} + this.$( '.history-drop-target' ).remove(); + this.$( '.history-drop-target-help' ).remove(); + return this; + }, + /** */ + dropTargetToggle : function(){ + if( this.dropTarget ){ + this.dropTargetOff(); + } else { + this.dropTargetOn(); + } + return this; + }, + + /** */ + dragenter : function( ev ){ + //console.debug( 'dragenter:', this, ev ); + ev.preventDefault(); + ev.stopPropagation(); + this.$( '.history-drop-target' ).css( 'border', '2px solid black' ); + }, + /** */ + dragover : function( ev ){ + ev.preventDefault(); + ev.stopPropagation(); + }, + /** */ + dragleave : function( ev ){ + //console.debug( 'dragleave:', this, ev ); + ev.preventDefault(); + ev.stopPropagation(); + this.$( '.history-drop-target' ).css( 'border', '1px dashed black' ); + }, + /** */ + drop : function( ev ){ + //console.warn( 'dataTransfer:', ev.dataTransfer.getData( 'text' ) ); + //console.warn( 'dataTransfer:', ev.originalEvent.dataTransfer.getData( 'text' ) ); + ev.preventDefault(); + //ev.stopPropagation(); + ev.dataTransfer.dropEffect = 'move'; + + //console.debug( 'ev.dataTransfer:', ev.dataTransfer ); + + var panel = this, + data = ev.dataTransfer.getData( "text" ); + try { + data = JSON.parse( data ); + + } catch( err ){ + this.warn( 'error parsing JSON from drop:', data ); + } + this.trigger( 'droptarget:drop', ev, data, panel ); + return false; + }, + + /** */ + dataDropped : function( data ){ + var panel = this; + // HDA: dropping will copy it to the history + if( _.isObject( data ) && data.model_class === 'HistoryDatasetAssociation' && data.id ){ + return panel.model.contents.copy( data.id ); + } + return jQuery.when(); + }, + // ........................................................................ misc /** Return a string rep of the history */ toString : function(){ diff -r 769e8dca49f033059d140b614c84381f13394611 -r c1b54085c3aeb9a7cf97c7277436ab3f7b50d299 client/galaxy/scripts/mvc/history/history-panel.js --- a/client/galaxy/scripts/mvc/history/history-panel.js +++ b/client/galaxy/scripts/mvc/history/history-panel.js @@ -254,6 +254,10 @@ _setUpWebStorage : function( initiallyExpanded, show_deleted, show_hidden ){ //if( !this.model ){ return this; } //this.log( '_setUpWebStorage', initiallyExpanded, show_deleted, show_hidden ); + if( this.storage ){ + this.stopListening( this.storage ); + } + this.storage = new HistoryPrefs({ id: HistoryPrefs.historyStorageKey( this.model.get( 'id' ) ) }); @@ -276,6 +280,18 @@ this.trigger( 'new-storage', this.storage, this ); this.log( this + ' (init\'d) storage:', this.storage.get() ); + + this.listenTo( this.storage, { + 'change:show_deleted' : function( view, newVal ){ + this.showDeleted = newVal; + }, + 'change:show_hidden' : function( view, newVal ){ + this.showHidden = newVal; + } + }, this ); + this.showDeleted = ( show_deleted !== undefined )? show_deleted : this.storage.get( 'show_deleted' ); + this.showHidden = ( show_hidden !== undefined )? show_hidden : this.storage.get( 'show_hidden' ); + return this; }, @@ -317,8 +333,8 @@ _filterItem : function( model ){ var panel = this; return ( _super.prototype._filterItem.call( panel, model ) - && ( !model.hidden() || panel.storage.get( 'show_hidden' ) ) - && ( !model.isDeletedOrPurged() || panel.storage.get( 'show_deleted' ) ) ); + && ( !model.hidden() || panel.showHidden ) + && ( !model.isDeletedOrPurged() || panel.showDeleted ) ); }, /** in this override, add a linktarget, and expand if id is in web storage */ @@ -372,12 +388,17 @@ * (2) re-rendering the history * @returns {Boolean} new show_deleted setting */ - toggleShowDeleted : function( show ){ - show = ( show !== undefined )?( show ):( !this.storage.get( 'show_deleted' ) ); - this.storage.set( 'show_deleted', show ); + toggleShowDeleted : function( show, store ){ + show = ( show !== undefined )?( show ):( !this.showDeleted ); + store = ( store !== undefined )?( store ):( true ); + this.showDeleted = show; + if( store ){ + this.storage.set( 'show_deleted', show ); + } + this.trigger( 'show-hidden', show ); //TODO:?? to events on storage('change:show_deleted') this.renderItems(); - return this.storage.get( 'show_deleted' ); + return this.showDeleted; }, /** Handle the user toggling the deleted visibility by: @@ -385,12 +406,17 @@ * (2) re-rendering the history * @returns {Boolean} new show_hidden setting */ - toggleShowHidden : function( show ){ - show = ( show !== undefined )?( show ):( !this.storage.get( 'show_hidden' ) ); - this.storage.set( 'show_hidden', show ); - //TODO:?? to events on storage('change:show_hidden') + toggleShowHidden : function( show, store ){ + show = ( show !== undefined )?( show ):( !this.showHidden ); + store = ( store !== undefined )?( store ):( true ); + this.showHidden = show; + if( store ){ + this.storage.set( 'show_hidden', show ); + } + this.trigger( 'show-hidden', show ); + //TODO:?? to events on storage('change:show_deleted') this.renderItems(); - return this.storage.get( 'show_hidden' ); + return this.showHidden; }, /** On the first search, if there are no details - load them, then search */ @@ -582,9 +608,7 @@ '<div class="title">', '<div class="name"><%= history.name %></div>', '</div>', - '<div class="subtitle">', - //'<%= view.collection.length %>', _l( ' items' ), - '</div>', + '<div class="subtitle"></div>', '<div class="history-size"><%= history.nice_size %></div>', '<div class="actions"></div>', 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.