diff --git a/.ci/flake8_blacklist.txt b/.ci/flake8_blacklist.txt index 4f2201f803e..6a17718a548 100644 --- a/.ci/flake8_blacklist.txt +++ b/.ci/flake8_blacklist.txt @@ -5,3 +5,4 @@ database/ doc/source/conf.py eggs/ lib/galaxy/util/jstree.py +lib/galaxy/web/proxy/js/node_modules/ diff --git a/.ci/py3_sources.txt b/.ci/py3_sources.txt index d52ac5da90b..87e88f16894 100644 --- a/.ci/py3_sources.txt +++ b/.ci/py3_sources.txt @@ -47,6 +47,8 @@ lib/galaxy/tours/ lib/galaxy/util/ lib/galaxy/visualization/ lib/galaxy/web/buildapp.py +lib/galaxy/web/framework/base.py +lib/galaxy/web/framework/decorators.py lib/galaxy/web/framework/__init__.py lib/galaxy/web/framework/middleware/error.py lib/galaxy/web/framework/middleware/static.py diff --git a/README.rst b/README.rst index 3db8f44c9c3..0abd2e598a2 100644 --- a/README.rst +++ b/README.rst @@ -1,4 +1,4 @@ -.. figure:: https://wiki.galaxyproject.org/Images/GalaxyLogo?action=AttachFile&do=get&target=galaxy_project_logo.jpg +.. figure:: https://galaxyproject.org/images/galaxy-logos/galaxy_project_logo.jpg :alt: Galaxy Logo The latest information about Galaxy is available via `https://galaxyproject.org/ `__ diff --git a/client/galaxy/scripts/apps/analysis.js b/client/galaxy/scripts/apps/analysis.js index c313169ca26..c893ed19271 100644 --- a/client/galaxy/scripts/apps/analysis.js +++ b/client/galaxy/scripts/apps/analysis.js @@ -68,15 +68,6 @@ window.app = function app( options, bootstrapped ){ Galaxy.currHistoryPanel = historyPanel.historyView; Galaxy.currHistoryPanel.listenToGalaxy( Galaxy ); - //HACK: move there - Galaxy.app = { - display : function( view, target ){ - // TODO: Remove this line after select2 update - $( '.select2-hidden-accessible' ).remove(); - centerPanel.display( view ); - }, - }; - // .................................................... routes /** */ Galaxy.router = new ( Backbone.Router.extend({ @@ -86,6 +77,17 @@ window.app = function app( options, bootstrapped ){ this.options = options; }, + /** helper to push a new navigation state */ + push: function( url, data ) { + data = data || {}; + data.__identifer = Math.random().toString( 36 ).substr( 2 ); + if ( !$.isEmptyObject( data ) ) { + url += url.indexOf( '?' ) == -1 ? '?' : '&'; + url += $.param( data , true ); + } + this.navigate( url, { 'trigger': true } ); + }, + /** override to parse query string into obj and send to each route */ execute: function( callback, args, name ){ Galaxy.debug( 'router execute:', callback, args, name ); @@ -101,7 +103,8 @@ window.app = function app( options, bootstrapped ){ // TODO: remove annoying 'root' from root urls '(/)root*' : 'home', '(/)tours(/)(:tour_id)' : 'show_tours', - '(/)users(/)' : 'show_users', + '(/)user(/)' : 'show_user', + '(/)user(/)(:form_id)' : 'show_user_form', }, show_tours : function( tour_id ){ @@ -112,10 +115,14 @@ window.app = function app( options, bootstrapped ){ } }, - show_users : function(){ + show_user : function(){ centerPanel.display( new UserPreferences.View() ); }, + show_user_form : function( form_id ) { + centerPanel.display( new UserPreferences.Forms( { form_id: form_id, user_id: Galaxy.params.id } ) ); + }, + /** */ home : function( params ){ // TODO: to router, remove Globals diff --git a/client/galaxy/scripts/galaxy.interactive_environments.js b/client/galaxy/scripts/galaxy.interactive_environments.js index eb2ed98837a..180011d5906 100644 --- a/client/galaxy/scripts/galaxy.interactive_environments.js +++ b/client/galaxy/scripts/galaxy.interactive_environments.js @@ -17,6 +17,59 @@ function display_spinner(){ $('#main').append(''); } +/** + * Check a URL for a boolean true/false and call a callback when done. + */ +function load_when_ready(url, success_callback){ + var request_count = 0; + var timeout_time = 1000; + var timeout_time_max = 15000; + var timeout_time_step = 1000; + var timeout = function(){ + $.ajax({ + url: url, + xhrFields: { + withCredentials: true + }, + type: "GET", + timeout: 500, + dataType: "json", + success: function(data){ + if(data == true){ + console.log("Galaxy reports IE container ready, returning"); + clear_main_area(); + toastr.clear(); + success_callback(); + }else if(data == false){ + if(request_count == 0){ + display_spinner(); + toastr.info( + "Galaxy is launching a container in which to run this interactive environment. Please wait...", + {'closeButton': true, 'tapToDismiss': false} + ); + } + request_count++; + if(timeout_time < timeout_time_max){ + timeout_time += timeout_time_step; + } + console.log("Readiness request " + request_count + " sleeping " + timeout_time / 1000 + "s"); + window.setTimeout(timeout, timeout_time) + }else{ + clear_main_area(); + toastr.clear(); + toastr.error( + "Galaxy failed to launch a container in which to run this interactive environment, contact your administrator.", + "Error", + {'closeButton': true, 'tapToDismiss': false} + ); + } + } + }); + } + window.setTimeout(timeout, timeout_time); +} + + /** * Test availability of a URL, and call a callback when done. @@ -43,7 +96,7 @@ function test_ie_availability(url, success_callback){ }, error: function(jqxhr, status, error){ request_count++; - console.log("Request " + request_count); + console.log("Availability request " + request_count); if(request_count > 30){ clearInterval(interval); clear_main_area(); diff --git a/client/galaxy/scripts/layout/menu.js b/client/galaxy/scripts/layout/menu.js index ffaafea5af2..507cf9aa843 100644 --- a/client/galaxy/scripts/layout/menu.js +++ b/client/galaxy/scripts/layout/menu.js @@ -1,5 +1,5 @@ /** Masthead Collection **/ -define(['layout/generic-nav-view', 'mvc/webhooks'], function( GenericNav, Webhooks ) { +define(['layout/generic-nav-view', 'mvc/webhooks', 'utils/localization'], function( GenericNav, Webhooks, _l ) { var Collection = Backbone.Collection.extend({ model: Backbone.Model.extend({ defaults: { @@ -22,7 +22,7 @@ var Collection = Backbone.Collection.extend({ // this.add({ id : 'analysis', - title : 'Analyze Data', + title : _l('Analyze Data'), url : '', tooltip : 'Analysis home view' }); @@ -32,7 +32,7 @@ var Collection = Backbone.Collection.extend({ // this.add({ id : 'workflow', - title : 'Workflow', + title : _l('Workflow'), url : 'workflow', tooltip : 'Chain tools into workflows', disabled : !Galaxy.user.id @@ -43,23 +43,23 @@ var Collection = Backbone.Collection.extend({ // this.add({ id : 'shared', - title : 'Shared Data', + title : _l('Shared Data'), url : 'library/index', tooltip : 'Access published resources', menu : [{ - title : 'Data Libraries', + title : _l('Data Libraries'), url : 'library/list' },{ - title : 'Histories', + title : _l('Histories'), url : 'history/list_published' },{ - title : 'Workflows', + title : _l('Workflows'), url : 'workflow/list_published' },{ - title : 'Visualizations', + title : _l('Visualizations'), url : 'visualization/list_published' },{ - title : 'Pages', + title : _l('Pages'), url : 'page/list_published' }] }); @@ -87,20 +87,20 @@ var Collection = Backbone.Collection.extend({ // this.add({ id : 'visualization', - title : 'Visualization', + title : _l('Visualization'), url : 'visualization/list', tooltip : 'Visualize datasets', disabled : !Galaxy.user.id, menu : [{ - title : 'New Track Browser', + title : _l('New Track Browser'), url : 'visualization/trackster', target : '_frame' },{ - title : 'Saved Visualizations', + title : _l('Saved Visualizations'), url : 'visualization/list', target : '_frame' },{ - title : 'Interactive Environments', + title : _l('Interactive Environments'), url : 'visualization/gie_list', target : 'galaxy_main' } @@ -147,7 +147,7 @@ var Collection = Backbone.Collection.extend({ // Galaxy.user.get( 'is_admin' ) && this.add({ id : 'admin', - title : 'Admin', + title : _l('Admin'), url : 'admin', tooltip : 'Administer this Galaxy', cls : 'admin-only' @@ -158,34 +158,34 @@ var Collection = Backbone.Collection.extend({ // var helpTab = { id : 'help', - title : 'Help', + title : _l('Help'), tooltip : 'Support, contact, and community', menu : [{ - title : 'Support', + title : _l('Support'), url : options.support_url, target : '_blank' },{ - title : 'Search', + title : _l('Search'), url : options.search_url, target : '_blank' },{ - title : 'Mailing Lists', + title : _l('Mailing Lists'), url : options.mailing_lists, target : '_blank' },{ - title : 'Videos', + title : _l('Videos'), url : options.screencasts_url, target : '_blank' },{ - title : 'Wiki', + title : _l('Wiki'), url : options.wiki_url, target : '_blank' },{ - title : 'How to Cite Galaxy', + title : _l('How to Cite Galaxy'), url : options.citation_url, target : '_blank' },{ - title : 'Interactive Tours', + title : _l('Interactive Tours'), url : 'tours', onclick : function(){ if (Galaxy.router){ @@ -198,17 +198,17 @@ var Collection = Backbone.Collection.extend({ }] }; options.terms_url && helpTab.menu.push({ - title : 'Terms and Conditions', + title : _l('Terms and Conditions'), url : options.terms_url, target : '_blank' }); options.biostar_url && helpTab.menu.unshift({ - title : 'Ask a question', + title : _l('Ask a question'), url : 'biostar/biostar_question_redirect', target : '_blank' }); options.biostar_url && helpTab.menu.unshift({ - title : 'Galaxy Biostar', + title : _l('Galaxy Biostar'), url : options.biostar_url_redirect, target : '_blank' }); @@ -220,18 +220,18 @@ var Collection = Backbone.Collection.extend({ if ( !Galaxy.user.id ){ var userTab = { id : 'user', - title : 'User', + title : _l('User'), cls : 'loggedout-only', tooltip : 'Account registration or login', menu : [{ - title : 'Login', + title : _l('Login'), url : 'user/login', target : 'galaxy_main', noscratchbook : true }] }; options.allow_user_creation && userTab.menu.push({ - title : 'Register', + title : _l('Register'), url : 'user/create', target : 'galaxy_main', noscratchbook : true @@ -240,37 +240,41 @@ var Collection = Backbone.Collection.extend({ } else { var userTab = { id : 'user', - title : 'User', + title : _l('User'), cls : 'loggedin-only', tooltip : 'Account and saved data', menu : [{ - title : 'Logged in as ' + Galaxy.user.get( 'email' ) + title : _l('Logged in as') + ' ' + Galaxy.user.get( 'email' ) },{ - title : 'Preferences', - url : 'users', + title : _l('Preferences'), + url : 'user', target : 'galaxy_main', onclick : function() { - window.location = Galaxy.root + 'users'; + if ( Galaxy.router ) { + Galaxy.router.push( 'user' ); + } else { + window.location = Galaxy.root + 'user'; + } } },{ - title : 'Custom Builds', + title : _l('Custom Builds'), url : 'user/dbkeys', target : 'galaxy_main' },{ - title : 'Logout', + title : _l('Logout'), url : 'user/logout', target : '_top', divider : true },{ - title : 'Saved Histories', + title : _l('Saved Histories'), url : 'history/list', target : 'galaxy_main' },{ - title : 'Saved Datasets', + title : _l('Saved Datasets'), url : 'dataset/list', target : 'galaxy_main' },{ - title : 'Saved Pages', + title : _l('Saved Pages'), url : 'page/list', target : '_top' }] diff --git a/client/galaxy/scripts/mvc/collection/base-creator.js b/client/galaxy/scripts/mvc/collection/base-creator.js new file mode 100644 index 00000000000..351406f939d --- /dev/null +++ b/client/galaxy/scripts/mvc/collection/base-creator.js @@ -0,0 +1,106 @@ +define([ +], function( ){ + +/* For presentation-related functionality shared across collection creators. + Particularily overlapping functionality related to name processing and help. +*/ +var CollectionCreatorMixin = { + + /** add (or clear if clear is truthy) a validation warning to the DOM element described in what */ + _validationWarning : function( what, clear ){ + var VALIDATION_CLASS = 'validation-warning'; + if( what === 'name' ){ + what = this.$( '.collection-name' ).add( this.$( '.collection-name-prompt' ) ); + this.$( '.collection-name' ).focus().select(); + } + if( clear ){ + what = what || this.$( '.' + VALIDATION_CLASS ); + what.removeClass( VALIDATION_CLASS ); + } else { + what.addClass( VALIDATION_CLASS ); + } + }, + + // ........................................................................ footer + /** handle a collection name change */ + _changeName : function( ev ){ + this._validationWarning( 'name', !!this._getName() ); + }, + + /** check for enter key press when in the collection name and submit */ + _nameCheckForEnter : function( ev ){ + if( ev.keyCode === 13 && !this.blocking ){ + this._clickCreate(); + } + }, + + /** get the current collection name */ + _getName : function(){ + return _.escape( this.$( '.collection-name' ).val() ); + }, + + // ........................................................................ header + /** expand help */ + _clickMoreHelp : function( ev ){ + ev.stopPropagation(); + this.$( '.main-help' ).addClass( 'expanded' ); + this.$( '.more-help' ).hide(); + }, + /** collapse help */ + _clickLessHelp : function( ev ){ + ev.stopPropagation(); + this.$( '.main-help' ).removeClass( 'expanded' ); + this.$( '.more-help' ).show(); + }, + /** toggle help */ + _toggleHelp : function( ev ){ + ev.stopPropagation(); + this.$( '.main-help' ).toggleClass( 'expanded' ); + this.$( '.more-help' ).toggle(); + }, + + /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */ + _showAlert : function( message, alertClass ){ + alertClass = alertClass || 'alert-danger'; + this.$( '.main-help' ).hide(); + this.$( '.header .alert' ) + .attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show() + .find( '.alert-message' ).html( message ); + }, + /** hide the alerts at the top */ + _hideAlert : function( message ){ + this.$( '.main-help' ).show(); + this.$( '.header .alert' ).hide(); + }, + + _cancelCreate: function( ev ){ + if( typeof this.oncancel === 'function' ){ + this.oncancel.call( this ); + } + }, + + /** attempt to create the current collection */ + _clickCreate : function( ev ){ + var name = this._getName(); + if( !name ){ + this._validationWarning( 'name' ); + } else if( !this.blocking ){ + this.createList( name ); + } + }, + + _creatorTemplates: { + main : _.template([ + '
', + '
', + '' + ].join('')), + } + +} + +//============================================================================== + return { + CollectionCreatorMixin: CollectionCreatorMixin + }; +}); diff --git a/client/galaxy/scripts/mvc/collection/list-collection-creator.js b/client/galaxy/scripts/mvc/collection/list-collection-creator.js index 5d7b75741be..f63f0847d03 100644 --- a/client/galaxy/scripts/mvc/collection/list-collection-creator.js +++ b/client/galaxy/scripts/mvc/collection/list-collection-creator.js @@ -3,15 +3,17 @@ define([ "mvc/history/hdca-model", "mvc/dataset/states", "mvc/base-mvc", + "mvc/collection/base-creator", "mvc/ui/ui-modal", "utils/natural-sort", "utils/localization", "ui/hoverhighlight" -], function( HDCA, STATES, BASE_MVC, UI_MODAL, naturalSort, _l ){ +], function( HDCA, STATES, BASE_MVC, baseCreator, UI_MODAL, naturalSort, _l ){ 'use strict'; var logNamespace = 'collections'; + /*============================================================================== TODO: use proper Element model and not just json @@ -151,7 +153,7 @@ var DatasetCollectionElementView = Backbone.View.extend( BASE_MVC.LoggableMixin // ============================================================================ /** An interface for building collections. */ -var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({ +var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend( baseCreator.CollectionCreatorMixin ).extend({ _logNamespace : logNamespace, /** the class used to display individual elements */ @@ -367,21 +369,6 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten this._showAlert( this.templates.invalidElements({ problems: this.invalidElements }), 'alert-warning' ); }, - /** add (or clear if clear is truthy) a validation warning to the DOM element described in what */ - _validationWarning : function( what, clear ){ - var VALIDATION_CLASS = 'validation-warning'; - if( what === 'name' ){ - what = this.$( '.collection-name' ).add( this.$( '.collection-name-prompt' ) ); - this.$( '.collection-name' ).focus().select(); - } - if( clear ){ - what = what || this.$( '.' + VALIDATION_CLASS ); - what.removeClass( VALIDATION_CLASS ); - } else { - what.addClass( VALIDATION_CLASS ); - } - }, - _disableNameAndCreate : function( disable ){ disable = !_.isUndefined( disable )? disable : true; if( disable ){ @@ -624,48 +611,10 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten // footer 'change .collection-name' : '_changeName', 'keydown .collection-name' : '_nameCheckForEnter', - 'click .cancel-create' : function( ev ){ - if( typeof this.oncancel === 'function' ){ - this.oncancel.call( this ); - } - }, + 'click .cancel-create' : '_cancelCreate', 'click .create-collection' : '_clickCreate'//, }, - // ........................................................................ header - /** expand help */ - _clickMoreHelp : function( ev ){ - ev.stopPropagation(); - this.$( '.main-help' ).addClass( 'expanded' ); - this.$( '.more-help' ).hide(); - }, - /** collapse help */ - _clickLessHelp : function( ev ){ - ev.stopPropagation(); - this.$( '.main-help' ).removeClass( 'expanded' ); - this.$( '.more-help' ).show(); - }, - /** toggle help */ - _toggleHelp : function( ev ){ - ev.stopPropagation(); - this.$( '.main-help' ).toggleClass( 'expanded' ); - this.$( '.more-help' ).toggle(); - }, - - /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*) */ - _showAlert : function( message, alertClass ){ - alertClass = alertClass || 'alert-danger'; - this.$( '.main-help' ).hide(); - this.$( '.header .alert' ) - .attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show() - .find( '.alert-message' ).html( message ); - }, - /** hide the alerts at the top */ - _hideAlert : function( message ){ - this.$( '.main-help' ).show(); - this.$( '.header .alert' ).hide(); - }, - // ........................................................................ elements /** reset all data to the initial state */ reset : function(){ @@ -789,46 +738,12 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten this.$dragging = null; }, - // ........................................................................ footer - /** handle a collection name change */ - _changeName : function( ev ){ - this._validationWarning( 'name', !!this._getName() ); - }, - - /** check for enter key press when in the collection name and submit */ - _nameCheckForEnter : function( ev ){ - if( ev.keyCode === 13 && !this.blocking ){ - this._clickCreate(); - } - }, - - /** get the current collection name */ - _getName : function(){ - return _.escape( this.$( '.collection-name' ).val() ); - }, - - /** attempt to create the current collection */ - _clickCreate : function( ev ){ - var name = this._getName(); - if( !name ){ - this._validationWarning( 'name' ); - } else if( !this.blocking ){ - this.createList( name ); - } - }, - // ------------------------------------------------------------------------ templates //TODO: move to require text plugin and load these as text //TODO: underscore currently unnecc. bc no vars are used //TODO: better way of localizing text-nodes in long strings /** underscore template fns attached to class */ - templates : { - /** the skeleton */ - main : _.template([ - '
', - '
', - '' - ].join('')), + templates : _.extend({}, baseCreator.CollectionCreatorMixin._creatorTemplates, { /** the header (not including help text) */ header : _.template([ @@ -974,7 +889,7 @@ var ListCollectionCreator = Backbone.View.extend( BASE_MVC.LoggableMixin ).exten '', '' ].join('')), - }, + }), // ------------------------------------------------------------------------ misc /** string rep */ diff --git a/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js b/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js index 23eca8a9bb2..264d61dde77 100644 --- a/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js +++ b/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js @@ -1,11 +1,11 @@ define([ "utils/levenshtein", "utils/natural-sort", - "mvc/collection/list-collection-creator", + "mvc/collection/base-creator", "mvc/base-mvc", "utils/localization", "ui/hoverhighlight" -], function( levenshteinDistance, naturalSort, LIST_COLLECTION_CREATOR, baseMVC, _l ){ +], function( levenshteinDistance, naturalSort, baseCreator, baseMVC, _l ){ 'use strict'; @@ -190,7 +190,7 @@ function autoPairFnBuilder( options ){ // ============================================================================ /** An interface for building collections of paired datasets. */ -var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).extend({ +var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).extend( baseCreator.CollectionCreatorMixin ).extend({ _logNamespace : logNamespace, className: 'list-of-pairs-collection-creator collection-creator flex-row-container', @@ -942,6 +942,7 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte // header 'click .more-help' : '_clickMoreHelp', 'click .less-help' : '_clickLessHelp', + 'click .main-help' : '_toggleHelp', 'click .header .alert button' : '_hideAlert', 'click .forward-column .column-title' : '_clickShowOnlyUnpaired', 'click .reverse-column .column-title' : '_clickShowOnlyUnpaired', @@ -981,39 +982,10 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte 'change .remove-extensions' : function( ev ){ this.toggleExtensions(); }, 'change .collection-name' : '_changeName', 'keydown .collection-name' : '_nameCheckForEnter', - 'click .cancel-create' : function( ev ){ - if( typeof this.oncancel === 'function' ){ - this.oncancel.call( this ); - } - }, + 'click .cancel-create' : '_cancelCreate', 'click .create-collection' : '_clickCreate'//, }, - // ........................................................................ header - /** expand help */ - _clickMoreHelp : function( ev ){ - this.$( '.main-help' ).addClass( 'expanded' ); - this.$( '.more-help' ).hide(); - }, - /** collapse help */ - _clickLessHelp : function( ev ){ - this.$( '.main-help' ).removeClass( 'expanded' ); - this.$( '.more-help' ).show(); - }, - - /** show an alert on the top of the interface containing message (alertClass is bootstrap's alert-*)*/ - _showAlert : function( message, alertClass ){ - alertClass = alertClass || 'alert-danger'; - this.$( '.main-help' ).hide(); - this.$( '.header .alert' ).attr( 'class', 'alert alert-dismissable' ).addClass( alertClass ).show() - .find( '.alert-message' ).html( message ); - }, - /** hide the alerts at the top */ - _hideAlert : function( message ){ - this.$( '.main-help' ).show(); - this.$( '.header .alert' ).hide(); - }, - /** toggle between showing only unpaired and split view */ _clickShowOnlyUnpaired : function( ev ){ //this.debug( 'click unpaired', ev.currentTarget ); @@ -1419,33 +1391,6 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte creator._renderFooter(); }, - /** handle a collection name change */ - _changeName : function( ev ){ - this._validationWarning( 'name', !!this._getName() ); - }, - - /** check for enter key press when in the collection name and submit */ - _nameCheckForEnter : function( ev ){ - if( ev.keyCode === 13 && !this.blocking ){ - this._clickCreate(); - } - }, - - /** get the current collection name */ - _getName : function(){ - return _.escape( this.$( '.collection-name' ).val() ); - }, - - /** attempt to create the current collection */ - _clickCreate : function( ev ){ - var name = this._getName(); - if( !name ){ - this._validationWarning( 'name' ); - } else if( !this.blocking ){ - this.createList(); - } - }, - // ------------------------------------------------------------------------ misc /** debug a dataset list */ _printList : function( list ){ @@ -1473,14 +1418,7 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte //TODO: underscore currently unnecc. bc no vars are used //TODO: better way of localizing text-nodes in long strings /** underscore template fns attached to class */ -PairedCollectionCreator.templates = PairedCollectionCreator.templates || { - - /** the skeleton */ - main : _.template([ - '
', - '
', - '', + '
', + '', + '<% _.each(dataset.nametags, function(tag){ %>', + '<%- tag %>', + '<% }); %>', + '', '' ], 'dataset' ); diff --git a/client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js b/client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js index 411bad9fcf5..ff825408d3c 100644 --- a/client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js +++ b/client/galaxy/scripts/mvc/library/library-foldertoolbar-view.js @@ -729,27 +729,34 @@ var FolderToolbarView = Backbone.View.extend({ */ addAllDatasetsFromHistory : function (){ var checked_hdas = this.modal.$el.find( '#selected_history_content' ).find( ':checked' ); - var history_dataset_ids = []; - var hdas_to_add = []; + var history_item_ids = []; // can be hda or hdca + var history_item_types = []; + var items_to_add = []; if ( checked_hdas.length < 1 ){ mod_toastr.info( 'You must select some datasets first.' ); } else { this.modal.disableButton( 'Add' ); checked_hdas.each(function(){ var hid = $( this.parentElement ).data( 'id' ); - if ( hid ) { - history_dataset_ids.push( hid ); - } + if ( hid ) { + var item_type = $( this.parentElement ).data( 'name' ); + history_item_ids.push( hid ); + history_item_types.push( item_type ); + } }); - for ( var i = history_dataset_ids.length - 1; i >= 0; i-- ) { - history_dataset_id = history_dataset_ids[i]; + for ( var i = history_item_ids.length - 1; i >= 0; i-- ) { + history_item_id = history_item_ids[i]; var folder_item = new mod_library_model.Item(); folder_item.url = Galaxy.root + 'api/folders/' + this.options.id + '/contents'; - folder_item.set( { 'from_hda_id':history_dataset_id } ); - hdas_to_add.push( folder_item ); + if (history_item_types[i] === 'collection') { + folder_item.set({'from_hdca_id': history_item_id}); + } else { + folder_item.set({'from_hda_id': history_item_id}); + } + items_to_add.push(folder_item); } - this.initChainCallControl( { length: hdas_to_add.length, action: 'adding_datasets' } ); - this.chainCallAddingHdas( hdas_to_add ); + this.initChainCallControl( { length: items_to_add.length, action: 'adding_datasets' } ); + this.chainCallAddingHdas( items_to_add ); } }, @@ -1387,9 +1394,26 @@ var FolderToolbarView = Backbone.View.extend({ 'Choose the datasets to import:', '' ].join('')); diff --git a/client/galaxy/scripts/mvc/tool/tool-form-composite.js b/client/galaxy/scripts/mvc/tool/tool-form-composite.js index 726c8a0176e..ca5783bd077 100644 --- a/client/galaxy/scripts/mvc/tool/tool-form-composite.js +++ b/client/galaxy/scripts/mvc/tool/tool-form-composite.js @@ -306,7 +306,7 @@ define([ 'utils/utils', 'utils/deferred', 'mvc/ui/ui-misc', 'mvc/form/form-view' var is_simple_input = ([ 'data_input', 'data_collection_input' ]).indexOf( step.step_type ) != -1; _.each( step.inputs, function( input ) { input.flavor = 'module'; input.hide_label = is_simple_input; } ); form = new Form( Utils.merge({ - title : '' + step.name + '' + step.description, + title : step.title, onchange : function() { _.each( self.links[ step.index ], function( link ) { self._refreshStep( link ) } ) }, inputs : step.inputs && step.inputs.length > 0 ? step.inputs : [ { type: 'hidden', name: 'No options available.', ignore: null } ] }, step ) ); diff --git a/client/galaxy/scripts/mvc/tool/tools.js b/client/galaxy/scripts/mvc/tool/tools.js index 85981234fb7..c7f878d38f1 100644 --- a/client/galaxy/scripts/mvc/tool/tools.js +++ b/client/galaxy/scripts/mvc/tool/tools.js @@ -532,10 +532,7 @@ var ToolLinkView = BaseView.extend({ var self = this; $link.find('a').on('click', function(e) { e.preventDefault(); - var form = new ToolForm.View( { id : self.model.id, version : self.model.get('version') } ); - form.deferred.execute(function() { - Galaxy.app.display( form ); - }); + Galaxy.router.push( '/', { tool_id : self.model.id, version : self.model.get('version') } ); }); } diff --git a/client/galaxy/scripts/mvc/ui/ui-select-content.js b/client/galaxy/scripts/mvc/ui/ui-select-content.js index 0d1c9112b89..f3ce3a69ec6 100644 --- a/client/galaxy/scripts/mvc/ui/ui-select-content.js +++ b/client/galaxy/scripts/mvc/ui/ui-select-content.js @@ -221,7 +221,8 @@ var View = Backbone.View.extend({ hid : item.hid, keep : item.keep, label: item.hid + ': ' + item.name, - value: item.id + value: item.id, + tags : item.tags }); self.history[ item.id + '_' + src ] = item; }); diff --git a/client/galaxy/scripts/mvc/ui/ui-select-default.js b/client/galaxy/scripts/mvc/ui/ui-select-default.js index b96f3fdd8a9..4d0671344a5 100644 --- a/client/galaxy/scripts/mvc/ui/ui-select-default.js +++ b/client/galaxy/scripts/mvc/ui/ui-select-default.js @@ -109,6 +109,11 @@ var View = Backbone.View.extend({ } }, + /** Matches a search term with a given text */ + _match: function( term, text ) { + return !term || term == '' || String( text ).toUpperCase().indexOf( term.toUpperCase() ) >= 0 + }, + /** Updates the selection options */ _changeData: function() { var self = this; @@ -125,22 +130,44 @@ var View = Backbone.View.extend({ if ( this.model.get( 'searchable' ) ) { this.data2 = []; _.each( this.data, function( option, index ) { - self.data2.push( { order: index, id: option.value, text: option.label } ); + self.data2.push( { order: index, id: option.value, text: option.label, tags: option.tags } ); }); this.$select.data( 'select2' ) && this.$select.select2( 'destroy' ); + this.matched_tags = {}; this.$select.select2({ data : self.data2, closeOnSelect : !this.model.get( 'multiple' ), multiple : this.model.get( 'multiple' ), query : function( q ) { + self.matched_tags = {}; var pagesize = self.model.get( 'pagesize' ); var results = _.filter( self.data2, function ( e ) { - return !q.term || q.term == '' || e.text.toUpperCase().indexOf( q.term.toUpperCase() ) >= 0; + var found = false; + _.each( e.tags, function( tag ) { + if ( self._match( q.term, tag ) ) { + found = self.matched_tags[ tag ] = true; + } + }); + return found || self._match( q.term, e.text ); }); q.callback({ results: results.slice( ( q.page - 1 ) * pagesize, q.page * pagesize ), more : results.length >= q.page * pagesize }); + }, + formatResult : function( result ) { + return _.escape( result.text ) + + '
' + + _.reduce( result.tags, function( memo, tag ) { + if ( self.matched_tags[ tag ] ) { + return memo + ' ' + + '
' + + _.escape( tag ) + + '
' + } + return memo; + }, '' ) + + '
'; } }); this.$( '.select2-container .select2-search input' ).off( 'blur' ); diff --git a/client/galaxy/scripts/mvc/upload/upload-ftp.js b/client/galaxy/scripts/mvc/upload/upload-ftp.js index d7eaefcd65d..4e36750f55f 100644 --- a/client/galaxy/scripts/mvc/upload/upload-ftp.js +++ b/client/galaxy/scripts/mvc/upload/upload-ftp.js @@ -106,7 +106,7 @@ define( [ 'utils/utils' ], function( Utils ) { _templateRow: function( options ) { return '' + '
' + - '' + options.path + '' + + '' + _.escape(options.path) + '' + '' + Utils.bytesToString( options.size ) + '' + '' + options.ctime + '' + ''; diff --git a/client/galaxy/scripts/mvc/user/user-preferences.js b/client/galaxy/scripts/mvc/user/user-preferences.js index 5d3e3438aec..5d90f1fa97f 100644 --- a/client/galaxy/scripts/mvc/user/user-preferences.js +++ b/client/galaxy/scripts/mvc/user/user-preferences.js @@ -1,40 +1,43 @@ /** User Preferences view */ define( [ 'mvc/form/form-view', 'mvc/ui/ui-misc' ], function( Form, Ui ) { - var View = Backbone.View.extend({ - - initialize: function() { - this.defs = { + /** Contains descriptive dictionaries describing user forms */ + var Model = Backbone.Model.extend({ + initialize: function( options ) { + options = options || {}; + options.user_id = options.user_id || Galaxy.user.id; + this.set({ + 'user_id' : options.user_id, 'information': { title : 'Manage information', description : 'Edit your email, addresses and custom parameters or change your username.', - url : 'api/users/' + Galaxy.user.id + '/information/inputs', + url : 'api/users/' + options.user_id + '/information/inputs', icon : 'fa-user' }, 'password': { title : 'Change password', description : 'Allows you to change your login credentials.', icon : 'fa-unlock-alt', - url : 'api/users/' + Galaxy.user.id + '/password/inputs', + url : 'api/users/' + options.user_id + '/password/inputs', submit_title : 'Save password', }, 'communication': { title : 'Change communication settings', description : 'Enable or disable the communication feature to chat with other users.', - url : 'api/users/' + Galaxy.user.id + '/communication/inputs', + url : 'api/users/' + options.user_id + '/communication/inputs', icon : 'fa-comments-o' }, 'permissions': { title : 'Set dataset permissions for new histories', description : 'Grant others default access to newly created histories. Changes made here will only affect histories created after these settings have been stored.', - url : 'api/users/' + Galaxy.user.id + '/permissions/inputs', + url : 'api/users/' + options.user_id + '/permissions/inputs', icon : 'fa-users', submit_title : 'Save permissions' }, 'api_key': { title : 'Manage API key', description : 'Access your current API key or create a new one.', - url : 'api/users/' + Galaxy.user.id + '/api_key/inputs', + url : 'api/users/' + options.user_id + '/api_key/inputs', icon : 'fa-key', submit_title : 'Create a new key', submit_icon : 'fa-check' @@ -42,7 +45,7 @@ define( [ 'mvc/form/form-view', 'mvc/ui/ui-misc' ], function( Form, Ui ) { 'toolbox_filters': { title : 'Manage Toolbox filters', description : 'Customize your Toolbox by displaying or omitting sets of Tools.', - url : 'api/users/' + Galaxy.user.id + '/toolbox_filters/inputs', + url : 'api/users/' + options.user_id + '/toolbox_filters/inputs', icon : 'fa-filter', submit_title : 'Save filters' }, @@ -69,7 +72,15 @@ define( [ 'mvc/form/form-view', 'mvc/ui/ui-misc' ], function( Form, Ui ) { }); } } - } + }); + } + }); + + /** View of the main user preference panel with links to individual user forms */ + var View = Backbone.View.extend({ + + initialize: function() { + this.model = new Model(); this.message = new Ui.Message(); this.setElement( '
' ); this.render(); @@ -85,93 +96,39 @@ define( [ 'mvc/form/form-view', 'mvc/ui/ui-misc' ], function( Form, Ui ) { .append( $( '

' ).append( 'You are logged in as ' + _.escape( data.email ) + '.' ) ) .append( self.$table = $( '' ).addClass( 'ui-panel-table' ) ); if( !config.use_remote_user ) { - self._link( self.defs.information ); - self._link( self.defs.password ); + self._addLink( 'information' ); + self._addLink( 'password' ); } if( config.enable_communication_server ) { - self._link( self.defs.communication ); + self._addLink( 'communication' ); } - self._link( self.defs.permissions ); - self._link( self.defs.api_key ); + self._addLink( 'permissions' ); + self._addLink( 'api_key' ); if( config.has_user_tool_filters ) { - self._link( self.defs.toolbox_filters ); + self._addLink( 'toolbox_filters' ); } if( config.enable_openid && !config.use_remote_user ) { - self._link( self.defs.openids ); + self._addLink( 'openids' ); } - self._link( self.defs.logout ); + self._addLink( 'logout' ); self.$preferences.append( self._templateFooter( data ) ); self.$el.empty().append( self.$preferences ); }); }, - _link: function( page ) { - var self = this; - var $page_item = $( this._templateRow( page ) ); - this.$table.append( $page_item ); - $page_item.find( 'a' ).on( 'click', function() { - if ( page.url ) { - $.ajax({ - url : Galaxy.root + page.url, - type : 'GET' - }).done( function( response ) { - var options = $.extend( {}, page, response ); - var form = new Form({ - title : options.title, - icon : options.icon, - inputs : options.inputs, - operations: { - 'submit': new Ui.ButtonIcon({ - tooltip : options.submit_tooltip, - title : options.submit_title || 'Save settings', - icon : options.submit_icon || 'fa-save', - onclick : function() { self._submit( form, options ) } - }), - 'back': new Ui.ButtonIcon({ - icon : 'fa-caret-left', - tooltip : 'Return to user preferences', - title : 'Preferences', - onclick : function() { form.remove(); self.$preferences.show(); } - }) - } - }); - self.$preferences.hide(); - self.$el.append( form.$el ); - }).fail( function( response ) { - self.message.update( { message: 'Failed to load resource ' + page.url + '.', status: 'danger' } ); - }) - } else { - page.onclick(); - } - }); + _addLink: function( action ) { + var options = this.model.get( action ); + var $row = $( this._templateLink( options ) ); + var $a = $row.find( 'a' ); + if ( options.onclick ) { + $a.on( 'click', function() { options.onclick() } ); + } else { + $a.attr( 'href', Galaxy.root + 'user/' + action ); + } + this.$table.append( $row ); }, - _submit: function( form, options ) { - var self = this; - $.ajax( { - url : options.url, - data : JSON.stringify(form.data.create()), - type : 'PUT', - contentType : 'application/json' - }).done( function( response ) { - var updated_values = false; - form.data.matchModel( response, function ( input, input_id ) { - form.field_list[ input_id ].value( input.value ); - updated_values = true; - }); - if ( updated_values ) { - form.message.update( { message: response.message, status: 'success' } ); - } else { - form.remove(); - self.$preferences.show(); - self.message.update( { message: response.message, status: 'success' } ); - } - }).fail( function( response ) { - form.message.update( { message: response.responseJSON.err_msg, status: 'danger' } ); - }); - }, - - _templateRow: function( options ) { + _templateLink: function( options ) { return '' + '
' + '
' + @@ -192,7 +149,69 @@ define( [ 'mvc/form/form-view', 'mvc/ui/ui-misc' ], function( Form, Ui ) { } }); + /** View of individual user forms */ + var Forms = Backbone.View.extend({ + + initialize: function( options ) { + this.model = new Model( options ); + this.page = this.model.get( options.form_id ); + this.setElement( '
' ); + this.render(); + }, + + render: function() { + var self = this; + $.ajax({ + url : Galaxy.root + this.page.url, + type : 'GET' + }).done( function( response ) { + var options = $.extend( {}, self.page, response ); + var form = new Form({ + title : options.title, + icon : options.icon, + inputs : options.inputs, + operations: { + 'submit': new Ui.ButtonIcon({ + tooltip : options.submit_tooltip, + title : options.submit_title || 'Save settings', + icon : options.submit_icon || 'fa-save', + onclick : function() { self._submit( form, options ) } + }) + } + }); + self.$el.empty().append( form.$el ); + }).fail( function( response ) { + self.$el.empty().append( new Ui.Message({ + message : 'Failed to load resource ' + self.page.url + '.', + status : 'danger', + persistent : true + }).$el ); + }); + }, + + _submit: function( form, options ) { + var self = this; + $.ajax( { + url : Galaxy.root + options.url, + data : JSON.stringify( form.data.create() ), + type : 'PUT', + contentType : 'application/json' + }).done( function( response ) { + var updated_values = false; + form.data.matchModel( response, function ( input, input_id ) { + form.field_list[ input_id ].value( input.value ); + updated_values = true; + }); + form.message.update( { message: response.message, status: 'success' } ); + }).fail( function( response ) { + window.console.log( response ); + form.message.update( { message: response.responseJSON.err_msg, status: 'danger' } ); + }); + } + }); + return { - View: View + View : View, + Forms : Forms }; }); diff --git a/client/galaxy/scripts/mvc/tool/tool-form-workflow.js b/client/galaxy/scripts/mvc/workflow/workflow-forms.js similarity index 94% rename from client/galaxy/scripts/mvc/tool/tool-form-workflow.js rename to client/galaxy/scripts/mvc/workflow/workflow-forms.js index d9ca767d433..965f70db631 100644 --- a/client/galaxy/scripts/mvc/tool/tool-form-workflow.js +++ b/client/galaxy/scripts/mvc/workflow/workflow-forms.js @@ -1,12 +1,18 @@ -/** This is the workflow tool form. */ -define( [ 'utils/utils', 'mvc/tool/tool-form-base' ], - function( Utils, ToolFormBase ) { - var View = Backbone.View.extend({ +define( [ 'utils/utils', 'mvc/form/form-view', 'mvc/tool/tool-form-base' ], function( Utils, Form, ToolFormBase ) { + + /** Default form wrapper for non-tool modules in the workflow editor. */ + var Default = Backbone.View.extend({ + initialize: function( options ) { + this.form = new Form( options ); + } + }); + + /** Tool form wrapper for the workflow editor. */ + var Tool = Backbone.View.extend({ initialize: function( options ) { var self = this; this.workflow = options.workflow; this.node = options.node; - this.setElement( '
' ); if ( this.node ) { this.post_job_actions = this.node.post_job_actions || {}; Utils.deepeach( options.inputs, function( input ) { @@ -15,7 +21,7 @@ define( [ 'utils/utils', 'mvc/tool/tool-form-base' ], input.type = 'hidden'; input.info = 'Data input \'' + input.name + '\' (' + Utils.textify( input.extensions ) + ')'; input.value = { '__class__': 'RuntimeValue' }; - } else { + } else if ( !input.fixed ) { input.collapsible_value = { '__class__': 'RuntimeValue' }; input.is_workflow = ( input.options && input.options.length == 0 ) || ( [ 'integer', 'float' ].indexOf( input.type ) != -1 ); @@ -64,7 +70,6 @@ define( [ 'utils/utils', 'mvc/tool/tool-form-base' ], }); }, })); - this.$el.append( this.form.$el ); } else { Galaxy.emit.debug('tool-form-workflow::initialize()', 'Node not found in workflow.'); } @@ -74,14 +79,6 @@ define( [ 'utils/utils', 'mvc/tool/tool-form-base' ], _makeSections: function( options ){ var inputs = options.inputs; var datatypes = options.datatypes; - inputs.push({ - label : 'Annotation / Notes', - name : '__annotation', - type : 'text', - area : true, - help : 'Add an annotation or note for this step. It will be shown with the workflow.', - value : this.node.annotation - }); var output_id = this.node.output_terminals && Object.keys( this.node.output_terminals )[ 0 ]; if ( output_id ) { inputs.push({ @@ -256,6 +253,7 @@ define( [ 'utils/utils', 'mvc/tool/tool-form-base' ], }); return { - View: View + Default: Default, + Tool: Tool }; }); diff --git a/client/galaxy/scripts/mvc/workflow/workflow-view.js b/client/galaxy/scripts/mvc/workflow/workflow-view.js index b19f51f98da..c79870999b8 100644 --- a/client/galaxy/scripts/mvc/workflow/workflow-view.js +++ b/client/galaxy/scripts/mvc/workflow/workflow-view.js @@ -6,13 +6,12 @@ define([ 'mvc/workflow/workflow-canvas', 'mvc/workflow/workflow-node', 'mvc/workflow/workflow-icons', - 'mvc/tool/tool-form-workflow', - 'mvc/form/form-view', + 'mvc/workflow/workflow-forms', 'mvc/ui/ui-misc', 'utils/async-save-text', 'libs/toastr', 'ui/editable-text' -], function( Utils, Globals, Workflow, WorkflowCanvas, Node, WorkflowIcons, ToolForm, Form, Ui, async_save_text, Toastr ){ +], function( Utils, Globals, Workflow, WorkflowCanvas, Node, WorkflowIcons, FormWrappers, Ui, async_save_text, Toastr ){ // Reset tool search to start state. function reset_tool_search( initValue ) { @@ -661,62 +660,64 @@ define([ var $container = $( '#' + cls ); if ( content && $container.find( '#' + id ).length == 0 ) { var $el = $( '
' ); - var form = null; + var form_wrapper = null; + content.node = node; + content.workflow = this.workflow; + content.datatypes = this.datatypes; content.icon = WorkflowIcons[ node.type ]; content.cls = 'ui-portlet-narrow'; - if ( node.type == 'tool' ) { - content.node = node; - content.workflow = this.workflow; - content.datatypes = this.datatypes; - form = new ToolForm.View( content ); - } else { - content.inputs.unshift({ - type : 'text', - name : '__label', - label : 'Label', - value : node.label, - help : 'Add a step label.', - onchange: function( new_label ) { - var duplicate = false; - for ( var i in self.workflow.nodes ) { - var n = self.workflow.nodes[ i ]; - if ( n.label && n.label == new_label && n.id != node.id ) { - duplicate = true; - break; - } + content.inputs.unshift({ + type : 'text', + name : '__annotation', + label : 'Annotation', + fixed : true, + value : node.annotation, + area : true, + help : 'Add an annotation or notes to this step. Annotations are available when a workflow is viewed.' + }); + content.inputs.unshift({ + type : 'text', + name : '__label', + label : 'Label', + value : node.label, + help : 'Add a step label.', + fixed : true, + onchange: function( new_label ) { + var duplicate = false; + for ( var i in self.workflow.nodes ) { + var n = self.workflow.nodes[ i ]; + if ( n.label && n.label == new_label && n.id != node.id ) { + duplicate = true; + break; } - var input_id = form.data.match( '__label' ); - var input_element = form.element_list[ input_id ]; - input_element.model.set( 'error_text', duplicate && 'Duplicate label. Please fix this before saving the workflow.' ); - form.trigger( 'change' ); + } + var input_id = form_wrapper.form.data.match( '__label' ); + var input_element = form_wrapper.form.element_list[ input_id ]; + input_element.model.set( 'error_text', duplicate && 'Duplicate label. Please fix this before saving the workflow.' ); + form_wrapper.form.trigger( 'change' ); + } + }); + content.onchange = function() { + Utils.request({ + type : 'POST', + url : Galaxy.root + 'api/workflows/build_module', + data : { + id : node.id, + type : node.type, + content_id : node.content_id, + inputs : form_wrapper.form.data.create() + }, + success : function( data ) { + node.update_field_data( data ); } }); - content.inputs.push({ - type : 'text', - name : '__annotation', - label : 'Annotation', - value : node.annotation, - area : true, - help : 'Add an annotation or notes to this step. Annotations are available when a workflow is viewed.' - }); - content.onchange = function() { - Utils.request({ - type : 'POST', - url : Galaxy.root + 'api/workflows/build_module', - data : { - id : node.id, - type : node.type, - content_id : node.content_id, - inputs : form.data.create() - }, - success : function( data ) { - node.update_field_data( data ); - } - }); - }; - form = new Form( content ); + }; + if ( node.type == 'tool' ) { + form_wrapper = new FormWrappers.Tool( content ); + } else { + form_wrapper = new FormWrappers.Default( content ); } - $el.append( form.$el ); + $el.append( form_wrapper.form.$el ); $container.append( $el ); } $( '.' + cls ).hide(); diff --git a/client/galaxy/scripts/nls/fr/locale.js b/client/galaxy/scripts/nls/fr/locale.js new file mode 100644 index 00000000000..858ea086796 --- /dev/null +++ b/client/galaxy/scripts/nls/fr/locale.js @@ -0,0 +1,331 @@ +/** fr localization */ +define({ +// ----------------------------------------------------------------------------- masthead +"Analyze Data": + "Analyse de données", +"Workflow": + "Workflow", +"Shared Data": + "Données partagées", +"Data Libraries": + "Bibliothèque de données", +"Histories": + "Historiques", +"Workflows": + "Workflows", +"Visualizations": + "Visualisations", +"Pages": + "Pages", +"Visualization": + "Visualisation", +"New Track Browser": + "Nouveau Navigateur de Tracks/Pistes", +"Saved Visualizations": + "Visualisations sauvegardés", +"Interactive Environments": + "Environnements interactifs", +"Admin": + "Admin", +"Help": + "Aide", +"Support": + "Assistance", +"Search": + "Recherche", +"Mailing Lists": + "Liste de diffusion", +"Videos": + "Vidéos", +"Wiki": + "Documentations", +"How to Cite Galaxy": + "Comment citer Galaxy", +"Interactive Tours": + "Guides interactifs", +"User": + "Utilisateur", +"Login": + "Authentification", +"Register": + "Enregistrement", +"Logged in as": + "Authentifié en tant que", +"Preferences": + "Préférences", +"Custom Builds": + "Mes génomes Builds de référence", +"Logout": + "Déconnection", +"Saved Histories": + "Historiques sauvegardés", +"Saved Datasets": + "Jeux de données sauvegardés", +"Saved Pages": + "Pages sauvegardées", +// ---------------------------------------------------------------------------- histories +// ---- history/options-menu +"History Lists": + "Tableaux des historiques", +// Saved histories is defined above. +// "Saved Histories": +// false, +"Histories Shared with Me": + "Historiques partagés avec moi", +"Current History": + "Cet Historique", +"Create New": + "Créer un nouveau", +"Copy History": + "Copier l'Historique", +"Share or Publish": + "Partager et publier", +"Show Structure": + "Montrer la structure", +"Extract Workflow": + "Extraire un Workflow", +// Delete is defined elsewhere, but is also in this menu. +// "Delete": +// false, +"Delete Permanently": + "Supprimer définitivement", +"Dataset Actions": + "Actions sur les jeux de données", +"Copy Datasets": + "Copier des jeux de données", +"Dataset Security": + "Permissions/Sécurité", +"Resume Paused Jobs": + "Reprendre les processus en pause", +"Collapse Expanded Datasets": + "Réduire les données étendus", +"Unhide Hidden Datasets": + "Afficher les données cachés", +"Delete Hidden Datasets": + "Supprimer les données cachés", +"Purge Deleted Datasets": + "Purger les données supprimer", +"Downloads": + "Télécharger", +"Export Tool Citations": + "Exporter les citations des outils", +"Export History to File": + "Exporter l'Historique dans un fichier", +"Other Actions": + "Autres actions", +"Import from File": + "Importer depuis un fichier", +"Webhooks": + "Webhooks", + +// ---- history-model +// ---- history-view +"This history is empty" : + "Cet historique est vide", +"No matching datasets found" : + "Aucunes données correspondantes n'a été trouvées", +"An error occurred while getting updates from the server" : + "Une erreur s'est produite lors de la réception des données depuis le serveur", +"Please contact a Galaxy administrator if the problem persists" : + "Veuillez contacter un administrateur de l'instance Galaxy si ce problème persiste", +//TODO: +//"An error was encountered while <% where %>" : +//false, +"search datasets" : + "Rechercher des données", +"You are currently viewing a deleted history!" : + "Vous consultez actuellement un historique supprimé!", +"You are over your disk quota" : + "Vous avez dépassé votre quota d'espace disque", +"Tool execution is on hold until your disk usage drops below your allocated quota" : + "L'exécution de l'outil est en attente tant que votre utilisation d'espace disque dépasse le quota attribué", +"All" : + "Tout", +"None" : + "Aucun", +"For all selected" : + "Pour toute la sélection", + +// // ---- history-view-edit +"Edit history tags" : + "Editer les mots-clés de l'historique", +"Edit history Annotation" : + "Editer l'annotation de l'historique", +"Click to rename history" : + "Cliquer pour renommer l'historique", +// multi operations +"Operations on multiple datasets" : + "Opérer sur plusieurs jeux de données en même temps", +"Hide datasets" : + "Cacher les jeux de données", +"Unhide datasets" : + "Afficher les jeux de données cachés", +"Delete datasets" : + "Supprimer les jeux de données", +"Undelete datasets" : + "Restaurer les jeux de données supprimés", +"Permanently delete datasets" : + "Supprimer définitivement les jeux de données", +"This will permanently remove the data in your datasets. Are you sure?" : + "Cela supprimera de manière permanente les données de votre historique. Êtes-vous certain?", + +// menu operations + + +// // ---- history-view-annotated +"Dataset" : + "Jeu de données", +"Annotation" : + "Annotation", + +// ---- history-view-edit-current +"This history is empty. Click 'Get Data' on the left tool menu to start" : + "Cet historique est vide. Cliquer sur 'Get Data' au niveau du menu d'outils à gauche pour démarrer", +"You must be logged in to create histories" : + "Vous devez être connecté pour créer un historique", +//TODO: +//"You can <% loadYourOwn %> or <% externalSource %>" : +//"Vous pouvez <% loadYourOwn %> ou <% externalSource %>", +"load your own data" : + "Charger vos propres données", +"get data from an external source" : + "Charger des données depuis une source externe", + +// these aren't in zh/ginga.po and the template doesn't localize +"Include Deleted Datasets" : + "Inclure les jeux de données supprimés", +"Include Hidden Datasets" : + "Inclure les jeux de données cachés", + + +// ---------------------------------------------------------------------------- datasets +// ---- hda-model +"Unable to purge dataset" : + "Impossible de purger le jeu de données", + +// ---- hda-base +// display button +"Cannot display datasets removed from disk" : + "Impossible de visualiser les jeux de données supprimés du disque", +"This dataset must finish uploading before it can be viewed" : + "Le jeu de données doit être totalement téléversé avant de pouvoir être visualiser", +"This dataset is not yet viewable" : + "Ce jeu de données n'est pas visualisable", +"View data" : + "Voir les données", +// download button +"Download" : + "Télécharger", +"Download dataset" : + "Télécharger le jeu de données", +"Additional files" : + "Fichiers additionnels", +// info/show_params +"View details" : + "Voir les détails", + +// dataset states +// state: new +"This is a new dataset and not all of its data are available yet" : + "Il s'agit d'un nouveau jeu de données et seule une partie des données est accessible pour le moment", +// state: noPermission +"You do not have permission to view this dataset" : + "Vous n'avez pas la permission de voir ce jeu de données", +// state: discarded +"The job creating this dataset was cancelled before completion" : + "Le processus à l'origine de ce jeu de données a été annulé prématurément", +// state: queued +"This job is waiting to run" : + "Ce calcul est en attente de traitement", +// state: upload +"This dataset is currently uploading" : + "Ce jeu de données est en cours de téléversement", +// state: setting_metadata +"Metadata is being auto-detected" : + "Les métadonnées sont auto-détectées", +// state: running +"This job is currently running" : + "Le traitement est en cours", +// state: paused +"This job is paused. Use the \"Resume Paused Jobs\" in the history menu to resume" : + "Ce traitement est en pause. Utilisez le \"Relancer les traitements en pause\" dans le menu d'historique pour le relancer", +// state: error +"An error occurred with this dataset" : + "Un erreur est survenue avec ce jeu de données", +// state: empty +"No data" : + "Aucune donnée", +// state: failed_metadata +"An error occurred setting the metadata for this dataset" : + "Une erreur est survenue pendant la récupération des métadonnées de ce jeu de données", + +// ajax error prefix +"There was an error getting the data for this dataset" : + "Il est survenu une erreur durant la récupération du contenu de ce jeu de données", + +// purged'd/del'd msg +"This dataset has been deleted and removed from disk" : + "Ce jeu de données a été supprimé et effacé du disque", +"This dataset has been deleted" : + "Ce jeu de données a été supprimé", +"This dataset has been hidden" : + "Ce jeu de données a été caché", + +"format" : + "format", +"database" : + "génome de référence", + +// ---- hda-edit +"Edit attributes" : + "Editer les attributs", +"Cannot edit attributes of datasets removed from disk" : + "Impossible d'éditer les attributs de jeux de données effacés du disque", +"Undelete dataset to edit attributes" : + "Restaurer le jeu de données pour en éditer les attributs", +"This dataset must finish uploading before it can be edited" : + "Ce jeu de données doit être entièrement téléversé avant toute modification", +"This dataset is not yet editable" : + "Ce jeu de données n'est pas encore éditable", + +"Delete" : + "Supprimer", +"Dataset is already deleted" : + "Le jeu de données est déjà supprimé", + +"View or report this error" : + "Voir ou remonter cette erreur", + +"Run this job again" : + "Exécuter ce traitement à nouveau", + +"Visualize" : + "Visualiser", +"Visualize in" : + "Visualiser via", + +"Undelete it" : + "Restaurer", +"Permanently remove it from disk" : + "Supprimer définitivement du disque", +"Unhide it" : + "Rendre visible", + +"You may be able to" : + "Vous devriez être en mesure de", +"set it manually or retry auto-detection" : + "Traitez le manuellement ou retenter la détection automatique", + +"Edit dataset tags" : + "Editer les mots-clés du jeu de données", +"Edit dataset annotation" : + "Editer les annotations du jeu de données", + + +// ---------------------------------------------------------------------------- misc. MVC +"Tags" : + "Mots-clés", +"Edit annotation" : + "Editer les annotations", + +}); diff --git a/client/galaxy/scripts/nls/ja/locale.js b/client/galaxy/scripts/nls/ja/locale.js index 18b81756da0..f23661cef4b 100644 --- a/client/galaxy/scripts/nls/ja/locale.js +++ b/client/galaxy/scripts/nls/ja/locale.js @@ -5,9 +5,9 @@ define({ // ---- history-model // ---- history-view "This history is empty" : -"ヒストリーは空です", + "ヒストリーは空です", "No matching datasets found" : -"一致するデータセットが見つかりませんでした", + "一致するデータセットが見つかりませんでした", //"An error occurred while getting updates from the server" : //false, //"Please contact a Galaxy administrator if the problem persists" : @@ -16,19 +16,19 @@ define({ //"An error was encountered while <% where %>" : //false, "Search datasets" : -"データセットを検索する", + "データセットを検索する", "You are currently viewing a deleted history!" : -"消去したヒストリーをみています。", + "消去したヒストリーをみています。", "You are over your disk quota" : -"あなたはディスククォータを超えている", + "あなたはディスククォータを超えている", //"Tool execution is on hold until your disk usage drops below your allocated quota" : //false, "All" : -"一式", + "一式", "None" : -"なし", + "なし", "For all selected" : -"各項目を", + "各項目を", // ---- history-view-edit //"Edit history tags" : @@ -36,10 +36,10 @@ define({ //"Edit history Annotation" : //false, "Click to rename history" : -"ヒストリーの名前を変更するにはクリック", + "ヒストリーの名前を変更するにはクリック", // multi operations "Operations on multiple datasets" : -"複数のデータセットに対する操作", + "複数のデータセットに対する操作", //"Hide datasets" : //false, //"Unhide datasets" : @@ -49,23 +49,21 @@ define({ //"Undelete datasets" : //false, "Permanently delete datasets" : -"永久にデータセットを削除", + "永久にデータセットを削除", "This will permanently remove the data in your datasets. Are you sure?" : -"これは永久にあなたのデータセット内のデータを削除します。本当に?", + "これは永久にあなたのデータセット内のデータを削除します。本当に?", // ---- history-view-annotated "Dataset" : -"データセット", + "データセット", //"Annotation" : //false, // ---- history-view-edit-current "This history is empty. Click 'Get Data' on the left tool menu to start" : -"ヒストリーは空です。解析をはじめるには、左パネルの 'データ取得' をクリック", -"No matching datasets found" : -"一致するデータセットが見つかりませんでした", + "ヒストリーは空です。解析をはじめるには、左パネルの 'データ取得' をクリック", "You must be logged in to create histories" : -"ヒストリーを作成するためにはログインする必要があります", + "ヒストリーを作成するためにはログインする必要があります", //TODO: //"You can <% loadYourOwn %> or <% externalSource %>" : //false, @@ -95,17 +93,17 @@ define({ //"This dataset is not yet viewable" : //false, "View data" : -"データを表示", + "データを表示", // download button "Download" : -"ダウンロード", + "ダウンロード", "Download dataset" : -"データセットをダウンロード", + "データセットをダウンロード", //"Additional files" : //false, // info/show_params "View details" : -"細部を表示", + "細部を表示", // dataset states // state: new @@ -119,7 +117,7 @@ define({ //false, // state: queued "This job is waiting to run" : -"ジョブは実行待ちです", + "ジョブは実行待ちです", // state: upload //"This dataset is currently uploading" : //false, @@ -128,16 +126,16 @@ define({ //false, // state: running "This job is currently running" : -"ジョブは実行中です", + "ジョブは実行中です", // state: paused //"This job is paused. Use the \"Resume Paused Jobs\" in the history menu to resume" : //false, // state: error "An error occurred with this dataset" : -"このジョブの実行中に発生したエラー", + "このジョブの実行中に発生したエラー", // state: empty "No data" : -"データ無し", + "データ無し", // state: failed_metadata //"An error occurred setting the metadata for this dataset" : //false, @@ -148,20 +146,20 @@ define({ // purged'd/del'd msg "This dataset has been deleted and removed from disk" : -"このデータセットは、永続的にディスクから削除されました", + "このデータセットは、永続的にディスクから削除されました", "This dataset has been deleted" : -"このデータセットは削除されました", + "このデータセットは削除されました", "This dataset has been hidden" : -"このデータセットは、非表示にされた", + "このデータセットは、非表示にされた", "format" : -"フォーマット", + "フォーマット", "database" : -"データベース", + "データベース", // ---- hda-edit "Edit attributes" : -"変数を編集する", + "変数を編集する", //"Cannot edit attributes of datasets removed from disk" : //false, //"Undelete dataset to edit attributes" : @@ -172,27 +170,27 @@ define({ //false, "Delete" : -"削除する", + "削除する", //"Dataset is already deleted" : //false, "View or report this error" : -"このエラーを届け出る", + "このエラーを届け出る", "Run this job again" : -"もう一度このジョブを実行する", + "もう一度このジョブを実行する", "Visualize" : -"可視化する", + "可視化する", //"Visualize in" : //false, "Undelete it" : -"復元する", + "復元する", "Permanently remove it from disk" : -"永久にディスクから削除", + "永久にディスクから削除", "Unhide it" : -"非表示解除する", + "非表示解除する", //"You may be able to" : //false, diff --git a/client/galaxy/scripts/nls/locale.js b/client/galaxy/scripts/nls/locale.js index c259585f9ac..9793e3068a8 100644 --- a/client/galaxy/scripts/nls/locale.js +++ b/client/galaxy/scripts/nls/locale.js @@ -1,72 +1,186 @@ /** en/main localization hash - for use with requirejs' i18n plugin */ define({ root : { - +// ----------------------------------------------------------------------------- masthead +"Analyze Data": + false, +"Workflow": + false, +"Shared Data": + false, +"Data Libraries": + false, +"Histories": + false, +"Workflows": + false, +"Visualizations": + false, +"Pages": + false, +"Visualization": + false, +"New Track Browser": + false, +"Saved Visualizations": + false, +"Interactive Environments": + false, +"Admin": + false, +"Help": + false, +"Support": + false, +"Search": + false, +"Mailing Lists": + false, +"Videos": + false, +"Wiki": + false, +"How to Cite Galaxy": + false, +"Interactive Tours": + false, +"User": + false, +"Login": + false, +"Register": + false, +"Logged in as": + false, +"Preferences": + false, +"Custom Builds": + false, +"Logout": + false, +"Saved Histories": + false, +"Saved Datasets": + false, +"Saved Pages": + false, // ---------------------------------------------------------------------------- histories +// ---- history/options-menu +"History Lists": + false, +// Saved histories is defined above. +// "Saved Histories": +// false, +"Histories Shared with Me": + false, +"Current History": + false, +"Create New": + false, +"Copy History": + false, +"Share or Publish": + false, +"Show Structure": + false, +"Extract Workflow": + false, +// Delete is defined elsewhere, but is also in this menu. +// "Delete": +// false, +"Delete Permanently": + false, +"Dataset Actions": + false, +"Copy Datasets": + false, +"Dataset Security": + false, +"Resume Paused Jobs": + false, +"Collapse Expanded Datasets": + false, +"Unhide Hidden Datasets": + false, +"Delete Hidden Datasets": + false, +"Purge Deleted Datasets": + false, +"Downloads": + false, +"Export Tool Citations": + false, +"Export History to File": + false, +"Other Actions": + false, +"Import from File": + false, +"Webhooks": + false, + // ---- history-model // ---- history-view "This history is empty" : -false, + false, "No matching datasets found" : -false, + false, "An error occurred while getting updates from the server" : -false, + false, "Please contact a Galaxy administrator if the problem persists" : -false, + false, //TODO: //"An error was encountered while <% where %>" : //false, -"Search datasets" : -false, +"search datasets" : + false, "You are currently viewing a deleted history!" : -false, + false, "You are over your disk quota" : -false, + false, "Tool execution is on hold until your disk usage drops below your allocated quota" : -false, + false, "All" : -false, + false, "None" : -false, + false, "For all selected" : -false, + false, // ---- history-view-edit "Edit history tags" : -false, + false, "Edit history Annotation" : -false, + false, "Click to rename history" : -false, + false, // multi operations "Operations on multiple datasets" : -false, + false, "Hide datasets" : -false, + false, "Unhide datasets" : -false, + false, "Delete datasets" : -false, + false, "Undelete datasets" : -false, + false, "Permanently delete datasets" : -false, + false, "This will permanently remove the data in your datasets. Are you sure?" : -false, + false, // ---- history-view-annotated "Dataset" : -false, + false, "Annotation" : false, // ---- history-view-edit-current "This history is empty. Click 'Get Data' on the left tool menu to start" : -false, -"No matching datasets found" : -false, + false, "You must be logged in to create histories" : -false, + false, //TODO: //"You can <% loadYourOwn %> or <% externalSource %>" : //false, @@ -85,138 +199,137 @@ false, // ---------------------------------------------------------------------------- datasets // ---- hda-model "Unable to purge dataset" : -false, + false, // ---- hda-base // display button "Cannot display datasets removed from disk" : -false, + false, "This dataset must finish uploading before it can be viewed" : -false, + false, "This dataset is not yet viewable" : -false, + false, "View data" : -false, + false, // download button "Download" : -false, + false, "Download dataset" : -false, + false, "Additional files" : -false, + false, // info/show_params "View details" : -false, + false, // dataset states // state: new "This is a new dataset and not all of its data are available yet" : -false, + false, // state: noPermission "You do not have permission to view this dataset" : -false, + false, // state: discarded "The job creating this dataset was cancelled before completion" : -false, + false, // state: queued "This job is waiting to run" : -false, + false, // state: upload "This dataset is currently uploading" : -false, + false, // state: setting_metadata "Metadata is being auto-detected" : -false, + false, // state: running "This job is currently running" : -false, + false, // state: paused "This job is paused. Use the \"Resume Paused Jobs\" in the history menu to resume" : -false, + false, // state: error "An error occurred with this dataset" : -false, + false, // state: empty "No data" : -false, + false, // state: failed_metadata "An error occurred setting the metadata for this dataset" : -false, + false, // ajax error prefix "There was an error getting the data for this dataset" : -false, + false, // purged'd/del'd msg "This dataset has been deleted and removed from disk" : -false, + false, "This dataset has been deleted" : -false, + false, "This dataset has been hidden" : -false, + false, "format" : -false, + false, "database" : -false, + false, // ---- hda-edit "Edit attributes" : -false, + false, "Cannot edit attributes of datasets removed from disk" : -false, + false, "Undelete dataset to edit attributes" : -false, + false, "This dataset must finish uploading before it can be edited" : -false, + false, "This dataset is not yet editable" : -false, + false, "Delete" : -false, + false, "Dataset is already deleted" : -false, + false, "View or report this error" : -false, + false, "Run this job again" : -false, + false, "Visualize" : -false, + false, "Visualize in" : -false, + false, "Undelete it" : -false, + false, "Permanently remove it from disk" : -false, + false, "Unhide it" : -false, + false, "You may be able to" : -false, + false, "set it manually or retry auto-detection" : -false, + false, "Edit dataset tags" : -false, + false, "Edit dataset annotation" : -false, + false, // ---------------------------------------------------------------------------- misc. MVC "Tags" : -false, -"Annotation" : -false, + false, "Edit annotation" : -false, + false, // ---------------------------------------------------------------------------- }, - 'ja' : true, - 'zh' : true + 'ja' : true, + 'fr' : true, + 'zh' : true }); diff --git a/client/galaxy/scripts/nls/zh/locale.js b/client/galaxy/scripts/nls/zh/locale.js index 3078c9c83f1..34282561508 100644 --- a/client/galaxy/scripts/nls/zh/locale.js +++ b/client/galaxy/scripts/nls/zh/locale.js @@ -4,9 +4,9 @@ define({ // ---- history-model // ---- history-view "This history is empty" : -"历史已空", + "历史已空", "No matching datasets found" : -"未找到匹配的数据集", + "未找到匹配的数据集", //"An error occurred while getting updates from the server" : //false, //"Please contact a Galaxy administrator if the problem persists" : @@ -15,19 +15,19 @@ define({ //"An error was encountered while <% where %>" : //false, "Search datasets" : -"搜索数据集", + "搜索数据集", "You are currently viewing a deleted history!" : -"正在查看已删除的历史", + "正在查看已删除的历史", "You are over your disk quota" : -"您已超过磁盘配额", + "您已超过磁盘配额", //"Tool execution is on hold until your disk usage drops below your allocated quota" : //false, "All" : -"皆", + "皆", "None" : -"一个也没有", + "一个也没有", "For all selected" : -"为每个选定", + "为每个选定", // ---- history-view-edit //"Edit history tags" : @@ -35,10 +35,10 @@ define({ //"Edit history Annotation" : //false, "Click to rename history" : -"单击要重命名的历史", + "单击要重命名的历史", // multi operations "Operations on multiple datasets" : -"编辑多个数据集", + "编辑多个数据集", //"Hide datasets" : //false, //"Unhide datasets" : @@ -48,23 +48,21 @@ define({ //"Undelete datasets" : //false, "Permanently delete datasets" : -"永久删除数据集", + "永久删除数据集", "This will permanently remove the data in your datasets. Are you sure?" : -"这将永久在你的数据集删除数据。你确定?", + "这将永久在你的数据集删除数据。你确定?", // ---- history-view-annotated "Dataset" : -"数据集", + "数据集", //"Annotation" : //false, // ---- history-view-edit-current "This history is empty. Click 'Get Data' on the left tool menu to start" : -"历史已空,请单击左边窗格中‘获取数据’", -"No matching datasets found" : -"没有发现", + "历史已空,请单击左边窗格中‘获取数据’", "You must be logged in to create histories" : -"你必须登录后才能创建历史", + "你必须登录后才能创建历史", //TODO: //"You can <% loadYourOwn %> or <% externalSource %>" : //false, @@ -88,17 +86,17 @@ define({ //"This dataset is not yet viewable" : //false, "View data" : -"数据", + "数据", // download button "Download" : -"下载", + "下载", "Download dataset" : -"下载数据集", + "下载数据集", //"Additional files" : //false, // info/show_params "View details" : -"查看详情", + "查看详情", // dataset states // state: new @@ -112,7 +110,7 @@ define({ //false, // state: queued "This job is waiting to run" : -"等待运行的进程", + "等待运行的进程", // state: upload //"This dataset is currently uploading" : //false, @@ -121,16 +119,16 @@ define({ //false, // state: running "This job is currently running" : -"正在运行的进程", + "正在运行的进程", // state: paused //"This job is paused. Use the \"Resume Paused Jobs\" in the history menu to resume" : //false, // state: error "An error occurred with this dataset" : -"进程运行时出错", + "进程运行时出错", // state: empty "No data" : -"没有数据", + "没有数据", // state: failed_metadata //"An error occurred setting the metadata for this dataset" : //false, @@ -143,18 +141,18 @@ define({ //"This dataset has been deleted and removed from disk" : //false, "This dataset has been deleted" : -"此数据集已被删除", + "此数据集已被删除", "This dataset has been hidden" : -"此数据集已隐藏", + "此数据集已隐藏", "format" : -"格式", + "格式", "database" : -"数据库", + "数据库", // ---- hda-edit "Edit attributes" : -"编辑属性", + "编辑属性", //"Cannot edit attributes of datasets removed from disk" : //false, //"Undelete dataset to edit attributes" : @@ -165,27 +163,27 @@ define({ //false, "Delete" : -"删除", + "删除", //"Dataset is already deleted" : //false, "View or report this error" : -"报告错误", + "报告错误", "Run this job again" : -"重新运行", + "重新运行", "Visualize" : -"图形", + "图形", //"Visualize in" : //false, "Undelete it" : -"反删除", + "反删除", "Permanently remove it from disk" : -"从磁盘中永久删除", + "从磁盘中永久删除", "Unhide it" : -"取消隐藏", + "取消隐藏", //"You may be able to" : //false, diff --git a/client/galaxy/style/less/history.less b/client/galaxy/style/less/history.less index dbdd15e784c..01bcf5f3843 100644 --- a/client/galaxy/style/less/history.less +++ b/client/galaxy/style/less/history.less @@ -221,6 +221,13 @@ } } } + span.nametags { + span.label { + display: inline-block; + margin-right: 2px; + text-decoration: none; + } + } } } diff --git a/client/galaxy/style/less/ui.less b/client/galaxy/style/less/ui.less index e702158c942..95f5a4d4d38 100644 --- a/client/galaxy/style/less/ui.less +++ b/client/galaxy/style/less/ui.less @@ -68,6 +68,11 @@ font-weight: bold; } +.ui-tags { + word-wrap: break-word; + padding-right: 25px; +} + .ui-message { padding: 2px 10px 2px 10px; margin-top: @ui-margin-vertical-large; diff --git a/config/datatypes_conf.xml.sample b/config/datatypes_conf.xml.sample index 2bd89eacc75..6670935dc92 100644 --- a/config/datatypes_conf.xml.sample +++ b/config/datatypes_conf.xml.sample @@ -218,6 +218,7 @@ + @@ -235,6 +236,8 @@ + + @@ -479,7 +482,7 @@ - + @@ -597,6 +600,10 @@ + + + + diff --git a/config/dependency_resolvers_conf.xml.sample b/config/dependency_resolvers_conf.xml.sample index 243fff0cdc8..cbc78951db7 100644 --- a/config/dependency_resolvers_conf.xml.sample +++ b/config/dependency_resolvers_conf.xml.sample @@ -1,28 +1,32 @@ - + - + - + + + + - - + - + - \ No newline at end of file + --> + diff --git a/config/galaxy.ini.sample b/config/galaxy.ini.sample index e9966226889..c201ffc8818 100644 --- a/config/galaxy.ini.sample +++ b/config/galaxy.ini.sample @@ -355,6 +355,21 @@ paste.app_factory = galaxy.web.buildapp:app_factory # separated list. #interactive_environment_plugins_directory = +# To run interactive environment containers in Docker Swarm mode (on an +# existing swarm), set this option to True and set `docker_connect_port` in the +# IE plugin config (ini) file(s) of any IE plugins you have enabled and ensure +# that you are not using any `docker run`-specific options in your plugins' +# `command_inject` options (swarm mode services run using `docker service +# create`, which has a different and more limited set of options). This option +# can be overridden on a per-plugin basis by using the `swarm_mode` option in +# the plugin's ini config file. +#interactive_environment_swarm_mode = False + +# Galaxy can run a "swarm manager" service that will monitor utilization of the +# swarm and provision/deprovision worker nodes as necessary. The service has +# its own configuration file. +#swarm_manager_config_file = config/swarm_manager_conf.yml + # Interactive tour directory: where to store interactive tour definition files. # Galaxy ships with several basic interface tours enabled, though a different # directory with custom tours can be specified here. The path is relative to the @@ -1191,7 +1206,7 @@ use_interactive = True # walltime limits but did fail quickly (either while queueing or running). The # commented out default below results in no default job resubmission condition, # failing jobs are just failed outright. -#default_job_resubmission_condition = +#default_job_resubmission_condition = # In multiprocess configurations, notification between processes about new jobs # must be done via the database. In single process configurations, this can be diff --git a/config/plugins/interactive_environments/bam_iobio/config/bam_iobio.ini.sample b/config/plugins/interactive_environments/bam_iobio/config/bam_iobio.ini.sample index d6ff35d95bb..8b8fd9b41f8 100644 --- a/config/plugins/interactive_environments/bam_iobio/config/bam_iobio.ini.sample +++ b/config/plugins/interactive_environments/bam_iobio/config/bam_iobio.ini.sample @@ -41,3 +41,15 @@ image = qiaoy/iobio-bundle.bam-iobio:1.0-ondemand # share data between the IE and Galaxy. #docker_galaxy_temp_dir = None +# If your Docker container exposes more then one port, Galaxy needs to know to +# which ports it needs to connect. With this option you can specify the port number +# inside your container to which Galaxy should connect the UI. +#docker_connect_port = None + +# To run containers in Docker Swarm mode on (an existing swarm), set the +# following option to True *and*: +# - set docker_connect_port above. For qiaoy/iobio-bundle.bam-iobio the port +# should most likely be 8000. +# - If command_inject is uncommented and includes `--sig-proxy`, that option should +# be removed. +#swarm_mode = False diff --git a/config/plugins/interactive_environments/bam_iobio/static/js/bam_iobio.js b/config/plugins/interactive_environments/bam_iobio/static/js/bam_iobio.js index 395904e329b..7b019f63630 100644 --- a/config/plugins/interactive_environments/bam_iobio/static/js/bam_iobio.js +++ b/config/plugins/interactive_environments/bam_iobio/static/js/bam_iobio.js @@ -22,12 +22,10 @@ function message_failed_connection(){ * */ function load_notebook(notebook_access_url){ - $( document ).ready(function() { - // Test notebook_login_url for accessibility, executing the login+load function whenever - // we've successfully connected to the IE. - test_ie_availability(notebook_access_url, function(){ - _handle_notebook_loading(notebook_access_url); - }); + // Test notebook_login_url for accessibility, executing the login+load function whenever + // we've successfully connected to the IE. + test_ie_availability(notebook_access_url, function(){ + _handle_notebook_loading(notebook_access_url); }); } diff --git a/config/plugins/interactive_environments/bam_iobio/templates/bam_iobio.mako b/config/plugins/interactive_environments/bam_iobio/templates/bam_iobio.mako index 8f18630074e..97eb4b78d25 100644 --- a/config/plugins/interactive_environments/bam_iobio/templates/bam_iobio.mako +++ b/config/plugins/interactive_environments/bam_iobio/templates/bam_iobio.mako @@ -46,7 +46,9 @@ root = h.url_for( '/' ) var startup = function(){ // Load notebook requirejs(['interactive_environments', 'plugin/bam_iobio'], function(){ - load_notebook(notebook_access_url); + load_when_ready(ie_readiness_url, function(){ + load_notebook(notebook_access_url); + }); }); }; diff --git a/config/plugins/interactive_environments/common/templates/ie.mako b/config/plugins/interactive_environments/common/templates/ie.mako index fac6366e50d..338ccc7e263 100644 --- a/config/plugins/interactive_environments/common/templates/ie.mako +++ b/config/plugins/interactive_environments/common/templates/ie.mako @@ -9,6 +9,7 @@ ie_password = '${ ie_request.notebook_pw }'; var galaxy_root = '${ ie_request.attr.root }'; var app_root = '${ ie_request.attr.app_root }'; +var ie_readiness_url = '${ ie_request.url_template("${PROXY_PREFIX}/interactive_environments/ready") }'; diff --git a/config/plugins/interactive_environments/ethercalc/config/ethercalc.ini.sample b/config/plugins/interactive_environments/ethercalc/config/ethercalc.ini.sample new file mode 100644 index 00000000000..63a1a2648c9 --- /dev/null +++ b/config/plugins/interactive_environments/ethercalc/config/ethercalc.ini.sample @@ -0,0 +1,44 @@ +[main] +# Unused + +[docker] +# Command to launch docker container. For example `sudo docker` or `docker-lxc`. +# If you need to use a command like `sg` you can do that here, just be sure to +# wrap all of the docker portion in single quotes. E.g. `sg 'docker' 'docker {docker_args}'` +# +# It is recommended that you use command_inject if you need to inject +# additional parameters. This command string is re-used for a `docker inspect` +# command and will likely cause errors if it is extensively modified, past the +# usual group/sudo changes. +#command = docker {docker_args} + +# The docker image name that should be started. +image = shiltemann/ethercalc-galaxy-ie:17.05 + +# Additional arguments that are passed to the `docker run` command. +#command_inject = --sig-proxy=true -e DEBUG=false + +# URL to access the Galaxy API with from the spawn Docker containter, if empty +# this falls back to galaxy.ini's galaxy_infrastructure_url and finally to the +# Docker host of the spawned container if that is also not set. +#galaxy_url = + +# The Docker hostname. It can be useful to run the Docker daemon on a different +# host than Galaxy. +#docker_hostname = localhost + +# Try to set the tempdirectory to world execute - this can fix the issue +# where 'sudo docker' is not able to mount the folder otherwise. +# "finalize namespace chdir to /import permission denied" +#wx_tempdir = False + +# Overwride the IE tempdirectory. This can be useful if you regular tempdir is +# located on an NFS share, which does not work well as Docker volume. In this case +# you can have a shared sshfs share which you can use as temporary directory to +# share data between the IE and Galaxy. +#docker_galaxy_temp_dir = None + +# If your Docker container exposes more then one port, Galaxy needs to know to +# which ports it needs to connect. With this option you can specify the port number +# inside your container to which Galaxy should connect the UI. +docker_connect_port = 80 diff --git a/config/plugins/interactive_environments/ethercalc/config/ethercalc.xml b/config/plugins/interactive_environments/ethercalc/config/ethercalc.xml new file mode 100644 index 00000000000..7d6091c9cfc --- /dev/null +++ b/config/plugins/interactive_environments/ethercalc/config/ethercalc.xml @@ -0,0 +1,16 @@ + + + + + + HistoryDatasetAssociation + tabular.Tabular + tabular.CSV + dataset_id + + + + dataset_id + + ethercalc.mako + diff --git a/config/plugins/interactive_environments/ethercalc/static/js/ethercalc.js b/config/plugins/interactive_environments/ethercalc/static/js/ethercalc.js new file mode 100644 index 00000000000..5a6a060f14d --- /dev/null +++ b/config/plugins/interactive_environments/ethercalc/static/js/ethercalc.js @@ -0,0 +1,43 @@ +function load_notebook(url){ + $( document ).ready(function() { + test_ie_availability(url, function(){ + append_notebook(url) + }); + }); +} + +function keep_alive(notebook_access_url){ + /** + * This is needed to keep the container alive. If the user leaves this site + * this function is not constantly pinging the container, the container will + * terminate itself. + */ + + var request_count = 0; + interval = setInterval(function(){ + $.ajax({ + url: notebook_access_url, + xhrFields: { + withCredentials: true + }, + type: "GET", + timeout: 500, + success: function(){ + console.log("Connected to IE, returning"); + }, + 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} + ); + } + } + }); + }, 10000); +} diff --git a/config/plugins/interactive_environments/ethercalc/templates/ethercalc.mako b/config/plugins/interactive_environments/ethercalc/templates/ethercalc.mako new file mode 100644 index 00000000000..2a325b99d88 --- /dev/null +++ b/config/plugins/interactive_environments/ethercalc/templates/ethercalc.mako @@ -0,0 +1,40 @@ +<%namespace name="ie" file="ie.mako" /> +<% +# Sets ID and sets up a lot of other variables +ie_request.load_deploy_config() + + +# Launch the IE. This builds and runs the docker command in the background. +ie_request.launch( + env_override={ + 'dataset_hid': hda.hid + } +) + +# Only once the container is launched can we template our URLs. The ie_request +# doesn't have all of the information needed until the container is running. +url = ie_request.url_template('${PROXY_URL}/ethercalc/') +%> + + +${ ie.load_default_js() } + + + +
+
+ + diff --git a/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample b/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample index 89797badfa6..d35bcbc728e 100644 --- a/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample +++ b/config/plugins/interactive_environments/jupyter/config/allowed_images.yml.sample @@ -6,7 +6,7 @@ # appropriate `apt-get/pip install` statements. --- - - image: bgruening/docker-jupyter-notebook:16.01 + image: bgruening/docker-jupyter-notebook:16.01.1 description: | The Jupyter notebook is the next iteration of IPython, allowing analysis in many different languages. This image features the Python, diff --git a/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample b/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample index ad73a20bb85..e9bf4b4aa15 100644 --- a/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample +++ b/config/plugins/interactive_environments/jupyter/config/jupyter.ini.sample @@ -18,7 +18,7 @@ # The image argument was moved to "allowed_images.yml.sample" # Additional arguments that are passed to the `docker run` command. -command_inject = --sig-proxy=true -e DEBUG=false -e DEFAULT_CONTAINER_RUNTIME=120 +#command_inject = --sig-proxy=true -e DEBUG=false -e DEFAULT_CONTAINER_RUNTIME=120 # URL to access the Galaxy API with from the spawn Docker containter, if empty # this falls back to galaxy.ini's galaxy_infrastructure_url and finally to the @@ -43,4 +43,12 @@ command_inject = --sig-proxy=true -e DEBUG=false -e DEFAULT_CONTAINER_RUNTIME=12 # If your Docker container exposes more then one port, Galaxy needs to know to # which ports it needs to connect. With this option you can specify the port number # inside your container to which Galaxy should connect the UI. -# docker_connect_port = None +#docker_connect_port = None + +# To run containers in Docker Swarm mode on (an existing swarm), set the +# following option to True *and*: +# - set docker_connect_port above. For Jupyter the # port should most likely be +# 8888. +# - If command_inject is uncommented and includes `--sig-proxy`, that option should +# be removed. +#swarm_mode = False diff --git a/config/plugins/interactive_environments/jupyter/static/js/jupyter.js b/config/plugins/interactive_environments/jupyter/static/js/jupyter.js index 3b0ca53e51e..0e717c796b0 100644 --- a/config/plugins/interactive_environments/jupyter/static/js/jupyter.js +++ b/config/plugins/interactive_environments/jupyter/static/js/jupyter.js @@ -34,12 +34,10 @@ function message_no_auth(){ * */ function load_notebook(password, notebook_login_url, notebook_access_url){ - $( document ).ready(function() { - // Test notebook_login_url for accessibility, executing the login+load function whenever - // we've successfully connected to the IE. - test_ie_availability(notebook_login_url, function(){ - _handle_notebook_loading(password, notebook_login_url, notebook_access_url); - }); + // Test notebook_login_url for accessibility, executing the login+load function whenever + // we've successfully connected to the IE. + test_ie_availability(notebook_login_url, function(){ + _handle_notebook_loading(password, notebook_login_url, notebook_access_url); }); } diff --git a/config/plugins/interactive_environments/jupyter/templates/jupyter.mako b/config/plugins/interactive_environments/jupyter/templates/jupyter.mako index 69bf37fc454..8f8490f5367 100644 --- a/config/plugins/interactive_environments/jupyter/templates/jupyter.mako +++ b/config/plugins/interactive_environments/jupyter/templates/jupyter.mako @@ -60,7 +60,9 @@ requirejs(['interactive_environments', 'plugin/jupyter'], function(){ // Load notebook requirejs(['interactive_environments', 'plugin/jupyter'], function(){ - load_notebook(ie_password, notebook_login_url, notebook_access_url); + load_when_ready(ie_readiness_url, function(){ + load_notebook(ie_password, notebook_login_url, notebook_access_url); + }); }); diff --git a/config/plugins/interactive_environments/neo/config/neo.ini.sample b/config/plugins/interactive_environments/neo/config/neo.ini.sample index 27411474293..4027edc1e4c 100644 --- a/config/plugins/interactive_environments/neo/config/neo.ini.sample +++ b/config/plugins/interactive_environments/neo/config/neo.ini.sample @@ -40,3 +40,16 @@ command_inject = --sig-proxy=true -e DEBUG=false -e DEFAULT_CONTAINER_RUNTIME=12 # you can have a shared sshfs share which you can use as temporary directory to # share data between the IE and Galaxy. #docker_galaxy_temp_dir = None + +# If your Docker container exposes more then one port, Galaxy needs to know to +# which ports it needs to connect. With this option you can specify the port number +# inside your container to which Galaxy should connect the UI. +#docker_connect_port = None + +# To run containers in Docker Swarm mode on (an existing swarm), set the +# following option to True *and*: +# - set docker_connect_port above. For thoba/neo4j_galaxy_ie the port +# should most likely be 7474. +# - If command_inject is uncommented and includes `--sig-proxy`, that option should +# be removed. +#swarm_mode = False diff --git a/config/plugins/interactive_environments/neo/static/js/neo.js b/config/plugins/interactive_environments/neo/static/js/neo.js index 068d68b6515..f1af1254819 100644 --- a/config/plugins/interactive_environments/neo/static/js/neo.js +++ b/config/plugins/interactive_environments/neo/static/js/neo.js @@ -1,12 +1,9 @@ // Load an interactive environment (IE) from a remote URL // @param {String} notebook_access_url: the URL embeded in the page and loaded function load_notebook(notebook_access_url){ - // When the page has completely loaded... - $( document ).ready(function() { - // Test if we can access the GIE, and if so, execute the function - // to load the GIE for the user. - test_ie_availability(notebook_access_url, function(){ - append_notebook(notebook_access_url); - }); + // Test if we can access the GIE, and if so, execute the function + // to load the GIE for the user. + test_ie_availability(notebook_access_url, function(){ + append_notebook(notebook_access_url); }); } diff --git a/config/plugins/interactive_environments/neo/templates/neo.mako b/config/plugins/interactive_environments/neo/templates/neo.mako index b241b9dae87..ab080fde489 100644 --- a/config/plugins/interactive_environments/neo/templates/neo.mako +++ b/config/plugins/interactive_environments/neo/templates/neo.mako @@ -33,7 +33,9 @@ requirejs(['interactive_environments', 'plugin/neo'], function () { - load_notebook(url); + load_when_ready(ie_readiness_url, function(){ + load_notebook(url); + }); }); diff --git a/config/plugins/interactive_environments/phinch/config/phinch.ini.sample b/config/plugins/interactive_environments/phinch/config/phinch.ini.sample index be08cb60848..c9dc8afba7c 100644 --- a/config/plugins/interactive_environments/phinch/config/phinch.ini.sample +++ b/config/plugins/interactive_environments/phinch/config/phinch.ini.sample @@ -19,3 +19,16 @@ image = shiltemann/docker-phinch-galaxy:16.04 # The Docker hostname. It can be useful to run the Docker daemon on a different # host than Galaxy. #docker_hostname = localhost + +# If your Docker container exposes more then one port, Galaxy needs to know to +# which ports it needs to connect. With this option you can specify the port number +# inside your container to which Galaxy should connect the UI. +#docker_connect_port = None + +# To run containers in Docker Swarm mode on (an existing swarm), set the +# following option to True *and*: +# - set docker_connect_port above. For shiltemann/docker-phinch-galaxy the port +# should most likely be 80. +# - If command_inject is uncommented and includes `--sig-proxy`, that option should +# be removed. +#swarm_mode = False diff --git a/config/plugins/interactive_environments/phinch/static/js/phinch.js b/config/plugins/interactive_environments/phinch/static/js/phinch.js index 1b4c993e554..e750943f96d 100644 --- a/config/plugins/interactive_environments/phinch/static/js/phinch.js +++ b/config/plugins/interactive_environments/phinch/static/js/phinch.js @@ -1,8 +1,6 @@ function load_notebook(url){ - $( document ).ready(function() { - test_ie_availability(url, function(){ - append_notebook(url) - }); + test_ie_availability(url, function(){ + append_notebook(url) }); } diff --git a/config/plugins/interactive_environments/phinch/templates/phinch.mako b/config/plugins/interactive_environments/phinch/templates/phinch.mako index c446bf7d6e5..54cd9aa5503 100644 --- a/config/plugins/interactive_environments/phinch/templates/phinch.mako +++ b/config/plugins/interactive_environments/phinch/templates/phinch.mako @@ -36,7 +36,9 @@ requirejs(['interactive_environments', 'plugin/phinch'], function(){ // Load notebook requirejs(['interactive_environments', 'plugin/phinch'], function(){ - load_notebook(url); + load_when_ready(ie_readiness_url, function(){ + load_notebook(url); + }); }); diff --git a/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample b/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample index ac15696936d..0f2b3fa14bb 100644 --- a/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample +++ b/config/plugins/interactive_environments/rstudio/config/rstudio.ini.sample @@ -41,3 +41,16 @@ password_auth = True # you can have a shared sshfs share which you can use as temporary directory to # share data between the IE and Galaxy. #docker_galaxy_temp_dir = None + +# If your Docker container exposes more then one port, Galaxy needs to know to +# which ports it needs to connect. With this option you can specify the port number +# inside your container to which Galaxy should connect the UI. +#docker_connect_port = None + +# To run containers in Docker Swarm mode on (an existing swarm), set the +# following option to True *and*: +# - set docker_connect_port above. For erasche/docker-rstudio-notebook the port +# should most likely be 80. +# - If command_inject is uncommented and includes `--sig-proxy`, that option should +# be removed. +#swarm_mode = False diff --git a/config/plugins/interactive_environments/rstudio/static/js/rstudio.js b/config/plugins/interactive_environments/rstudio/static/js/rstudio.js index cc0b62ee7a1..38764d84567 100644 --- a/config/plugins/interactive_environments/rstudio/static/js/rstudio.js +++ b/config/plugins/interactive_environments/rstudio/static/js/rstudio.js @@ -15,58 +15,56 @@ function message_failed_connection(){ * */ function load_notebook(notebook_login_url, notebook_access_url, notebook_pubkey_url, username){ - $( document ).ready(function() { - // Test notebook_login_url for accessibility, executing the login+load function whenever - // we've successfully connected to the IE. - test_ie_availability(notebook_pubkey_url, function(){ - var payload = username + "\n" + ie_password; - $.ajax({ - type: 'GET', - url: notebook_pubkey_url, - xhrFields: { + // Test notebook_login_url for accessibility, executing the login+load function whenever + // we've successfully connected to the IE. + test_ie_availability(notebook_pubkey_url, function(){ + var payload = username + "\n" + ie_password; + $.ajax({ + type: 'GET', + url: notebook_pubkey_url, + xhrFields: { + withCredentials: true + }, + success: function(response_text){ + var chunks = response_text.split(':', 2); + var exp = chunks[0]; + var mod = chunks[1]; + console.log("Found " + exp +" and " + mod); + var rsa = new RSAKey(); + rsa.setPublic(mod, exp); + console.log("Encrypting '" + username + "', '" + ie_password + "'"); + var enc_hex = rsa.encrypt(payload); + var encrypted = hex2b64(enc_hex); + console.log("E: " + encrypted); + + // Now we can login + $.ajax({ + type: "POST", + // to the Login URL + url: notebook_login_url, + // With our password + data: { + 'v': encrypted, + 'persist': 1, + 'clientPath': '/rstudio/auth-sign-in', + 'appUri': '', + }, + contentType: "application/x-www-form-urlencoded", + xhrFields: { withCredentials: true - }, - success: function(response_text){ - var chunks = response_text.split(':', 2); - var exp = chunks[0]; - var mod = chunks[1]; - console.log("Found " + exp +" and " + mod); - var rsa = new RSAKey(); - rsa.setPublic(mod, exp); - console.log("Encrypting '" + username + "', '" + ie_password + "'"); - var enc_hex = rsa.encrypt(payload); - var encrypted = hex2b64(enc_hex); - console.log("E: " + encrypted); - - // Now we can login - $.ajax({ - type: "POST", - // to the Login URL - url: notebook_login_url, - // With our password - data: { - 'v': encrypted, - 'persist': 1, - 'clientPath': '/rstudio/auth-sign-in', - 'appUri': '', - }, - contentType: "application/x-www-form-urlencoded", - xhrFields: { - withCredentials: true - }, - // If that is successful, load the notebook - success: function(){ - append_notebook(notebook_access_url); - }, - error: function(jqxhr, status, error){ - message_failed_connection(); - // Do we want to try and load the notebook anyway? Just in case? - append_notebook(notebook_access_url); - } - }); - } - }); - + }, + // If that is successful, load the notebook + success: function(){ + append_notebook(notebook_access_url); + }, + error: function(jqxhr, status, error){ + message_failed_connection(); + // Do we want to try and load the notebook anyway? Just in case? + append_notebook(notebook_access_url); + } + }); + } }); + }); } diff --git a/config/plugins/interactive_environments/rstudio/templates/rstudio.mako b/config/plugins/interactive_environments/rstudio/templates/rstudio.mako index fdb99cde32d..c9b472c6f98 100644 --- a/config/plugins/interactive_environments/rstudio/templates/rstudio.mako +++ b/config/plugins/interactive_environments/rstudio/templates/rstudio.mako @@ -64,7 +64,9 @@ requirejs([ 'crypto/base64', 'plugin/rstudio' ], function(){ - load_notebook(notebook_login_url, notebook_access_url, notebook_pubkey_url, "${ USERNAME }"); + load_when_ready(ie_readiness_url, function(){ + load_notebook(notebook_login_url, notebook_access_url, notebook_pubkey_url, "${ USERNAME }"); + }); });
diff --git a/config/plugins/visualizations/charts/static/repository/visualizations/cytoscape/viewer/config.js b/config/plugins/visualizations/charts/static/repository/visualizations/cytoscape/viewer/config.js index 3831f44a69b..366b044a81c 100644 --- a/config/plugins/visualizations/charts/static/repository/visualizations/cytoscape/viewer/config.js +++ b/config/plugins/visualizations/charts/static/repository/visualizations/cytoscape/viewer/config.js @@ -65,7 +65,6 @@ define( [], function() { { label : 'Incomers', value : 'incomers' }, { label : 'Roots', value : 'roots' }, { label : 'Leaves', value : 'leaves' }, - { label : 'None', value : '' } ] }, choose_red : { diff --git a/config/plugins/webhooks/demo/search/config/searchover.yaml b/config/plugins/webhooks/demo/search/config/searchover.yaml new file mode 100644 index 00000000000..787c4dc8dc3 --- /dev/null +++ b/config/plugins/webhooks/demo/search/config/searchover.yaml @@ -0,0 +1,22 @@ +name: searchover +type: + - masthead +activate: true + +icon: fa-search +tooltip: Click to activate search and press Ctrl + Alt + q to open the overlay + +function: > + $.getJSON("/api/webhooks", function( data ) { + for( var item in data ) { + var webhook = data[item]; + if( webhook.name === "searchover" ) { + if( webhook.script && !window.static_search ) { + $( '