commit/galaxy-central: 4 new changesets
4 new commits in galaxy-central: https://bitbucket.org/galaxy/galaxy-central/commits/f535ef20718d/ Changeset: f535ef20718d User: carlfeberhard Date: 2014-09-12 18:23:19 Summary: Client build system: (1st step) duplicate static/scripts at client/scripts (w/o packed), add npm package.json file w/ grunt-contrib-copy dependency, add GruntFile.js w/ single task: copy client/scripts to static/scripts Affected #: 164 files diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/GruntFile.js --- /dev/null +++ b/client/GruntFile.js @@ -0,0 +1,21 @@ +module.exports = function(grunt) { + + // Project configuration. + grunt.initConfig({ + pkg: grunt.file.readJSON('package.json'), + + copy: { + main: { + expand: true, + cwd: 'scripts/', + src: '**', + dest: '../static/scripts/' + } + } + + }); + + grunt.loadNpmTasks('grunt-contrib-copy'); + + grunt.registerTask('default', ['copy']); +}; diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/package.json --- /dev/null +++ b/client/package.json @@ -0,0 +1,11 @@ +{ + "name": "galaxy-client", + "version": "0.1.0", + "description": "Galaxy client application build system", + "keywords": [ + "galaxy" + ], + "devDependencies": { + "grunt-contrib-copy": "^0.5.0" + } +} diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/scripts/base.js --- /dev/null +++ b/client/scripts/base.js @@ -0,0 +1,15 @@ +define( ["libs/backbone/backbone"], function( Backbone ) { + + var Base = function() { + if( this.initialize ) { + this.initialize.apply(this, arguments); + } + }; + Base.extend = Backbone.Model.extend; + + return { + Base: Base, + Backbone: Backbone + }; + +}); \ No newline at end of file diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/scripts/galaxy-app-base.js --- /dev/null +++ b/client/scripts/galaxy-app-base.js @@ -0,0 +1,160 @@ +define([ + 'mvc/user/user-model', + 'utils/metrics-logger', + 'utils/add-logging', + 'utils/localization', + 'bootstrapped-data' +], function( userModel, metricsLogger, addLogging, localize, bootstrapped ){ +// ============================================================================ +/** Base galaxy client-side application. + * Iniitializes: + * logger : the logger/metrics-logger + * localize : the string localizer + * config : the current configuration (any k/v in + * universe_wsgi.ini available from the configuration API) + * user : the current user (as a mvc/user/user-model) + */ +function GalaxyApp( options ){ + var self = this; + return self._init( options || {} ); +} + +// add logging shortcuts for this object +addLogging( GalaxyApp, 'GalaxyApp' ); + +/** default options */ +GalaxyApp.prototype.defaultOptions = { + /** monkey patch attributes from existing window.Galaxy object? */ + patchExisting : true, + /** root url of this app */ + // move to self.root? + root : '/' +}; + +/** initalize options and sub-components */ +GalaxyApp.prototype._init = function init( options ){ + var self = this; + _.extend( self, Backbone.Events ); + + self._processOptions( options ); + self.debug( 'GalaxyApp.options: ', self.options ); + + self._patchGalaxy( window.Galaxy ); + + self._initLogger( options.loggerOptions || {} ); + self.debug( 'GalaxyApp.logger: ', self.logger ); + + self._initLocale(); + self.debug( 'GalaxyApp.localize: ', self.localize ); + + self.config = options.config || bootstrapped.config || {}; + self.debug( 'GalaxyApp.config: ', self.config ); + + self._initUser( options.user || bootstrapped.user || {} ); + self.debug( 'GalaxyApp.user: ', self.user ); + + //TODO: temp + self.trigger( 'ready', self ); + //if( typeof options.onload === 'function' ){ + // options.onload(); + //} + + self._setUpListeners(); + + return self; +}; + +/** add an option from options if the key matches an option in defaultOptions */ +GalaxyApp.prototype._processOptions = function _processOptions( options ){ + var self = this, + defaults = self.defaultOptions; + self.debug( '_processOptions: ', options ); + + self.options = {}; + for( var k in defaults ){ + if( defaults.hasOwnProperty( k ) ){ + self.options[ k ] = ( options.hasOwnProperty( k ) )?( options[ k ] ):( defaults[ k ] ); + } + } + return self; +}; + +/** add an option from options if the key matches an option in defaultOptions */ +GalaxyApp.prototype._patchGalaxy = function _processOptions( patchWith ){ + var self = this; + // in case req or plain script tag order has created a prev. version of the Galaxy obj... + if( self.options.patchExisting && patchWith ){ + self.debug( 'found existing Galaxy object:', patchWith ); + // ...(for now) monkey patch any added attributes that the previous Galaxy may have had + //TODO: move those attributes to more formal assignment in GalaxyApp + for( var k in patchWith ){ + if( patchWith.hasOwnProperty( k ) ){ + self.debug( '\t patching in ' + k + ' to Galaxy' ); + self[ k ] = patchWith[ k ]; + } + } + } +}; + +/** set up the metrics logger (utils/metrics-logger) and pass loggerOptions */ +GalaxyApp.prototype._initLogger = function _initLogger( loggerOptions ){ + var self = this; + self.debug( '_initLogger:', loggerOptions ); + self.logger = new metricsLogger.MetricsLogger( loggerOptions ); + return self; +}; + +/** add the localize fn to this object and the window namespace (as '_l') */ +GalaxyApp.prototype._initLocale = function _initLocale( options ){ + var self = this; + self.debug( '_initLocale:', options ); + self.localize = localize; + // add to window as global shortened alias + window._l = self.localize; + return self; +}; + +/** set up the current user as a Backbone model (mvc/user/user-model) */ +GalaxyApp.prototype._initUser = function _initUser( userJSON ){ + var self = this; + self.debug( '_initUser:', userJSON ); + self.user = new userModel.User( userJSON ); + //TODO: temp - old alias + self.currUser = self.user; + return self; +}; + +/** Set up DOM/jQuery/Backbone event listeners enabled for all pages */ +GalaxyApp.prototype._setUpListeners = function _setUpListeners(){ + var self = this; + + // hook to jq beforeSend to record the most recent ajax call and cache some data about it + /** cached info about the last ajax call made through jQuery */ + self.lastAjax = {}; + $( document ).bind( 'ajaxSend', function( ev, xhr, options ){ + var data = options.data; + try { + data = JSON.parse( data ); + } catch( err ){} + + self.lastAjax = { + url : location.href.slice( 0, -1 ) + options.url, + data : data + }; + //TODO:?? we might somehow manage to *retry* ajax using either this hook or Backbone.sync + }); + +}; + +/** string rep */ +GalaxyApp.prototype.toString = function toString(){ + var userEmail = this.user.get( 'email' ) || '(anonymous)'; + return 'GalaxyApp(' + userEmail + ')'; +}; + + +// ============================================================================ + return { + GalaxyApp : GalaxyApp + }; +}); diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/scripts/galaxy.autocom_tagging.js --- /dev/null +++ b/client/scripts/galaxy.autocom_tagging.js @@ -0,0 +1,368 @@ +/** +* JQuery extension for tagging with autocomplete. +* @author: Jeremy Goecks +* @require: jquery.autocomplete plugin +*/ +// +// Initialize "tag click functions" for tags. +// +function init_tag_click_function(tag_elt, click_func) { + $(tag_elt).find('.tag-name').each( function() { + $(this).click( function() { + var tag_str = $(this).text(); + var tag_name_and_value = tag_str.split(":"); + click_func(tag_name_and_value[0], tag_name_and_value[1]); + return true; + }); + }); +} + +jQuery.fn.autocomplete_tagging = function(options) { + + var defaults = { + get_toggle_link_text_fn: function(tags) { + var text = ""; + var num_tags = obj_length(tags); + if (num_tags > 0) { + text = num_tags + (num_tags > 1 ? " Tags" : " Tag"); + } else { + text = "Add tags"; + } + return text; + }, + tag_click_fn : function (name, value) {}, + editable: true, + input_size: 20, + in_form: false, + tags : {}, + use_toggle_link: true, + item_id: "", + add_tag_img: "", + add_tag_img_rollover: "", + delete_tag_img: "", + ajax_autocomplete_tag_url: "", + ajax_retag_url: "", + ajax_delete_tag_url: "", + ajax_add_tag_url: "" + }; + + var settings = jQuery.extend(defaults, options); + + // + // Initalize object's elements. + // + + // Get elements for this object. For this_obj, assume the last element with the id is the "this"; this is somewhat of a hack to address the problem + // that there may be two tagging elements for a single item if there are both community and individual tags for an element. + var this_obj = $(this); + var tag_area = this_obj.find('.tag-area'); + var toggle_link = this_obj.find('.toggle-link'); + var tag_input_field = this_obj.find('.tag-input'); + var add_tag_button = this_obj.find('.add-tag-button'); + + // Initialize toggle link. + toggle_link.click( function() { + // Take special actions depending on whether toggle is showing or hiding link. + var after_toggle_fn; + if (tag_area.is(":hidden")) { + after_toggle_fn = function() { + // If there are no tags, go right to editing mode by generating a click on the area. + var num_tags = $(this).find('.tag-button').length; + if (num_tags === 0) { + tag_area.click(); + } + }; + } else { + after_toggle_fn = function() { + tag_area.blur(); + }; + } + tag_area.slideToggle("fast", after_toggle_fn); + return $(this); + }); + + // Initialize tag input field. + if (settings.editable) { + tag_input_field.hide(); + } + tag_input_field.keyup( function(e) { + if ( e.keyCode === 27 ) { + // Escape key + $(this).trigger( "blur" ); + } else if ( + ( e.keyCode === 13 ) || // Return Key + ( e.keyCode === 188 ) || // Comma + ( e.keyCode === 32 ) // Space + ) { + // + // Check input. + // + + var new_value = this.value; + + // Suppress space after a ":" + if ( new_value.indexOf(": ", new_value.length - 2) !== -1) { + this.value = new_value.substring(0, new_value.length-1); + return false; + } + + // Remove trigger keys from input. + if ( (e.keyCode === 188) || (e.keyCode === 32) ) { + new_value = new_value.substring( 0 , new_value.length - 1 ); + } + + // Trim whitespace. + new_value = $.trim(new_value); + + // Too short? + if (new_value.length < 2) { + return false; + } + + // + // New tag OK - apply it. + // + + this.value = ""; // Reset text field now that tag is being added + + // Add button for tag after all other tag buttons. + var new_tag_button = build_tag_button(new_value); + var tag_buttons = tag_area.children(".tag-button"); + if (tag_buttons.length !== 0) { + var last_tag_button = tag_buttons.slice(tag_buttons.length-1); + last_tag_button.after(new_tag_button); + } else { + tag_area.prepend(new_tag_button); + } + + // Add tag to internal list. + var tag_name_and_value = new_value.split(":"); + settings.tags[tag_name_and_value[0]] = tag_name_and_value[1]; + + // Update toggle link text. + var new_text = settings.get_toggle_link_text_fn(settings.tags); + toggle_link.text(new_text); + + // Commit tag to server. + var zz = $(this); + $.ajax({ + url: settings.ajax_add_tag_url, + data: { new_tag: new_value }, + error: function() { + // Failed. Roll back changes and show alert. + new_tag_button.remove(); + delete settings.tags[tag_name_and_value[0]]; + var new_text = settings.get_toggle_link_text_fn(settings.tags); + toggle_link.text(new_text); + alert( "Add tag failed" ); + }, + success: function() { + // Flush autocomplete cache because it's not out of date. + // TODO: in the future, we could remove the particular item + // that was chosen from the cache rather than flush it. + zz.data('autocompleter').cacheFlush(); + } + }); + + return false; + } + }); + + // Add autocomplete to input. + var format_item_func = function(key, row_position, num_rows, value, search_term) { + var tag_name_and_value = value.split(":"); + return (tag_name_and_value.length === 1 ? tag_name_and_value[0] : tag_name_and_value[1]); + }; + var autocomplete_options = { selectFirst: false, formatItem: format_item_func, + autoFill: false, highlight: false }; + tag_input_field.autocomplete(settings.ajax_autocomplete_tag_url, autocomplete_options); + + + // Initialize delete tag images for current tags. + this_obj.find('.delete-tag-img').each(function() { + init_delete_tag_image( $(this) ); + }); + + + // Initialize tag click function. + init_tag_click_function($(this), settings.tag_click_fn); + + // Initialize "add tag" button. + add_tag_button.click( function() { + $(this).hide(); + + // Clicking on button is the same as clicking on the tag area. + tag_area.click(); + return false; + }); + + // + // Set up tag area interactions; these are needed only if tags are editable. + // + if (settings.editable) { + // When the tag area blurs, go to "view tag" mode. + tag_area.bind("blur", function(e) { + if (obj_length(settings.tags) > 0) { + add_tag_button.show(); + tag_input_field.hide(); + tag_area.removeClass("active-tag-area"); + // tag_area.addClass("tooltip"); + } else { + // No tags, so do nothing to ensure that input is still visible. + } + }); + + // On click, enable user to add tags. + tag_area.click( function(e) { + var is_active = $(this).hasClass("active-tag-area"); + + // If a "delete image" object was pressed and area is inactive, do nothing. + if ($(e.target).hasClass("delete-tag-img") && !is_active) { + return false; + } + + // If a "tag name" object was pressed and area is inactive, do nothing. + if ($(e.target).hasClass("tag-name") && !is_active) { + return false; + } + + // Remove tooltip. + // $(this).removeClass("tooltip"); + + // Hide add tag button, show tag_input field. Change background to show + // area is active. + $(this).addClass("active-tag-area"); + add_tag_button.hide(); + tag_input_field.show(); + tag_input_field.focus(); + + // Add handler to document that will call blur when the tag area is blurred; + // a tag area is blurred when a user clicks on an element outside the area. + var handle_document_click = function(e) { + var check_click = function(tag_area, target) { + var tag_area_id = tag_area.attr("id"); + // Blur the tag area if the element clicked on is not in the tag area. + if (target !== tag_area) { + tag_area.blur(); + $(window).unbind("click.tagging_blur"); + $(this).addClass("tooltip"); + } + }; + check_click(tag_area, $(e.target)); + }; + // TODO: we should attach the click handler to all frames in order to capture + // clicks outside the frame that this element is in. + //window.parent.document.onclick = handle_document_click; + //var temp = $(window.parent.document.body).contents().find("iframe").html(); + //alert(temp); + //$(document).parent().click(handle_document_click); + $(window).bind("click.tagging_blur", handle_document_click); + + return false; + }); + } + + // If using toggle link, hide the tag area. Otherwise, show the tag area. + if (settings.use_toggle_link) { + tag_area.hide(); + } + + // + // Helper functions. + // + + // + // Collapse tag name + value into a single string. + // + function build_tag_str(tag_name, tag_value) { + return tag_name + ( tag_value ? ":" + tag_value : ""); + } + + + // Initialize a "delete tag image": when click, delete tag from UI and send delete request to server. + function init_delete_tag_image(delete_img) { + $(delete_img).mouseenter( function () { + $(this).attr("src", settings.delete_tag_img_rollover); + }); + $(delete_img).mouseleave( function () { + $(this).attr("src", settings.delete_tag_img); + }); + $(delete_img).click( function () { + // Tag button is image's parent. + var tag_button = $(this).parent(); + + // Get tag name, value. + var tag_name_elt = tag_button.find(".tag-name").eq(0); + var tag_str = tag_name_elt.text(); + var tag_name_and_value = tag_str.split(":"); + var tag_name = tag_name_and_value[0]; + var tag_value = tag_name_and_value[1]; + + var prev_button = tag_button.prev(); + tag_button.remove(); + + // Remove tag from local list for consistency. + delete settings.tags[tag_name]; + + // Update toggle link text. + var new_text = settings.get_toggle_link_text_fn(settings.tags); + toggle_link.text(new_text); + + // Delete tag. + $.ajax({ + url: settings.ajax_delete_tag_url, + data: { tag_name: tag_name }, + error: function() { + // Failed. Roll back changes and show alert. + settings.tags[tag_name] = tag_value; + if (prev_button.hasClass("tag-button")) { + prev_button.after(tag_button); + } else { + tag_area.prepend(tag_button); + } + alert( "Remove tag failed" ); + + toggle_link.text(settings.get_toggle_link_text_fn(settings.tags)); + + // TODO: no idea why it's necessary to set this up again. + delete_img.mouseenter( function () { + $(this).attr("src", settings.delete_tag_img_rollover); + }); + delete_img.mouseleave( function () { + $(this).attr("src", settings.delete_tag_img); + }); + }, + success: function() {} + }); + + return true; + }); + } + + // + // Function that builds a tag button. + // + function build_tag_button(tag_str) { + // Build "delete tag" image. + var delete_img = $("<img/>").attr("src", settings.delete_tag_img).addClass("delete-tag-img"); + init_delete_tag_image(delete_img); + + // Build tag button. + var tag_name_elt = $("<span>").text(tag_str).addClass("tag-name"); + tag_name_elt.click( function() { + var tag_name_and_value = tag_str.split(":"); + settings.tag_click_fn(tag_name_and_value[0], tag_name_and_value[1]); + return true; + }); + + var tag_button = $("<span></span>").addClass("tag-button"); + tag_button.append(tag_name_elt); + // Allow delete only if element is editable. + if (settings.editable) { + tag_button.append(delete_img); + } + + return tag_button; + } + +}; diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/scripts/galaxy.base.js --- /dev/null +++ b/client/scripts/galaxy.base.js @@ -0,0 +1,636 @@ +// requestAnimationFrame polyfill +(function() { + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; + window.cancelRequestAnimationFrame = window[vendors[x]+ + 'CancelRequestAnimationFrame']; + } + + if (!window.requestAnimationFrame) + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + + if (!window.cancelAnimationFrame) + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; +}()); + +// IE doesn't implement Array.indexOf +if (!Array.indexOf) { + Array.prototype.indexOf = function(obj) { + for (var i = 0, len = this.length; i < len; i++) { + if (this[i] == obj) { + return i; + } + } + return -1; + }; +} + +// Returns the number of keys (elements) in an array/dictionary. +function obj_length(obj) { + if (obj.length !== undefined) { + return obj.length; + } + + var count = 0; + for (var element in obj) { + count++; + } + return count; +} + +$.fn.makeAbsolute = function(rebase) { + return this.each(function() { + var el = $(this); + var pos = el.position(); + el.css({ + position: "absolute", + marginLeft: 0, marginTop: 0, + top: pos.top, left: pos.left, + right: $(window).width() - ( pos.left + el.width() ) + }); + if (rebase) { + el.remove().appendTo("body"); + } + }); +}; + +/** + * Sets up popupmenu rendering and binds options functions to the appropriate links. + * initial_options is a dict with text describing the option pointing to either (a) a + * function to perform; or (b) another dict with two required keys, 'url' and 'action' (the + * function to perform. (b) is useful for exposing the underlying URL of the option. + */ +function make_popupmenu(button_element, initial_options) { + /* Use the $.data feature to store options with the link element. + This allows options to be changed at a later time + */ + var element_menu_exists = (button_element.data("menu_options")); + button_element.data("menu_options", initial_options); + + // If element already has menu, nothing else to do since HTML and actions are already set. + if (element_menu_exists) { return; } + + button_element.bind("click.show_popup", function(e) { + // Close existing visible menus + $(".popmenu-wrapper").remove(); + + // Need setTimeouts so clicks don't interfere with each other + setTimeout( function() { + // Dynamically generate the wrapper holding all the selectable options of the menu. + var menu_element = $( "<ul class='dropdown-menu' id='" + button_element.attr('id') + "-menu'></ul>" ); + var options = button_element.data("menu_options"); + if (obj_length(options) <= 0) { + $("<li>No Options.</li>").appendTo(menu_element); + } + $.each( options, function( k, v ) { + if (v) { + // Action can be either an anonymous function and a mapped dict. + var action = v.action || v; + menu_element.append( $("<li></li>").append( $("<a>").attr("href", v.url).html(k).click(action) ) ); + } else { + menu_element.append( $("<li></li>").addClass( "head" ).append( $("<a href='#'></a>").html(k) ) ); + } + }); + var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ) + .append( menu_element ).appendTo( "body" ); + + var x = e.pageX - wrapper.width() / 2 ; + x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 5 ); + x = Math.max( x, $(document).scrollLeft() + 5 ); + + wrapper.css({ + top: e.pageY, + left: x + }); + }, 10); + + setTimeout( function() { + // Bind click event to current window and all frames to remove any visible menus + // Bind to document object instead of window object for IE compat + var close_popup = function(el) { + $(el).bind("click.close_popup", function() { + $(".popmenu-wrapper").remove(); + el.unbind("click.close_popup"); + }); + }; + close_popup( $(window.document) ); // Current frame + close_popup( $(window.top.document) ); // Parent frame + for (var frame_id = window.top.frames.length; frame_id--;) { // Sibling frames + var frame = $(window.top.frames[frame_id].document); + close_popup(frame); + } + }, 50); + + return false; + }); + +} + +/** + * Convert two seperate (often adjacent) divs into galaxy popupmenu + * - div 1 contains a number of anchors which become the menu options + * - div 1 should have a 'popupmenu' attribute + * - this popupmenu attribute contains the id of div 2 + * - div 2 becomes the 'face' of the popupmenu + * + * NOTE: make_popup_menus finds and operates on all divs with a popupmenu attr (no need to point it at something) + * but (since that selector searches the dom on the page), you can send a parent in + * NOTE: make_popup_menus, and make_popupmenu are horrible names + */ +function make_popup_menus( parent ) { + // find all popupmenu menu divs (divs that contains anchors to be converted to menu options) + // either in the parent or the document if no parent passed + parent = parent || document; + $( parent ).find( "div[popupmenu]" ).each( function() { + var options = {}; + var menu = $(this); + + // find each anchor in the menu, convert them into an options map: { a.text : click_function } + menu.find( "a" ).each( function() { + var link = $(this), + link_dom = link.get(0), + confirmtext = link_dom.getAttribute( "confirm" ), + href = link_dom.getAttribute( "href" ), + target = link_dom.getAttribute( "target" ); + + // no href - no function (gen. a label) + if (!href) { + options[ link.text() ] = null; + + } else { + options[ link.text() ] = { + url: href, + action: function() { + + // if theres confirm text, send the dialog + if ( !confirmtext || confirm( confirmtext ) ) { + // link.click() doesn't use target for some reason, + // so manually do it here. + if (target) { + window.open(href, target); + return false; + } + // For all other links, do the default action. + else { + link.click(); + } + } + } + }; + } + }); + // locate the element with the id corresponding to the menu's popupmenu attr + var box = $( parent ).find( "#" + menu.attr( 'popupmenu' ) ); + + // For menus with clickable link text, make clicking on the link go through instead + // of activating the popup menu + box.find("a").bind("click", function(e) { + e.stopPropagation(); // Stop bubbling so clicking on the link goes through + return true; + }); + + // attach the click events and menu box building to the box element + make_popupmenu(box, options); + box.addClass("popup"); + menu.remove(); + }); +} + +// Alphanumeric/natural sort fn +function naturalSort(a, b) { + // setup temp-scope variables for comparison evauluation + var re = /(-?[0-9\.]+)/g, + x = a.toString().toLowerCase() || '', + y = b.toString().toLowerCase() || '', + nC = String.fromCharCode(0), + xN = x.replace( re, nC + '$1' + nC ).split(nC), + yN = y.replace( re, nC + '$1' + nC ).split(nC), + xD = (new Date(x)).getTime(), + yD = xD ? (new Date(y)).getTime() : null; + // natural sorting of dates + if ( yD ) { + if ( xD < yD ) { return -1; } + else if ( xD > yD ) { return 1; } + } + // natural sorting through split numeric strings and default strings + var oFxNcL, oFyNcL; + for ( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) { + oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc]; + oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc]; + if (oFxNcL < oFyNcL) { return -1; } + else if (oFxNcL > oFyNcL) { return 1; } + } + return 0; +} + +$.fn.refresh_select2 = function() { + var select_elt = $(this); + var options = { width: "resolve", + closeOnSelect: !select_elt.is("[MULTIPLE]") + }; + return select_elt.select2( options ); +} + +// Replace select box with a text input box + autocomplete. +function replace_big_select_inputs(min_length, max_length, select_elts) { + // To do replace, the select2 plugin must be loaded. + + if (!jQuery.fn.select2) { + return; + } + + // Set default for min_length and max_length + if (min_length === undefined) { + min_length = 20; + } + if (max_length === undefined) { + max_length = 3000; + } + + select_elts = select_elts || $('select'); + + select_elts.each( function() { + var select_elt = $(this).not('[multiple]'); + // Make sure that options is within range. + var num_options = select_elt.find('option').length; + if ( (num_options < min_length) || (num_options > max_length) ) { + return; + } + + if (select_elt.hasClass("no-autocomplete")) { + return; + } + + /* Replaced jQuery.autocomplete with select2, notes: + * - multiple selects are supported + * - the original element is updated with the value, convert_to_values should not be needed + * - events are fired when updating the original element, so refresh_on_change should just work + * + * - should we still sort dbkey fields here? + */ + select_elt.refresh_select2(); + }); +} + +/** + * Make an element with text editable: (a) when user clicks on text, a textbox/area + * is provided for editing; (b) when enter key pressed, element's text is set and on_finish + * is called. + */ +// TODO: use this function to implement async_save_text (implemented below). +$.fn.make_text_editable = function(config_dict) { + // Get config options. + var num_cols = ("num_cols" in config_dict ? config_dict.num_cols : 30), + num_rows = ("num_rows" in config_dict ? config_dict.num_rows : 4), + use_textarea = ("use_textarea" in config_dict ? config_dict.use_textarea : false), + on_finish = ("on_finish" in config_dict ? config_dict.on_finish : null), + help_text = ("help_text" in config_dict ? config_dict.help_text : null); + + // Add element behavior. + var container = $(this); + container.addClass("editable-text").click(function(e) { + // If there's already an input element, editing is active, so do nothing. + if ($(this).children(":input").length > 0) { + return; + } + + container.removeClass("editable-text"); + + // Handler for setting element text. + var set_text = function(new_text) { + container.find(":input").remove(); + + if (new_text !== "") { + container.text(new_text); + } + else { + // No text; need a line so that there is a click target. + container.html("<br>"); + } + container.addClass("editable-text"); + + if (on_finish) { + on_finish(new_text); + } + }; + + // Create input element(s) for editing. + var cur_text = ("cur_text" in config_dict ? config_dict.cur_text : container.text() ), + input_elt, button_elt; + + if (use_textarea) { + input_elt = $("<textarea/>") + .attr({ rows: num_rows, cols: num_cols }).text($.trim(cur_text)) + .keyup(function(e) { + if (e.keyCode === 27) { + // Escape key. + set_text(cur_text); + } + }); + button_elt = $("<button/>").text("Done").click(function() { + set_text(input_elt.val()); + // Return false so that click does not propogate to container. + return false; + }); + } + else { + input_elt = $("<input type='text'/>").attr({ value: $.trim(cur_text), size: num_cols }) + .blur(function() { + set_text(cur_text); + }).keyup(function(e) { + if (e.keyCode === 27) { + // Escape key. + $(this).trigger("blur"); + } else if (e.keyCode === 13) { + // Enter key. + set_text($(this).val()); + } + + // Do not propogate event to avoid unwanted side effects. + e.stopPropagation(); + }); + } + + // Replace text with input object(s) and focus & select. + container.text(""); + container.append(input_elt); + if (button_elt) { + container.append(button_elt); + } + input_elt.focus(); + input_elt.select(); + + // Do not propogate to elements below b/c that blurs input and prevents it from being used. + e.stopPropagation(); + }); + + // Add help text if there some. + if (help_text) { + container.attr("title", help_text).tooltip(); + } + + return container; +}; + +/** + * Edit and save text asynchronously. + */ +function async_save_text( click_to_edit_elt, text_elt_id, save_url, + text_parm_name, num_cols, use_textarea, num_rows, on_start, on_finish ) { + // Set defaults if necessary. + if (num_cols === undefined) { + num_cols = 30; + } + if (num_rows === undefined) { + num_rows = 4; + } + + // Set up input element. + $("#" + click_to_edit_elt).click(function() { + // Check if this is already active + if ( $("#renaming-active").length > 0) { + return; + } + var text_elt = $("#" + text_elt_id), + old_text = text_elt.text(), + t; + + if (use_textarea) { + t = $("<textarea></textarea>").attr({ rows: num_rows, cols: num_cols }).text( $.trim(old_text) ); + } else { + t = $("<input type='text'></input>").attr({ value: $.trim(old_text), size: num_cols }); + } + t.attr("id", "renaming-active"); + t.blur( function() { + $(this).remove(); + text_elt.show(); + if (on_finish) { + on_finish(t); + } + }); + t.keyup( function( e ) { + if ( e.keyCode === 27 ) { + // Escape key + $(this).trigger( "blur" ); + } else if ( e.keyCode === 13 ) { + // Enter key submits + var ajax_data = {}; + ajax_data[text_parm_name] = $(this).val(); + $(this).trigger( "blur" ); + $.ajax({ + url: save_url, + data: ajax_data, + error: function() { + alert( "Text editing for elt " + text_elt_id + " failed" ); + // TODO: call finish or no? For now, let's not because error occurred. + }, + success: function(processed_text) { + // Set new text and call finish method. + if (processed_text !== "") { + text_elt.text(processed_text); + } else { + text_elt.html("<em>None</em>"); + } + if (on_finish) { + on_finish(t); + } + } + }); + } + }); + + if (on_start) { + on_start(t); + } + // Replace text with input object and focus & select. + text_elt.hide(); + t.insertAfter(text_elt); + t.focus(); + t.select(); + + return; + }); +} + +function commatize( number ) { + number += ''; // Convert to string + var rgx = /(\d+)(\d{3})/; + while (rgx.test(number)) { + number = number.replace(rgx, '$1' + ',' + '$2'); + } + return number; +} + +// Reset tool search to start state. +function reset_tool_search( initValue ) { + // Function may be called in top frame or in tool_menu_frame; + // in either case, get the tool menu frame. + var tool_menu_frame = $("#galaxy_tools").contents(); + if (tool_menu_frame.length === 0) { + tool_menu_frame = $(document); + } + + // Remove classes that indicate searching is active. + $(this).removeClass("search_active"); + tool_menu_frame.find(".toolTitle").removeClass("search_match"); + + // Reset visibility of tools and labels. + tool_menu_frame.find(".toolSectionBody").hide(); + tool_menu_frame.find(".toolTitle").show(); + tool_menu_frame.find(".toolPanelLabel").show(); + tool_menu_frame.find(".toolSectionWrapper").each( function() { + if ($(this).attr('id') !== 'recently_used_wrapper') { + // Default action. + $(this).show(); + } else if ($(this).hasClass("user_pref_visible")) { + $(this).show(); + } + }); + tool_menu_frame.find("#search-no-results").hide(); + + // Reset search input. + tool_menu_frame.find("#search-spinner").hide(); + if (initValue) { + var search_input = tool_menu_frame.find("#tool-search-query"); + search_input.val("search tools"); + } +} + +// Create GalaxyAsync object. +var GalaxyAsync = function(log_action) { + this.url_dict = {}; + this.log_action = (log_action === undefined ? false : log_action); +}; + +GalaxyAsync.prototype.set_func_url = function( func_name, url ) { + this.url_dict[func_name] = url; +}; + +// Set user preference asynchronously. +GalaxyAsync.prototype.set_user_pref = function( pref_name, pref_value ) { + // Get URL. + var url = this.url_dict[arguments.callee]; + if (url === undefined) { return false; } + $.ajax({ + url: url, + data: { "pref_name" : pref_name, "pref_value" : pref_value }, + error: function() { return false; }, + success: function() { return true; } + }); +}; + +// Log user action asynchronously. +GalaxyAsync.prototype.log_user_action = function( action, context, params ) { + if (!this.log_action) { return; } + + // Get URL. + var url = this.url_dict[arguments.callee]; + if (url === undefined) { return false; } + $.ajax({ + url: url, + data: { "action" : action, "context" : context, "params" : params }, + error: function() { return false; }, + success: function() { return true; } + }); +}; + +// Initialize refresh events. +function init_refresh_on_change () { + $("select[refresh_on_change='true']") + .off('change') + .change(function() { + var select_field = $(this), + select_val = select_field.val(), + refresh = false, + ref_on_change_vals = select_field.attr("refresh_on_change_values"); + if (ref_on_change_vals) { + ref_on_change_vals = ref_on_change_vals.split(','); + var last_selected_value = select_field.attr("last_selected_value"); + if ($.inArray(select_val, ref_on_change_vals) === -1 && $.inArray(last_selected_value, ref_on_change_vals) === -1) { + return; + } + } + $(window).trigger("refresh_on_change"); + $(document).trigger("convert_to_values"); // Convert autocomplete text to values + select_field.get(0).form.submit(); + }); + + // checkboxes refresh on change + $(":checkbox[refresh_on_change='true']") + .off('click') + .click( function() { + var select_field = $(this), + select_val = select_field.val(), + refresh = false, + ref_on_change_vals = select_field.attr("refresh_on_change_values"); + if (ref_on_change_vals) { + ref_on_change_vals = ref_on_change_vals.split(','); + var last_selected_value = select_field.attr("last_selected_value"); + if ($.inArray(select_val, ref_on_change_vals) === -1 && $.inArray(last_selected_value, ref_on_change_vals) === -1) { + return; + } + } + $(window).trigger("refresh_on_change"); + select_field.get(0).form.submit(); + }); + + // Links with confirmation + $( "a[confirm]" ) + .off('click') + .click( function() { + return confirm( $(this).attr("confirm") ); + }); +}; + +$(document).ready( function() { + + // Refresh events for form fields. + init_refresh_on_change(); + + // Tooltips + if ( $.fn.tooltip ) { + // Put tooltips below items in panel header so that they do not overlap masthead. + $(".unified-panel-header [title]").tooltip( { placement: 'bottom' } ); + + // default tooltip initialization, it will follow the data-placement tag for tooltip location + // and fallback to 'top' if not present + $("[title]").tooltip(); + } + // Make popup menus. + make_popup_menus(); + + // Replace big selects. + replace_big_select_inputs(20, 1500); + + // If galaxy_main frame does not exist and link targets galaxy_main, + // add use_panels=True and set target to self. + $("a").click( function() { + var anchor = $(this); + var galaxy_main_exists = (parent.frames && parent.frames.galaxy_main); + if ( ( anchor.attr( "target" ) == "galaxy_main" ) && ( !galaxy_main_exists ) ) { + var href = anchor.attr("href"); + if (href.indexOf("?") == -1) { + href += "?"; + } + else { + href += "&"; + } + href += "use_panels=True"; + anchor.attr("href", href); + anchor.attr("target", "_self"); + } + return anchor; + }); + +}); diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/scripts/galaxy.frame.js --- /dev/null +++ b/client/scripts/galaxy.frame.js @@ -0,0 +1,173 @@ +// dependencies +define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) { + +// frame manager +var GalaxyFrame = Backbone.View.extend( +{ + // base element + el_main: 'body', + + // frame active/disabled + active: false, + + // button active + button_active: null, + + // button load + button_load : null, + + // initialize + initialize : function(options) + { + // add to masthead menu + var self = this; + + // create frames + this.frames = new Frames.View({ + visible: false, + }); + + // add activate icon + this.button_active = new mod_masthead.GalaxyMastheadIcon ( + { + icon : 'fa-th', + tooltip : 'Enable/Disable Scratchbook', + onclick : function() { self._activate(); }, + onunload : function() { + if (self.frames.length() > 0) { + return "You opened " + self.frames.length() + " frame(s) which will be lost."; + } + } + }); + + // add to masthead + Galaxy.masthead.append(this.button_active); + + // add load icon + this.button_load = new mod_masthead.GalaxyMastheadIcon ( + { + icon : 'fa-eye', + tooltip : 'Show/Hide Scratchbook', + onclick : function(e) { + if (self.frames.visible) { + self.frames.hide(); + } else { + self.frames.show(); + } + }, + with_number : true + }); + + // add to masthead + Galaxy.masthead.append(this.button_load); + + // create + this.setElement(this.frames.$el); + + // append to main + $(this.el_main).append(this.$el); + + // refresh menu + this.frames.setOnChange(function() { + self._refresh(); + }); + this._refresh(); + }, + + // adds and displays a new frame/window + add: function(options) + { + // open new tab + if (options.target == '_blank') + { + window.open(options.content); + return; + } + + // reload entire window + if (options.target == '_top' || options.target == '_parent' || options.target == '_self') + { + window.location = options.content; + return; + } + + // validate + if (!this.active) + { + // fix url if main frame is unavailable + var $galaxy_main = $(window.parent.document).find('#galaxy_main'); + if (options.target == 'galaxy_main' || options.target == 'center') + { + if ($galaxy_main.length === 0) + { + var href = options.content; + if (href.indexOf('?') == -1) + href += '?'; + else + href += '&'; + href += 'use_panels=True'; + window.location = href; + } else { + $galaxy_main.attr('src', options.content); + } + } else + window.location = options.content; + + // stop + return; + } + + // add to frames view + this.frames.add(options); + }, + + // activate/disable panel + _activate: function () + { + // check + if (this.active) + { + // disable + this.active = false; + + // toggle + this.button_active.untoggle(); + + // hide panel + this.frames.hide(); + } else { + // activate + this.active = true; + + // untoggle + this.button_active.toggle(); + } + }, + + // update frame counter + _refresh: function() + { + // update on screen counter + this.button_load.number(this.frames.length()); + + // check + if(this.frames.length() === 0) + this.button_load.hide(); + else + this.button_load.show(); + + // check + if (this.frames.visible) { + this.button_load.toggle(); + } else { + this.button_load.untoggle(); + } + } +}); + +// return +return { + GalaxyFrame: GalaxyFrame +}; + +}); diff -r 2346e098b27e0141fdd3e9821895413e27bc2c2f -r f535ef20718d82ab374408d492afa917324a22c5 client/scripts/galaxy.library.js --- /dev/null +++ b/client/scripts/galaxy.library.js @@ -0,0 +1,159 @@ +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// === MAIN GALAXY LIBRARY MODULE ==== +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + +define([ + "galaxy.masthead", + "utils/utils", + "libs/toastr", + "mvc/base-mvc", + "mvc/library/library-model", + "mvc/library/library-folderlist-view", + "mvc/library/library-librarylist-view", + "mvc/library/library-librarytoolbar-view", + "mvc/library/library-foldertoolbar-view", + "mvc/library/library-dataset-view", + "mvc/library/library-library-view", + "mvc/library/library-folder-view" + ], +function(mod_masthead, + mod_utils, + mod_toastr, + mod_baseMVC, + mod_library_model, + mod_folderlist_view, + mod_librarylist_view, + mod_librarytoolbar_view, + mod_foldertoolbar_view, + mod_library_dataset_view, + mod_library_library_view, + mod_library_folder_view + ) { + +// ============================================================================ +// ROUTER +var LibraryRouter = Backbone.Router.extend({ + initialize: function() { + this.routesHit = 0; + //keep count of number of routes handled by the application + Backbone.history.on('route', function() { this.routesHit++; }, this); + }, + + routes: { + "" : "libraries", + "library/:library_id/permissions" : "library_permissions", + "folders/:folder_id/permissions" : "folder_permissions", + "folders/:id" : "folder_content", + "folders/:folder_id/datasets/:dataset_id" : "dataset_detail", + "folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions", + "folders/:folder_id/datasets/:dataset_id/versions/:ldda_id" : "dataset_version", + "folders/:folder_id/download/:format" : "download" + }, + + back: function() { + if(this.routesHit > 1) { + //more than one route hit -> user did not land to current page directly + window.history.back(); + } else { + //otherwise go to the home page. Use replaceState if available so + //the navigation doesn't create an extra history entry + this.navigate('#', {trigger:true, replace:true}); + } + } +}); + +// ============================================================================ +/** session storage for library preferences */ +var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({ + defaults : { + with_deleted : false, + sort_order : 'asc', + sort_by : 'name' + } +}); + +// ============================================================================ +// Main controller of Galaxy Library +var GalaxyLibrary = Backbone.View.extend({ + + libraryToolbarView: null, + libraryListView: null, + library_router: null, + libraryView: null, + folderToolbarView: null, + folderListView: null, + datasetView: null, + + initialize : function(){ + Galaxy.libraries = this; + + this.preferences = new LibraryPrefs( {id: 'global-lib-prefs'} ); + + this.library_router = new LibraryRouter(); + + this.library_router.on('route:libraries', function() { + Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView(); + Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView(); + }); + + this.library_router.on('route:folder_content', function(id) { + if (Galaxy.libraries.folderToolbarView){ + Galaxy.libraries.folderToolbarView.$el.unbind('click'); + } + Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id}); + Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id}); + }); + + this.library_router.on('route:download', function(folder_id, format) { + if ($('#folder_list_body').find(':checked').length === 0) { + mod_toastr.info('You have to select some datasets to download'); + Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true}); + } else { + Galaxy.libraries.folderToolbarView.download(folder_id, format); + Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true}); + } + }); + + this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){ + if (Galaxy.libraries.datasetView){ + Galaxy.libraries.datasetView.$el.unbind('click'); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id}); + }); + this.library_router.on('route:dataset_version', function(folder_id, dataset_id, ldda_id){ + if (Galaxy.libraries.datasetView){ + Galaxy.libraries.datasetView.$el.unbind('click'); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true}); + }); + + this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){ + if (Galaxy.libraries.datasetView){ + Galaxy.libraries.datasetView.$el.unbind('click'); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true}); + }); + + this.library_router.on('route:library_permissions', function(library_id){ + if (Galaxy.libraries.libraryView){ + Galaxy.libraries.libraryView.$el.unbind('click'); + } + Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true}); + }); + + this.library_router.on('route:folder_permissions', function(folder_id){ + if (Galaxy.libraries.folderView){ + Galaxy.libraries.folderView.$el.unbind('click'); + } + Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true}); + }); + + Backbone.history.start({pushState: false}); + } +}); + +return { + GalaxyApp: GalaxyLibrary +}; + +}); This diff is so big that we needed to truncate the remainder. https://bitbucket.org/galaxy/galaxy-central/commits/ba66d120d001/ Changeset: ba66d120d001 User: carlfeberhard Date: 2014-09-16 15:05:46 Summary: Merged galaxy/galaxy-central into default Affected #: 85 files diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/galaxy.base.js --- a/client/scripts/galaxy.base.js +++ b/client/scripts/galaxy.base.js @@ -593,6 +593,26 @@ }); }; + +// jQuery plugin to prevent double submission of forms +// Ref: http://stackoverflow.com/questions/2830542/prevent-double-submission-of-form... +jQuery.fn.preventDoubleSubmission = function() { + $(this).on('submit',function(e){ + var $form = $(this); + + if ($form.data('submitted') === true) { + // Previously submitted - don't submit again + e.preventDefault(); + } else { + // Mark it so that the next submit can be ignored + $form.data('submitted', true); + } + }); + + // Keep chainability + return this; +}; + $(document).ready( function() { // Refresh events for form fields. diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-datasets.js --- a/client/scripts/mvc/tools/tools-datasets.js +++ b/client/scripts/mvc/tools/tools-datasets.js @@ -25,21 +25,26 @@ }, // filter datasets by data type - filterType: function(filter_type) { - // return matched datasets - return this.currHistoryContents.filter( function( content ){ - // link details - var history_content_type = content.get( 'history_content_type' ); - var data_type = content.get( 'file_ext'); + filterType: function(options) { + options = options || {}; + return this.currHistoryContents.filter(function(content){ + // match datatypes + var found = false; + for (var i in options.data_types) { + if (content.get('data_type').indexOf(options.data_types[i]) != -1) { + found = true; + break; + } + } - // apply filter - return history_content_type === 'dataset';// && (data_type === filter_type || filter_type === ''); + // final match result + return (content.get('history_content_type') === options.content_type || !options.content_type) && + (found || !options.data_types) && !content.get('deleted'); }); }, // filter datasets by id filter: function(filter_id) { - // return matched datasets return _.first( this.currHistoryContents.filter( function( content ){ return content.get( 'id' ) === filter_id; }) ); } }); diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-form.js --- a/client/scripts/mvc/tools/tools-form.js +++ b/client/scripts/mvc/tools/tools-form.js @@ -56,6 +56,12 @@ }); }, + // message + message: function(options) { + $(this.main_el).empty(); + $(this.main_el).append(ToolTemplate.message(options)); + }, + // reset form reset: function() { for (var i in this.element_list) { @@ -63,6 +69,20 @@ } }, + // refresh + refresh: function() { + // recreate tree structure + this.tree.refresh(); + + // trigger change + for (var id in this.field_list) { + this.field_list[id].trigger('change'); + } + + // log + console.debug('tools-form::refresh() - Recreated tree structure. Refresh.'); + }, + // initialize tool form _initializeToolForm: function() { // link this @@ -135,10 +155,6 @@ button_search.$el.hide(); } - // create message - self.message = new Ui.Message(); - self.portlet.append(self.message.$el); - // append form $(self.main_el).append(self.portlet.$el); @@ -174,22 +190,9 @@ // trigger refresh self.refresh(); //self.job_handler.submit(); + self.tree.finalize(); } }); - }, - - // refresh - refresh: function() { - // recreate tree structure - this.tree.refresh(); - - // trigger change - for (var id in this.field_list) { - this.field_list[id].trigger('change'); - } - - // log - console.debug('tools-form::refresh() - Recreated tree structure. Refresh.'); } }); diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-jobs.js --- a/client/scripts/mvc/tools/tools-jobs.js +++ b/client/scripts/mvc/tools/tools-jobs.js @@ -31,12 +31,16 @@ // success handler function(response) { if (!response.outputs || response.outputs.length == 0) { - console.log(response); + console.debug(response); } + self.app.message({ + text : 'A job has been successfully added to the queue. You can check the status of queued jobs and view the resulting data by refreshing the History pane. When the job has been run the status will change from \'running\' to \'finished\' if completed successfully or \'error\' if problems were encountered.' + }); self._refreshHdas(); }, // error handler function(response) { + console.debug(response); if (response && response.message && response.message.data) { var error_messages = self.app.tree.match(response.message.data); for (var id in error_messages) { diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-section.js --- a/client/scripts/mvc/tools/tools-section.js +++ b/client/scripts/mvc/tools/tools-section.js @@ -16,13 +16,11 @@ // set text this.$el.find('.ui-table-form-error-text').html(text); this.$el.find('.ui-table-form-error').fadeIn(); - this.$el.addClass('ui-table-row-error'); }, // reset reset: function() { this.$el.find('.ui-table-form-error').hide(); - this.$el.removeClass('ui-table-form-error'); }, // template @@ -35,7 +33,7 @@ } // add error - $input.append('<div class="ui-table-form-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>'); + $input.append('<div class="ui-table-form-error ui-error"><span class="fa fa-arrow-down"/><span class="ui-table-form-error-text"></div>'); // add label if (options.label) { @@ -274,7 +272,7 @@ // dataset column case 'data_column': - field = this._field_data_colum(input_def); + field = this._field_select(input_def); break; // conditional select field diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-select-dataset.js --- a/client/scripts/mvc/tools/tools-select-dataset.js +++ b/client/scripts/mvc/tools/tools-select-dataset.js @@ -6,54 +6,6 @@ initialize : function(app, options) { // link this var self = this; - - // get datasets - var datasets = app.datasets.filterType(); - - // configure options fields - var select_data = []; - for (var i in datasets) { - select_data.push({ - label: datasets[i].get('name'), - value: datasets[i].get('id') - }); - } - - // create select field - this.select = new Ui.Select.View({ - data : select_data, - value : select_data[0].value, - onchange : function() { - self.trigger('change'); - } - }); - - // create select field for multiple files - this.select_multiple = new Ui.Select.View({ - multiple : true, - data : select_data, - value : select_data[0].value, - onchange : function() { - self.trigger('change'); - } - }); - - - // create select field for multiple files - this.select_collection = new Ui.Select.View({ - data : select_data, - value : select_data[0].value, - onchange : function() { - self.trigger('change'); - } - }); - - // add change event. fires on trigger - this.on('change', function() { - if (options.onchange) { - options.onchange(self.value()); - } - }); // tabs this.tabs = new Tabs.View({ @@ -62,20 +14,66 @@ } }); - // add tab - this.tabs.add({ - id : 'single', - title : 'Select a dataset', - $el : this.select.$el + // + // datasets + // + var datasets = app.datasets.filterType({ + content_type : 'dataset', + data_types : options.extensions + }); + + // configure options fields + var dataset_options = []; + for (var i in datasets) { + dataset_options.push({ + label: datasets[i].get('name'), + value: datasets[i].get('id') + }); + } + + // select field + this.select_datasets = new Ui.Select.View({ + multiple : true, + data : dataset_options, + value : dataset_options[0] && dataset_options[0].value, + onchange : function() { + self.trigger('change'); + } }); // add tab this.tabs.add({ - id : 'multiple', - title : 'Select multiple datasets', - $el : this.select_multiple.$el + id : 'datasets', + title : 'Select datasets', + $el : this.select_datasets.$el }); - + + // + // collections + // + var collections = app.datasets.filterType({ + content_type : 'collection', + data_types : options.extensions + }); + + // configure options fields + var collection_options = []; + for (var i in collections) { + collection_options.push({ + label: collections[i].get('name'), + value: collections[i].get('id') + }); + } + + // create select field for collections + this.select_collection = new Ui.Select.View({ + data : collection_options, + value : collection_options[0] && collection_options[0].value, + onchange : function() { + self.trigger('change'); + } + }); + // add tab this.tabs.add({ id : 'collection', @@ -85,18 +83,23 @@ // add element this.setElement(this.tabs.$el); + + // add change event. fires on trigger + this.on('change', function() { + if (options.onchange) { + options.onchange(self.value()); + } + }); }, // value value : function (new_value) { var current_tab = this.tabs.current(); switch(current_tab) { - case 'multiple' : - return this.select_multiple.value(); - case 'collection' : + case 'datasets': + return this.select_datasets.value(); + case 'collection': return this.select_collection.value(); - default : - return this.select.value(); } }, diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-template.js --- a/client/scripts/mvc/tools/tools-template.js +++ b/client/scripts/mvc/tools/tools-template.js @@ -13,6 +13,12 @@ citations: function() { return '<div id="citations"></div>'; + }, + + message: function(options) { + return '<div class="donemessagelarge">' + + '<p>' + options.text + '</p>' + + '</div>'; } }; diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/tools/tools-tree.js --- a/client/scripts/mvc/tools/tools-tree.js +++ b/client/scripts/mvc/tools/tools-tree.js @@ -50,8 +50,8 @@ // converter between raw dictionary and job dictionary function convert(identifier, head) { - for (var i in head) { - var node = head[i]; + for (var index in head) { + var node = head[index]; if (node.input) { // get node var input = node.input; @@ -68,9 +68,9 @@ // handle repeats case 'repeat': var index = 0; - for (var j in node) { - if (j.indexOf('section') != -1) { - convert(job_input_id + '_' + index++, node[j]); + for (var i in node) { + if (i.indexOf('section') != -1) { + convert(job_input_id + '_' + index++, node[i]); } } break; @@ -83,20 +83,38 @@ add (job_input_id + '|' + input.test_param.name, input.id, value); // find selected case - for (var j in input.cases) { - if (input.cases[j].value == value) { - convert(job_input_id, head[input.id + '-section-' + j]); + for (var i in input.cases) { + if (input.cases[i].value == value) { + convert(job_input_id, head[input.id + '-section-' + i]); break; } } break; // handle data inputs case 'data': - var value = { - id : self.app.field_list[input.id].value(), - src : 'hda' + // create array for dataset ids + var dataset_selection = null; + + // collect dataset ids from input field + var value = self.app.field_list[input.id].value(); + if (typeof value === 'string') { + dataset_selection = { + id : value, + src : 'hda' + }; + } else { + // create array of dataset dictionaries for api submission + dataset_selection = []; + for (var i in value) { + dataset_selection.push({ + id : value[i], + src : 'hda' + }); + } } - add(job_input_id, input.id, value); + + // add final array to job definition + add(job_input_id, input.id, dataset_selection); break; // handle boolean input case 'boolean': @@ -118,7 +136,7 @@ // start conversion convert('', this.dict); - + console.log(this.job_def); // return result return this.job_def; }, diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/ui/ui-misc.js --- a/client/scripts/mvc/ui/ui-misc.js +++ b/client/scripts/mvc/ui/ui-misc.js @@ -1,6 +1,6 @@ // dependencies -define(['utils/utils', 'mvc/ui/ui-select-default', 'mvc/ui/ui-slider', 'mvc/ui/ui-checkbox', 'mvc/ui/ui-radiobutton', 'mvc/ui/ui-button-menu', 'mvc/ui/ui-modal'], - function(Utils, Select, Slider, Checkbox, RadioButton, ButtonMenu, Modal) { +define(['utils/utils', 'mvc/ui/ui-select-default', 'mvc/ui/ui-slider', 'mvc/ui/ui-options', 'mvc/ui/ui-button-menu', 'mvc/ui/ui-modal'], + function(Utils, Select, Slider, Options, ButtonMenu, Modal) { /** * This class contains backbone wrappers for basic ui elements such as Images, Labels, Buttons, Input fields etc. @@ -403,8 +403,8 @@ Label : Label, Message : Message, Modal : Modal, - RadioButton : RadioButton, - Checkbox : Checkbox, + RadioButton : Options.RadioButton, + Checkbox : Options.Checkbox, Searchbox : Searchbox, Select : Select, Hidden : Hidden, diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/ui/ui-select-default.js --- a/client/scripts/mvc/ui/ui-select-default.js +++ b/client/scripts/mvc/ui/ui-select-default.js @@ -172,7 +172,7 @@ // check if selected value exists exists: function(value) { - return this.$select.find('option[value=' + value + ']').length > 0; + return this.$select.find('option[value="' + value + '"]').length > 0; }, // change diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/upload/upload-ftp.js --- a/client/scripts/mvc/upload/upload-ftp.js +++ b/client/scripts/mvc/upload/upload-ftp.js @@ -31,10 +31,9 @@ // fill table _fill: function(ftp_files) { - if (ftp_files.length > 0) { // add table - this.$el.find('#upload-ftp-content').html($(this._template_table())); + this.$el.find('#upload-ftp-content').html($(this._templateTable())); // add files to table var size = 0; @@ -48,7 +47,7 @@ this.$el.find('#upload-ftp-disk').html(Utils.bytesToString (size, true)); } else { // add info - this.$el.find('#upload-ftp-content').html($(this._template_info())); + this.$el.find('#upload-ftp-content').html($(this._templateInfo())); } // hide spinner @@ -58,7 +57,7 @@ // add add: function(ftp_file) { // create new item - var $it = $(this._template_row(ftp_file)); + var $it = $(this._templateRow(ftp_file)); // append to table $(this.el).find('tbody').append($it); @@ -118,7 +117,7 @@ }, // template row - _template_row: function(options) { + _templateRow: function(options) { return '<tr>' + '<td><div id="upload-ftp-add"/></td>' + '<td style="width: 200px"><p style="width: inherit; word-wrap: break-word;">' + options.path + '</p></td>' + @@ -128,8 +127,7 @@ }, // load table template - _template_table: function() - { + _templateTable: function() { return '<span style="whitespace: nowrap; float: left;">Available files: </span>' + '<span style="whitespace: nowrap; float: right;">' + '<span class="upload-icon fa fa-file-text-o"/>' + @@ -151,16 +149,14 @@ }, // load table template - _template_info: function() - { + _templateInfo: function() { return '<div class="upload-ftp-warning warningmessage">' + 'Your FTP directory does not contain any files.' + '</div>'; }, // load html template - _template: function() - { + _template: function() { return '<div class="upload-ftp">' + '<div id="upload-ftp-wait" class="upload-ftp-wait fa fa-spinner fa-spin"/>' + '<div class="upload-ftp-help">This Galaxy server allows you to upload files via FTP. To upload some files, log in to the FTP server at <strong>' + this.app.options.ftp_upload_site + '</strong> using your Galaxy credentials (email address and password).</div>' + diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/upload/upload-row.js --- a/client/scripts/mvc/upload/upload-row.js +++ b/client/scripts/mvc/upload/upload-row.js @@ -214,16 +214,14 @@ // // genome - _refreshGenome: function() - { + _refreshGenome: function() { // update genome info on screen var genome = this.model.get('genome'); this.select_genome.value(genome); }, // progress - _refreshInfo: function() - { + _refreshInfo: function() { // write error message var info = this.model.get('info'); if (info) { @@ -234,8 +232,7 @@ }, // progress - _refreshPercentage : function() - { + _refreshPercentage : function() { var percentage = parseInt(this.model.get('percentage')); this.$el.find('.progress-bar').css({ width : percentage + '%' }); if (percentage != 100) @@ -245,8 +242,7 @@ }, // status - _refreshStatus : function() - { + _refreshStatus : function() { // get element var it = this.$el; @@ -315,8 +311,7 @@ }, // attach file info popup - _showExtensionInfo : function() - { + _showExtensionInfo : function() { // initialize var $el = $(this.el).find('#extension-info'); var extension = this.model.get('extension'); @@ -343,8 +338,7 @@ }, // attach file info popup - _showSettings : function() - { + _showSettings : function() { // check if popover is visible if (!this.settings.visible) { // show popover @@ -371,8 +365,7 @@ }, // template - _template: function(options) - { + _template: function(options) { return '<tr id="upload-item-' + options.id + '" class="upload-item">' + '<td>' + '<div style="position: relative;">' + diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/upload/upload-settings.js --- a/client/scripts/mvc/upload/upload-settings.js +++ b/client/scripts/mvc/upload/upload-settings.js @@ -25,12 +25,12 @@ // ui event: space to tabs this.$el.find('#upload-space-to-tabs').on('click', function() { - self._switch_state('#upload-space-to-tabs', 'space_to_tabs'); + self._switchState('#upload-space-to-tabs', 'space_to_tabs'); }); // ui event: to posix this.$el.find('#upload-to-posix-lines').on('click', function() { - self._switch_state('#upload-to-posix-lines', 'to_posix_lines'); + self._switchState('#upload-to-posix-lines', 'to_posix_lines'); }); // render @@ -45,8 +45,8 @@ // render render: function() { // render states - this._render_state('#upload-space-to-tabs', this.model.get('space_to_tabs')); - this._render_state('#upload-to-posix-lines', this.model.get('to_posix_lines')); + this._renderState('#upload-space-to-tabs', this.model.get('space_to_tabs')); + this._renderState('#upload-to-posix-lines', this.model.get('to_posix_lines')); // disable options var $cover = this.$el.find('#upload-settings-cover'); @@ -58,16 +58,16 @@ }, // switch state - _switch_state: function (element_id, parameter_id) { + _switchState: function (element_id, parameter_id) { if (this.model.get('status') == 'init') { var checked = !this.model.get(parameter_id); this.model.set(parameter_id, checked); - this._render_state(element_id, checked); + this._renderState(element_id, checked); } }, // render state - _render_state: function (element_id, checked) { + _renderState: function (element_id, checked) { // swith icon class var $it = this.$el.find(element_id); $it.removeClass(); @@ -79,8 +79,7 @@ }, // load template - _template: function() - { + _template: function() { return '<div class="upload-settings" style="position: relative;">' + '<div id="upload-settings-cover" class="upload-settings-cover"/>' + '<table class="table table-striped">' + diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 client/scripts/mvc/upload/upload-view.js --- a/client/scripts/mvc/upload/upload-view.js +++ b/client/scripts/mvc/upload/upload-view.js @@ -19,8 +19,7 @@ ) { // galaxy upload -return Backbone.View.extend( -{ +return Backbone.View.extend({ // options options : { nginx_upload_path : '' diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 display_applications/igv/bam.xml --- a/display_applications/igv/bam.xml +++ b/display_applications/igv/bam.xml @@ -12,15 +12,19 @@ <dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey --> - <filter>${dataset.dbkey in $site_dbkeys}</filter> - + <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter> + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bam_file" url="galaxy_${DATASET_HASH}.bam" /><param type="data" name="bai_file" url="galaxy_${DATASET_HASH}.bam.bai" metadata="bam_index" /><param type="template" name="site_organism" strip="True" > - $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ] + #if ($dataset.dbkey in $site_dbkeys) + $site_organisms[ $site_dbkeys.index( $bam_file.dbkey ) ] + #else: + $bam_file.dbkey + #end if </param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?> diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 display_applications/igv/vcf.xml --- a/display_applications/igv/vcf.xml +++ b/display_applications/igv/vcf.xml @@ -12,15 +12,19 @@ <dynamic_param name="site_organisms" value="4" split="True" separator="," /><!-- Filter out some of the links based upon matching site_dbkeys to dataset dbkey --> - <filter>${dataset.dbkey in $site_dbkeys}</filter> - + <filter>${$site_id.startswith( 'local_' ) or $dataset.dbkey in $site_dbkeys}</filter> + <!-- We define url and params as normal, but values defined in dynamic_param are available by specified name --><url>${redirect_url}</url><param type="data" name="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz" format="vcf_bgzip" /><param type="data" name="tabix_file" dataset="bgzip_file" url="galaxy_${DATASET_HASH}.vcf.gz.tbi" format="tabix" /><param type="template" name="site_organism" strip="True" > - $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ] + #if ($dataset.dbkey in $site_dbkeys) + $site_organisms[ $site_dbkeys.index( $bgzip_file.dbkey ) ] + #else: + $bgzip_file.dbkey + #end if </param><param type="template" name="jnlp" url="galaxy_${DATASET_HASH}.jnlp" viewable="True" mimetype="application/x-java-jnlp-file"><?xml version="1.0" encoding="utf-8"?> diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/tools/parameters/basic.py --- a/lib/galaxy/tools/parameters/basic.py +++ b/lib/galaxy/tools/parameters/basic.py @@ -794,6 +794,8 @@ if value is not None: if not isinstance( value, list ): value = [ value ] + # We could have an unvalidated value here when e.g. running a workflow. + value = [ val.value if isinstance( val, UnvalidatedValue ) else val for val in value ] field = form_builder.SelectField( self.name, self.multiple, self.display, self.refresh_on_change, refresh_on_change_values=self.refresh_on_change_values ) options = self.get_options( trans, context ) for text, optval, selected in options: diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py --- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py +++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py @@ -417,12 +417,13 @@ query = irmm.get_query_for_setting_metadata_on_repositories( order=False ) # Now reset metadata on all remaining repositories. for repository in query: - repository_id = trans.security.encode_id( repository.id ) try: - invalid_file_tups, metadata_dict = irmm.reset_all_metadata_on_installed_repository( repository_id ) - if invalid_file_tups: + irmm.set_repository( repository ) + irmm.reset_all_metadata_on_installed_repository() + irmm_invalid_file_tups = irmm.get_invalid_file_tups() + if irmm_invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, - invalid_file_tups, + irmm_invalid_file_tups, repository, None, as_html=False ) diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py --- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py +++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py @@ -1732,20 +1732,21 @@ tool_path, relative_install_dir = repository.get_tool_relative_path( trans.app ) if relative_install_dir: original_metadata_dict = repository.metadata - irmm = InstalledRepositoryMetadataManager( trans.app ) - metadata_dict, invalid_file_tups = \ - irmm.generate_metadata_for_changeset_revision( repository=repository, - changeset_revision=repository.changeset_revision, - repository_clone_url=repository_clone_url, - shed_config_dict = repository.get_shed_config_dict( trans.app ), - relative_install_dir=relative_install_dir, - repository_files_dir=None, - resetting_all_metadata_on_repository=False, - updating_installed_repository=False, - persist=False ) - repository.metadata = metadata_dict - if metadata_dict != original_metadata_dict: - irmm.update_in_shed_tool_config( repository ) + irmm = InstalledRepositoryMetadataManager( app=trans.app, + repository=repository, + changeset_revision=repository.changeset_revision, + repository_clone_url=repository_clone_url, + shed_config_dict = repository.get_shed_config_dict( trans.app ), + relative_install_dir=relative_install_dir, + repository_files_dir=None, + resetting_all_metadata_on_repository=False, + updating_installed_repository=False, + persist=False ) + irmm.generate_metadata_for_changeset_revision() + irmm_metadata_dict = irmm.get_metadata_dict() + if irmm_metadata_dict != original_metadata_dict: + repository.metadata = irmm_metadata_dict + irmm.update_in_shed_tool_config() trans.install_model.context.add( repository ) trans.install_model.context.flush() message = 'Metadata has been reset on repository <b>%s</b>.' % repository.name @@ -1938,22 +1939,24 @@ dmh.remove_from_data_manager( repository ) # Update the repository metadata. tpm = tool_panel_manager.ToolPanelManager( trans.app ) - irmm = InstalledRepositoryMetadataManager( trans.app, tpm ) - metadata_dict, invalid_file_tups = \ - irmm.generate_metadata_for_changeset_revision( repository=repository, - changeset_revision=latest_changeset_revision, - repository_clone_url=repository_clone_url, - shed_config_dict=repository.get_shed_config_dict( trans.app ), - relative_install_dir=relative_install_dir, - repository_files_dir=None, - resetting_all_metadata_on_repository=False, - updating_installed_repository=True, - persist=True ) - if 'tools' in metadata_dict: - tool_panel_dict = metadata_dict.get( 'tool_panel_section', None ) + irmm = InstalledRepositoryMetadataManager( app=trans.app, + tpm=tpm, + repository=repository, + changeset_revision=latest_changeset_revision, + repository_clone_url=repository_clone_url, + shed_config_dict=repository.get_shed_config_dict( trans.app ), + relative_install_dir=relative_install_dir, + repository_files_dir=None, + resetting_all_metadata_on_repository=False, + updating_installed_repository=True, + persist=True ) + irmm.generate_metadata_for_changeset_revision() + irmm_metadata_dict = irmm.get_metadata_dict() + if 'tools' in irmm_metadata_dict: + tool_panel_dict = irmm_metadata_dict.get( 'tool_panel_section', None ) if tool_panel_dict is None: tool_panel_dict = tpm.generate_tool_panel_dict_from_shed_tool_conf_entries( repository ) - repository_tools_tups = irmm.get_repository_tools_tups( metadata_dict ) + repository_tools_tups = irmm.get_repository_tools_tups() tpm.add_to_tool_panel( repository_name=str( repository.name ), repository_clone_url=repository_clone_url, changeset_revision=str( repository.installed_changeset_revision ), @@ -1963,18 +1966,18 @@ tool_panel_dict=tool_panel_dict, new_install=False ) # Add new Data Manager entries - if 'data_manager' in metadata_dict: + if 'data_manager' in irmm_metadata_dict: dmh = data_manager.DataManagerHandler( trans.app ) new_data_managers = dmh.install_data_managers( trans.app.config.shed_data_manager_config_file, - metadata_dict, + irmm_metadata_dict, repository.get_shed_config_dict( trans.app ), os.path.join( relative_install_dir, name ), repository, repository_tools_tups ) - if 'repository_dependencies' in metadata_dict or 'tool_dependencies' in metadata_dict: - new_repository_dependencies_dict = metadata_dict.get( 'repository_dependencies', {} ) + if 'repository_dependencies' in irmm_metadata_dict or 'tool_dependencies' in irmm_metadata_dict: + new_repository_dependencies_dict = irmm_metadata_dict.get( 'repository_dependencies', {} ) new_repository_dependencies = new_repository_dependencies_dict.get( 'repository_dependencies', [] ) - new_tool_dependencies_dict = metadata_dict.get( 'tool_dependencies', {} ) + new_tool_dependencies_dict = irmm_metadata_dict.get( 'tool_dependencies', {} ) if new_repository_dependencies: # [[http://localhost:9009', package_picard_1_56_0', devteam', 910b0b056666', False', False']] proceed_to_install = False @@ -2017,7 +2020,7 @@ updating_repository_id=trans.security.encode_id( repository.id ), updating_to_ctx_rev=latest_ctx_rev, updating_to_changeset_revision=latest_changeset_revision, - encoded_updated_metadata=encoding_util.tool_shed_encode( metadata_dict ), + encoded_updated_metadata=encoding_util.tool_shed_encode( irmm_metadata_dict ), updating=True ) return self.prepare_for_install( trans, **new_kwd ) # Updates received did not include any newly defined repository dependencies but did include @@ -2033,12 +2036,12 @@ proceed_to_install = True break if proceed_to_install: - encoded_tool_dependencies_dict = encoding_util.tool_shed_encode( metadata_dict.get( 'tool_dependencies', {} ) ) + encoded_tool_dependencies_dict = encoding_util.tool_shed_encode( irmm_metadata_dict.get( 'tool_dependencies', {} ) ) encoded_relative_install_dir = encoding_util.tool_shed_encode( relative_install_dir ) new_kwd = dict( updating_repository_id=trans.security.encode_id( repository.id ), updating_to_ctx_rev=latest_ctx_rev, updating_to_changeset_revision=latest_changeset_revision, - encoded_updated_metadata=encoding_util.tool_shed_encode( metadata_dict ), + encoded_updated_metadata=encoding_util.tool_shed_encode( irmm_metadata_dict ), encoded_relative_install_dir=encoded_relative_install_dir, encoded_tool_dependencies_dict=encoded_tool_dependencies_dict, message=message, @@ -2047,7 +2050,7 @@ # Updates received did not include any newly defined repository dependencies or newly defined # tool dependencies that need to be installed. repository = trans.app.update_repository_manager.update_repository_record( repository=repository, - updated_metadata_dict=metadata_dict, + updated_metadata_dict=irmm_metadata_dict, updated_changeset_revision=latest_changeset_revision, updated_ctx_rev=latest_ctx_rev ) message = "The installed repository named '%s' has been updated to change set revision '%s'. " % \ diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/webapps/tool_shed/api/repositories.py --- a/lib/galaxy/webapps/tool_shed/api/repositories.py +++ b/lib/galaxy/webapps/tool_shed/api/repositories.py @@ -429,13 +429,13 @@ def handle_repository( trans, rmm, repository, results ): log.debug( "Resetting metadata on repository %s" % str( repository.name ) ) - repository_id = trans.security.encode_id( repository.id ) try: - invalid_file_tups, metadata_dict = \ - rmm.reset_all_metadata_on_repository_in_tool_shed( repository_id ) - if invalid_file_tups: + rmm.set_repository( repository ) + rmm.reset_all_metadata_on_repository_in_tool_shed() + rmm_invalid_file_tups = rmm.get_invalid_file_tups() + if rmm_invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, - invalid_file_tups, + rmm_invalid_file_tups, repository, None, as_html=False ) @@ -451,7 +451,11 @@ status = '%s : %s' % ( str( repository.name ), message ) results[ 'repository_status' ].append( status ) return results - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) + rmm = repository_metadata_manager.RepositoryMetadataManager( app=trans.app, + user=trans.user, + resetting_all_metadata_on_repository=True, + updating_installed_repository=False, + persist=False ) start_time = strftime( "%Y-%m-%d %H:%M:%S" ) results = dict( start_time=start_time, repository_status=[], @@ -511,12 +515,17 @@ results = dict( start_time=start_time, repository_status=[] ) try: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) - invalid_file_tups, metadata_dict = \ - rmm.reset_all_metadata_on_repository_in_tool_shed( trans.security.encode_id( repository.id ) ) - if invalid_file_tups: + rmm = repository_metadata_manager.RepositoryMetadataManager( app=trans.app, + user=trans.user, + repository=repository, + resetting_all_metadata_on_repository=True, + updating_installed_repository=False, + persist=False ) + rmm.reset_all_metadata_on_repository_in_tool_shed() + rmm_invalid_file_tups = rmm.get_invalid_file_tups() + if rmm_invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, - invalid_file_tups, + rmm_invalid_file_tups, repository, None, as_html=False ) diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/webapps/tool_shed/controllers/hg.py --- a/lib/galaxy/webapps/tool_shed/controllers/hg.py +++ b/lib/galaxy/webapps/tool_shed/controllers/hg.py @@ -1,6 +1,8 @@ import os, logging from galaxy import web from galaxy.web.base.controller import BaseUIController + +from tool_shed.util.common_util import generate_clone_url_for_repository_in_tool_shed from tool_shed.util.shed_util_common import get_repository_by_name_and_owner from tool_shed.util.hg_util import update_repository from tool_shed.metadata import repository_metadata_manager @@ -47,9 +49,19 @@ # interface will result in a new head being created. repo = hg.repository( ui.ui(), repository.repo_path( trans.app ) ) update_repository( repo, ctx_rev=None ) + repository_clone_url = generate_clone_url_for_repository_in_tool_shed( trans.user, repository ) # Set metadata using the repository files on disk. - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) - error_message, status = rmm.set_repository_metadata( trans.request.host, repository ) + rmm = repository_metadata_manager.RepositoryMetadataManager( app=trans.app, + user=trans.user, + repository=repository, + changeset_revision=repository.tip( trans.app ), + repository_clone_url=repository_clone_url, + relative_install_dir=repository.repo_path( trans.app ), + repository_files_dir=None, + resetting_all_metadata_on_repository=False, + updating_installed_repository=False, + persist=False ) + error_message, status = rmm.set_repository_metadata( trans.request.host ) if status == 'ok' and error_message: log.debug( "Successfully reset metadata on repository %s owned by %s, but encountered problem: %s" % \ ( str( repository.name ), str( repository.user.username ), error_message ) ) diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/webapps/tool_shed/controllers/repository.py --- a/lib/galaxy/webapps/tool_shed/controllers/repository.py +++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py @@ -2759,15 +2759,18 @@ def reset_all_metadata( self, trans, id, **kwd ): """Reset all metadata on the complete changelog for a single repository in the tool shed.""" # This method is called only from the ~/templates/webapps/tool_shed/repository/manage_repository.mako template. - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) - invalid_file_tups, metadata_dict = \ - rmm.reset_all_metadata_on_repository_in_tool_shed( id ) - if invalid_file_tups: - repository = suc.get_repository_in_tool_shed( trans.app, id ) + repository = suc.get_repository_in_tool_shed( trans.app, id ) + rmm = repository_metadata_manager.RepositoryMetadataManager( app=trans.app, + user=trans.user, + repository=repository ) + rmm.reset_all_metadata_on_repository_in_tool_shed() + rmm_metadata_dict = rmm.get_metadata_dict() + rmm_invalid_file_tups = rmm.get_invalid_file_tups() + if rmm_invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( trans.app, - invalid_file_tups, + rmm_invalid_file_tups, repository, - metadata_dict ) + rmm_metadata_dict ) status = 'error' else: message = "All repository metadata has been reset. " @@ -2849,10 +2852,10 @@ if tip == repository.tip( trans.app ): message += 'No changes to repository. ' else: - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) - status, error_message = rmm.set_repository_metadata_due_to_new_tip( trans.request.host, - repository, - **kwd ) + rmm = repository_metadata_manager.RepositoryMetadataManager( app=trans.app, + user=trans.user, + repository=repository ) + status, error_message = rmm.set_repository_metadata_due_to_new_tip( trans.request.host, **kwd ) if error_message: message = error_message else: diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/galaxy/webapps/tool_shed/controllers/upload.py --- a/lib/galaxy/webapps/tool_shed/controllers/upload.py +++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py @@ -263,10 +263,11 @@ ( len( files_to_remove ), upload_point ) else: message += " %d files were removed from the repository root. " % len( files_to_remove ) - rmm = repository_metadata_manager.RepositoryMetadataManager( trans.app, trans.user ) + rmm = repository_metadata_manager.RepositoryMetadataManager( app=trans.app, + user=trans.user, + repository=repository ) status, error_message = \ rmm.set_repository_metadata_due_to_new_tip( trans.request.host, - repository, content_alert_str=content_alert_str, **kwd ) if error_message: diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/tool_shed/capsule/capsule_manager.py --- a/lib/tool_shed/capsule/capsule_manager.py +++ b/lib/tool_shed/capsule/capsule_manager.py @@ -792,9 +792,10 @@ results_dict[ 'ok' ] = False results_dict[ 'error_message' ] += error_message try: - rmm = repository_metadata_manager.RepositoryMetadataManager( self.app, self.user ) + rmm = repository_metadata_manager.RepositoryMetadataManager( app=self.app, + user=self.user, + repository=repository ) status, error_message = rmm.set_repository_metadata_due_to_new_tip( self.host, - repository, content_alert_str=content_alert_str ) if error_message: results_dict[ 'ok' ] = False diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/tool_shed/galaxy_install/install_manager.py --- a/lib/tool_shed/galaxy_install/install_manager.py +++ b/lib/tool_shed/galaxy_install/install_manager.py @@ -510,31 +510,33 @@ """ shed_config_dict = self.app.toolbox.get_shed_config_dict_by_filename( shed_tool_conf ) tdtm = data_table_manager.ToolDataTableManager( self.app ) - irmm = InstalledRepositoryMetadataManager( self.app, self.tpm ) - metadata_dict, invalid_file_tups = \ - irmm.generate_metadata_for_changeset_revision( repository=tool_shed_repository, - changeset_revision=tool_shed_repository.changeset_revision, - repository_clone_url=repository_clone_url, - shed_config_dict=shed_config_dict, - relative_install_dir=relative_install_dir, - repository_files_dir=None, - resetting_all_metadata_on_repository=False, - updating_installed_repository=False, - persist=True ) - tool_shed_repository.metadata = metadata_dict + irmm = InstalledRepositoryMetadataManager( app=self.app, + tpm=self.tpm, + repository=tool_shed_repository, + changeset_revision=tool_shed_repository.changeset_revision, + repository_clone_url=repository_clone_url, + shed_config_dict=shed_config_dict, + relative_install_dir=relative_install_dir, + repository_files_dir=None, + resetting_all_metadata_on_repository=False, + updating_installed_repository=False, + persist=True ) + irmm.generate_metadata_for_changeset_revision() + irmm_metadata_dict = irmm.get_metadata_dict() + tool_shed_repository.metadata = irmm_metadata_dict # Update the tool_shed_repository.tool_shed_status column in the database. tool_shed_status_dict = suc.get_tool_shed_status_for_installed_repository( self.app, tool_shed_repository ) if tool_shed_status_dict: tool_shed_repository.tool_shed_status = tool_shed_status_dict self.install_model.context.add( tool_shed_repository ) self.install_model.context.flush() - if 'tool_dependencies' in metadata_dict and not reinstalling: + if 'tool_dependencies' in irmm_metadata_dict and not reinstalling: tool_dependencies = tool_dependency_util.create_tool_dependency_objects( self.app, tool_shed_repository, relative_install_dir, set_status=True ) - if 'sample_files' in metadata_dict: - sample_files = metadata_dict.get( 'sample_files', [] ) + if 'sample_files' in irmm_metadata_dict: + sample_files = irmm_metadata_dict.get( 'sample_files', [] ) tool_index_sample_files = tdtm.get_tool_index_sample_files( sample_files ) tool_data_table_conf_filename, tool_data_table_elems = \ tdtm.install_tool_data_tables( tool_shed_repository, tool_index_sample_files ) @@ -543,13 +545,13 @@ None, self.app.config.shed_tool_data_table_config, persist=True ) - if 'tools' in metadata_dict: - tool_panel_dict = self.tpm.generate_tool_panel_dict_for_new_install( metadata_dict[ 'tools' ], tool_section ) - sample_files = metadata_dict.get( 'sample_files', [] ) + if 'tools' in irmm_metadata_dict: + tool_panel_dict = self.tpm.generate_tool_panel_dict_for_new_install( irmm_metadata_dict[ 'tools' ], tool_section ) + sample_files = irmm_metadata_dict.get( 'sample_files', [] ) tool_index_sample_files = tdtm.get_tool_index_sample_files( sample_files ) tool_util.copy_sample_files( self.app, tool_index_sample_files, tool_path=tool_path ) sample_files_copied = [ str( s ) for s in tool_index_sample_files ] - repository_tools_tups = irmm.get_repository_tools_tups( metadata_dict ) + repository_tools_tups = irmm.get_repository_tools_tups() if repository_tools_tups: # Handle missing data table entries for tool parameters that are dynamically generated select lists. repository_tools_tups = tdtm.handle_missing_data_table_entry( relative_install_dir, @@ -575,15 +577,15 @@ shed_tool_conf=shed_tool_conf, tool_panel_dict=tool_panel_dict, new_install=True ) - if 'data_manager' in metadata_dict: + if 'data_manager' in irmm_metadata_dict: dmh = data_manager.DataManagerHandler( self.app ) new_data_managers = dmh.install_data_managers( self.app.config.shed_data_manager_config_file, - metadata_dict, + irmm_metadata_dict, shed_config_dict, relative_install_dir, tool_shed_repository, repository_tools_tups ) - if 'datatypes' in metadata_dict: + if 'datatypes' in irmm_metadata_dict: tool_shed_repository.status = self.install_model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES if not tool_shed_repository.includes_datatypes: tool_shed_repository.includes_datatypes = True @@ -604,7 +606,7 @@ name=tool_shed_repository.name, owner=tool_shed_repository.owner, installed_changeset_revision=tool_shed_repository.installed_changeset_revision, - tool_dicts=metadata_dict.get( 'tools', [] ), + tool_dicts=irmm_metadata_dict.get( 'tools', [] ), converter_path=converter_path, display_path=display_path ) if converter_path: diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/tool_shed/galaxy_install/installed_repository_manager.py --- a/lib/tool_shed/galaxy_install/installed_repository_manager.py +++ b/lib/tool_shed/galaxy_install/installed_repository_manager.py @@ -82,9 +82,12 @@ repository.status = self.install_model.ToolShedRepository.installation_status.INSTALLED if repository.includes_tools_for_display_in_tool_panel: tpm = tool_panel_manager.ToolPanelManager( self.app ) - irmm = InstalledRepositoryMetadataManager( self.app, tpm ) - metadata = repository.metadata - repository_tools_tups = irmm.get_repository_tools_tups( metadata ) + irmm = InstalledRepositoryMetadataManager( app=self.app, + tpm=tpm, + repository=repository, + changeset_revision=repository.changeset_revision, + metadata_dict=repository.metadata ) + repository_tools_tups = irmm.get_repository_tools_tups() # Reload tools into the appropriate tool panel section. tool_panel_dict = repository.metadata[ 'tool_panel_section' ] tpm.add_to_tool_panel( repository.name, @@ -101,7 +104,7 @@ data_manager_relative_install_dir = os.path.join( data_manager_relative_install_dir, repository.name ) dmh = data_manager.DataManagerHandler( self.app ) new_data_managers = dmh.install_data_managers( self.app.config.shed_data_manager_config_file, - metadata, + repository.metadata, repository.get_shed_config_dict( self.app ), data_manager_relative_install_dir, repository, diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py --- a/lib/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py +++ b/lib/tool_shed/galaxy_install/metadata/installed_repository_metadata_manager.py @@ -19,9 +19,16 @@ class InstalledRepositoryMetadataManager( metadata_generator.MetadataGenerator ): - def __init__( self, app, tpm=None ): - super( InstalledRepositoryMetadataManager, self ).__init__( app ) - self.app = app + def __init__( self, app, tpm=None, repository=None, changeset_revision=None, repository_clone_url=None, + shed_config_dict=None, relative_install_dir=None, repository_files_dir=None, + resetting_all_metadata_on_repository=False, updating_installed_repository=False, + persist=False, metadata_dict=None ): + super( InstalledRepositoryMetadataManager, self ).__init__( app, repository, changeset_revision, + repository_clone_url, shed_config_dict, + relative_install_dir, repository_files_dir, + resetting_all_metadata_on_repository, + updating_installed_repository, persist, + metadata_dict=metadata_dict, user=None ) if tpm is None: self.tpm = tool_panel_manager.ToolPanelManager( self.app ) else: @@ -53,15 +60,15 @@ return self.app.install_model.context.query( self.app.install_model.ToolShedRepository ) \ .filter( self.app.install_model.ToolShedRepository.table.c.uninstalled == False ) - def get_repository_tools_tups( self, metadata_dict ): + def get_repository_tools_tups( self ): """ Return a list of tuples of the form (relative_path, guid, tool) for each tool defined in the received tool shed repository metadata. """ repository_tools_tups = [] - index, shed_conf_dict = self.tpm.get_shed_tool_conf_dict( metadata_dict.get( 'shed_config_filename' ) ) - if 'tools' in metadata_dict: - for tool_dict in metadata_dict[ 'tools' ]: + index, shed_conf_dict = self.tpm.get_shed_tool_conf_dict( self.metadata_dict.get( 'shed_config_filename' ) ) + if 'tools' in self.metadata_dict: + for tool_dict in self.metadata_dict[ 'tools' ]: load_relative_path = relative_path = tool_dict.get( 'tool_config', None ) if shed_conf_dict.get( 'tool_path' ): load_relative_path = os.path.join( shed_conf_dict.get( 'tool_path' ), relative_path ) @@ -74,36 +81,21 @@ repository_tools_tups.append( ( relative_path, guid, tool ) ) return repository_tools_tups - def reset_all_metadata_on_installed_repository( self, id ): + def reset_all_metadata_on_installed_repository( self ): """Reset all metadata on a single tool shed repository installed into a Galaxy instance.""" - invalid_file_tups = [] - metadata_dict = {} - repository = repository_util.get_installed_tool_shed_repository( self.app, id ) - repository_clone_url = common_util.generate_clone_url_for_installed_repository( self.app, repository ) - tool_path, relative_install_dir = repository.get_tool_relative_path( self.app ) - if relative_install_dir: - original_metadata_dict = repository.metadata - metadata_dict, invalid_file_tups = \ - self.generate_metadata_for_changeset_revision( repository=repository, - changeset_revision=repository.changeset_revision, - repository_clone_url=repository_clone_url, - shed_config_dict = repository.get_shed_config_dict( self.app ), - relative_install_dir=relative_install_dir, - repository_files_dir=None, - resetting_all_metadata_on_repository=False, - updating_installed_repository=False, - persist=False ) - repository.metadata = metadata_dict - if metadata_dict != original_metadata_dict: - self.update_in_shed_tool_config( repository ) - self.app.install_model.context.add( repository ) + if self.relative_install_dir: + original_metadata_dict = self.repository.metadata + self.generate_metadata_for_changeset_revision() + if self.metadata_dict != original_metadata_dict: + self.repository.metadata = self.metadata_dict + self.update_in_shed_tool_config() + self.app.install_model.context.add( self.repository ) self.app.install_model.context.flush() - log.debug( 'Metadata has been reset on repository %s.' % repository.name ) + log.debug( 'Metadata has been reset on repository %s.' % self.repository.name ) else: - log.debug( 'Metadata did not need to be reset on repository %s.' % repository.name ) + log.debug( 'Metadata did not need to be reset on repository %s.' % self.repository.name ) else: - log.debug( 'Error locating installation directory for repository %s.' % repository.name ) - return invalid_file_tups, metadata_dict + log.debug( 'Error locating installation directory for repository %s.' % self.repository.name ) def reset_metadata_on_selected_repositories( self, user, **kwd ): """ @@ -119,19 +111,19 @@ for repository_id in repository_ids: try: repository = repository_util.get_installed_tool_shed_repository( self.app, repository_id ) - owner = str( repository.owner ) - invalid_file_tups, metadata_dict = \ - self.reset_all_metadata_on_installed_repository( repository_id ) - if invalid_file_tups: + self.set_repository( repository ) + self.reset_all_metadata_on_installed_repository() + if self.invalid_file_tups: message = tool_util.generate_message_for_invalid_tools( self.app, - invalid_file_tups, + self.invalid_file_tups, repository, None, as_html=False ) log.debug( message ) unsuccessful_count += 1 else: - log.debug( "Successfully reset metadata on repository %s owned by %s" % ( str( repository.name ), owner ) ) + log.debug( "Successfully reset metadata on repository %s owned by %s" % \ + ( str( repository.name ), str( repository.owner ) ) ) successful_count += 1 except: log.exception( "Error attempting to reset metadata on repository %s", str( repository.name ) ) @@ -146,32 +138,37 @@ status = 'error' return message, status - def tool_shed_from_repository_clone_url( self, repository_clone_url ): + def set_repository( self, repository ): + super( InstalledRepositoryMetadataManager, self ).set_repository( repository ) + self.repository_clone_url = common_util.generate_clone_url_for_installed_repository( self.app, repository ) + + def tool_shed_from_repository_clone_url( self ): """Given a repository clone URL, return the tool shed that contains the repository.""" - return common_util.remove_protocol_and_user_from_clone_url( repository_clone_url ).split( '/repos/' )[ 0 ].rstrip( '/' ) + cleaned_repository_clone_url = common_util.remove_protocol_and_user_from_clone_url( self.repository_clone_url ) + return common_util.remove_protocol_and_user_from_clone_url( cleaned_repository_clone_url ).split( '/repos/' )[ 0 ].rstrip( '/' ) - def update_in_shed_tool_config( self, repository ): + def update_in_shed_tool_config( self ): """ A tool shed repository is being updated so change the shed_tool_conf file. Parse the config file to generate the entire list of config_elems instead of using the in-memory list. """ - shed_conf_dict = repository.get_shed_config_dict( self.app ) + shed_conf_dict = self.repository.get_shed_config_dict( self.app ) shed_tool_conf = shed_conf_dict[ 'config_filename' ] tool_path = shed_conf_dict[ 'tool_path' ] - tool_panel_dict = self.tpm.generate_tool_panel_dict_from_shed_tool_conf_entries( repository ) - repository_tools_tups = self.get_repository_tools_tups( repository.metadata ) - clone_url = common_util.generate_clone_url_for_installed_repository( self.app, repository ) - cleaned_repository_clone_url = common_util.remove_protocol_and_user_from_clone_url( clone_url ) - tool_shed = self.tool_shed_from_repository_clone_url( cleaned_repository_clone_url ) - owner = repository.owner + tool_panel_dict = self.tpm.generate_tool_panel_dict_from_shed_tool_conf_entries( self.repository ) + repository_tools_tups = self.get_repository_tools_tups() + clone_url = common_util.generate_clone_url_for_installed_repository( self.app, self.repository ) + tool_shed = self.tool_shed_from_repository_clone_url() + owner = self.repository.owner if not owner: + cleaned_repository_clone_url = common_util.remove_protocol_and_user_from_clone_url( clone_url ) owner = suc.get_repository_owner( cleaned_repository_clone_url ) guid_to_tool_elem_dict = {} for tool_config_filename, guid, tool in repository_tools_tups: guid_to_tool_elem_dict[ guid ] = self.tpm.generate_tool_elem( tool_shed, - repository.name, - repository.changeset_revision, - repository.owner or '', + self.repository.name, + self.repository.changeset_revision, + self.repository.owner or '', tool_config_filename, tool, None ) diff -r f535ef20718d82ab374408d492afa917324a22c5 -r ba66d120d001d6531300f57f215210056481f368 lib/tool_shed/galaxy_install/tool_migration_manager.py --- a/lib/tool_shed/galaxy_install/tool_migration_manager.py +++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py @@ -416,21 +416,23 @@ log.exception( "Exception attempting to filter and persist non-shed-related tool panel configs:\n%s" % str( e ) ) finally: lock.release() - irmm = InstalledRepositoryMetadataManager( self.app, self.tpm ) - metadata_dict, invalid_file_tups = \ - irmm.generate_metadata_for_changeset_revision( repository=tool_shed_repository, - changeset_revision=tool_shed_repository.changeset_revision, - repository_clone_url=repository_clone_url, - shed_config_dict = self.shed_config_dict, - relative_install_dir=relative_install_dir, - repository_files_dir=None, - resetting_all_metadata_on_repository=False, - updating_installed_repository=False, - persist=True ) - tool_shed_repository.metadata = metadata_dict + irmm = InstalledRepositoryMetadataManager( app=self.app, + tpm=self.tpm, + repository=tool_shed_repository, + changeset_revision=tool_shed_repository.changeset_revision, + repository_clone_url=repository_clone_url, + shed_config_dict = self.shed_config_dict, + relative_install_dir=relative_install_dir, + repository_files_dir=None, + resetting_all_metadata_on_repository=False, + updating_installed_repository=False, + persist=True ) + irmm.generate_metadata_for_changeset_revision() + irmm_metadata_dict = irmm.get_metadata_dict() + tool_shed_repository.metadata = irmm_metadata_dict self.app.install_model.context.add( tool_shed_repository ) self.app.install_model.context.flush() - has_tool_dependencies = self.__has_tool_dependencies( metadata_dict ) + has_tool_dependencies = self.__has_tool_dependencies( irmm_metadata_dict ) if has_tool_dependencies: # All tool_dependency objects must be created before the tools are processed even if no # tool dependencies will be installed. @@ -440,14 +442,14 @@ set_status=True ) else: tool_dependencies = None - if 'tools' in metadata_dict: + if 'tools' in irmm_metadata_dict: tdtm = data_table_manager.ToolDataTableManager( self.app ) - sample_files = metadata_dict.get( 'sample_files', [] ) + sample_files = irmm_metadata_dict.get( 'sample_files', [] ) sample_files = [ str( s ) for s in sample_files ] tool_index_sample_files = tdtm.get_tool_index_sample_files( sample_files ) tool_util.copy_sample_files( self.app, tool_index_sample_files, tool_path=self.tool_path ) sample_files_copied = [ s for s in tool_index_sample_files ] - repository_tools_tups = irmm.get_repository_tools_tups( metadata_dict ) + repository_tools_tups = irmm.get_repository_tools_tups() if repository_tools_tups: # Handle missing data table entries for tool parameters that are dynamically # generated select lists. @@ -491,7 +493,7 @@ if installed_tool_dependency.status == self.app.install_model.ToolDependency.installation_status.ERROR: print '\nThe ToolMigrationManager returned the following error while installing tool dependency ', installed_tool_dependency.name, ':' print installed_tool_dependency.error_message, '\n\n' - if 'datatypes' in metadata_dict: + if 'datatypes' in irmm_metadata_dict: cdl = custom_datatype_manager.CustomDatatypeLoader( self.app ) tool_shed_repository.status = self.app.install_model.ToolShedRepository.installation_status.LOADING_PROPRIETARY_DATATYPES if not tool_shed_repository.includes_datatypes: @@ -514,7 +516,7 @@ name=tool_shed_repository.name, owner=self.repository_owner, installed_changeset_revision=tool_shed_repository.installed_changeset_revision, - tool_dicts=metadata_dict.get( 'tools', [] ), + tool_dicts=irmm_metadata_dict.get( 'tools', [] ), converter_path=converter_path, display_path=display_path ) if converter_path: This diff is so big that we needed to truncate the remainder. https://bitbucket.org/galaxy/galaxy-central/commits/773bae7768c1/ Changeset: 773bae7768c1 User: carlfeberhard Date: 2014-09-16 15:40:13 Summary: Move client/scripts to client/galaxy/scripts Affected #: 325 files diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/GruntFile.js --- a/client/GruntFile.js +++ b/client/GruntFile.js @@ -7,7 +7,7 @@ copy: { main: { expand: true, - cwd: 'scripts/', + cwd: 'galaxy/scripts/', src: '**', dest: '../static/scripts/' } diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/galaxy/scripts/base.js --- /dev/null +++ b/client/galaxy/scripts/base.js @@ -0,0 +1,15 @@ +define( ["libs/backbone/backbone"], function( Backbone ) { + + var Base = function() { + if( this.initialize ) { + this.initialize.apply(this, arguments); + } + }; + Base.extend = Backbone.Model.extend; + + return { + Base: Base, + Backbone: Backbone + }; + +}); \ No newline at end of file diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/galaxy/scripts/galaxy-app-base.js --- /dev/null +++ b/client/galaxy/scripts/galaxy-app-base.js @@ -0,0 +1,160 @@ +define([ + 'mvc/user/user-model', + 'utils/metrics-logger', + 'utils/add-logging', + 'utils/localization', + 'bootstrapped-data' +], function( userModel, metricsLogger, addLogging, localize, bootstrapped ){ +// ============================================================================ +/** Base galaxy client-side application. + * Iniitializes: + * logger : the logger/metrics-logger + * localize : the string localizer + * config : the current configuration (any k/v in + * universe_wsgi.ini available from the configuration API) + * user : the current user (as a mvc/user/user-model) + */ +function GalaxyApp( options ){ + var self = this; + return self._init( options || {} ); +} + +// add logging shortcuts for this object +addLogging( GalaxyApp, 'GalaxyApp' ); + +/** default options */ +GalaxyApp.prototype.defaultOptions = { + /** monkey patch attributes from existing window.Galaxy object? */ + patchExisting : true, + /** root url of this app */ + // move to self.root? + root : '/' +}; + +/** initalize options and sub-components */ +GalaxyApp.prototype._init = function init( options ){ + var self = this; + _.extend( self, Backbone.Events ); + + self._processOptions( options ); + self.debug( 'GalaxyApp.options: ', self.options ); + + self._patchGalaxy( window.Galaxy ); + + self._initLogger( options.loggerOptions || {} ); + self.debug( 'GalaxyApp.logger: ', self.logger ); + + self._initLocale(); + self.debug( 'GalaxyApp.localize: ', self.localize ); + + self.config = options.config || bootstrapped.config || {}; + self.debug( 'GalaxyApp.config: ', self.config ); + + self._initUser( options.user || bootstrapped.user || {} ); + self.debug( 'GalaxyApp.user: ', self.user ); + + //TODO: temp + self.trigger( 'ready', self ); + //if( typeof options.onload === 'function' ){ + // options.onload(); + //} + + self._setUpListeners(); + + return self; +}; + +/** add an option from options if the key matches an option in defaultOptions */ +GalaxyApp.prototype._processOptions = function _processOptions( options ){ + var self = this, + defaults = self.defaultOptions; + self.debug( '_processOptions: ', options ); + + self.options = {}; + for( var k in defaults ){ + if( defaults.hasOwnProperty( k ) ){ + self.options[ k ] = ( options.hasOwnProperty( k ) )?( options[ k ] ):( defaults[ k ] ); + } + } + return self; +}; + +/** add an option from options if the key matches an option in defaultOptions */ +GalaxyApp.prototype._patchGalaxy = function _processOptions( patchWith ){ + var self = this; + // in case req or plain script tag order has created a prev. version of the Galaxy obj... + if( self.options.patchExisting && patchWith ){ + self.debug( 'found existing Galaxy object:', patchWith ); + // ...(for now) monkey patch any added attributes that the previous Galaxy may have had + //TODO: move those attributes to more formal assignment in GalaxyApp + for( var k in patchWith ){ + if( patchWith.hasOwnProperty( k ) ){ + self.debug( '\t patching in ' + k + ' to Galaxy' ); + self[ k ] = patchWith[ k ]; + } + } + } +}; + +/** set up the metrics logger (utils/metrics-logger) and pass loggerOptions */ +GalaxyApp.prototype._initLogger = function _initLogger( loggerOptions ){ + var self = this; + self.debug( '_initLogger:', loggerOptions ); + self.logger = new metricsLogger.MetricsLogger( loggerOptions ); + return self; +}; + +/** add the localize fn to this object and the window namespace (as '_l') */ +GalaxyApp.prototype._initLocale = function _initLocale( options ){ + var self = this; + self.debug( '_initLocale:', options ); + self.localize = localize; + // add to window as global shortened alias + window._l = self.localize; + return self; +}; + +/** set up the current user as a Backbone model (mvc/user/user-model) */ +GalaxyApp.prototype._initUser = function _initUser( userJSON ){ + var self = this; + self.debug( '_initUser:', userJSON ); + self.user = new userModel.User( userJSON ); + //TODO: temp - old alias + self.currUser = self.user; + return self; +}; + +/** Set up DOM/jQuery/Backbone event listeners enabled for all pages */ +GalaxyApp.prototype._setUpListeners = function _setUpListeners(){ + var self = this; + + // hook to jq beforeSend to record the most recent ajax call and cache some data about it + /** cached info about the last ajax call made through jQuery */ + self.lastAjax = {}; + $( document ).bind( 'ajaxSend', function( ev, xhr, options ){ + var data = options.data; + try { + data = JSON.parse( data ); + } catch( err ){} + + self.lastAjax = { + url : location.href.slice( 0, -1 ) + options.url, + data : data + }; + //TODO:?? we might somehow manage to *retry* ajax using either this hook or Backbone.sync + }); + +}; + +/** string rep */ +GalaxyApp.prototype.toString = function toString(){ + var userEmail = this.user.get( 'email' ) || '(anonymous)'; + return 'GalaxyApp(' + userEmail + ')'; +}; + + +// ============================================================================ + return { + GalaxyApp : GalaxyApp + }; +}); diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/galaxy/scripts/galaxy.autocom_tagging.js --- /dev/null +++ b/client/galaxy/scripts/galaxy.autocom_tagging.js @@ -0,0 +1,368 @@ +/** +* JQuery extension for tagging with autocomplete. +* @author: Jeremy Goecks +* @require: jquery.autocomplete plugin +*/ +// +// Initialize "tag click functions" for tags. +// +function init_tag_click_function(tag_elt, click_func) { + $(tag_elt).find('.tag-name').each( function() { + $(this).click( function() { + var tag_str = $(this).text(); + var tag_name_and_value = tag_str.split(":"); + click_func(tag_name_and_value[0], tag_name_and_value[1]); + return true; + }); + }); +} + +jQuery.fn.autocomplete_tagging = function(options) { + + var defaults = { + get_toggle_link_text_fn: function(tags) { + var text = ""; + var num_tags = obj_length(tags); + if (num_tags > 0) { + text = num_tags + (num_tags > 1 ? " Tags" : " Tag"); + } else { + text = "Add tags"; + } + return text; + }, + tag_click_fn : function (name, value) {}, + editable: true, + input_size: 20, + in_form: false, + tags : {}, + use_toggle_link: true, + item_id: "", + add_tag_img: "", + add_tag_img_rollover: "", + delete_tag_img: "", + ajax_autocomplete_tag_url: "", + ajax_retag_url: "", + ajax_delete_tag_url: "", + ajax_add_tag_url: "" + }; + + var settings = jQuery.extend(defaults, options); + + // + // Initalize object's elements. + // + + // Get elements for this object. For this_obj, assume the last element with the id is the "this"; this is somewhat of a hack to address the problem + // that there may be two tagging elements for a single item if there are both community and individual tags for an element. + var this_obj = $(this); + var tag_area = this_obj.find('.tag-area'); + var toggle_link = this_obj.find('.toggle-link'); + var tag_input_field = this_obj.find('.tag-input'); + var add_tag_button = this_obj.find('.add-tag-button'); + + // Initialize toggle link. + toggle_link.click( function() { + // Take special actions depending on whether toggle is showing or hiding link. + var after_toggle_fn; + if (tag_area.is(":hidden")) { + after_toggle_fn = function() { + // If there are no tags, go right to editing mode by generating a click on the area. + var num_tags = $(this).find('.tag-button').length; + if (num_tags === 0) { + tag_area.click(); + } + }; + } else { + after_toggle_fn = function() { + tag_area.blur(); + }; + } + tag_area.slideToggle("fast", after_toggle_fn); + return $(this); + }); + + // Initialize tag input field. + if (settings.editable) { + tag_input_field.hide(); + } + tag_input_field.keyup( function(e) { + if ( e.keyCode === 27 ) { + // Escape key + $(this).trigger( "blur" ); + } else if ( + ( e.keyCode === 13 ) || // Return Key + ( e.keyCode === 188 ) || // Comma + ( e.keyCode === 32 ) // Space + ) { + // + // Check input. + // + + var new_value = this.value; + + // Suppress space after a ":" + if ( new_value.indexOf(": ", new_value.length - 2) !== -1) { + this.value = new_value.substring(0, new_value.length-1); + return false; + } + + // Remove trigger keys from input. + if ( (e.keyCode === 188) || (e.keyCode === 32) ) { + new_value = new_value.substring( 0 , new_value.length - 1 ); + } + + // Trim whitespace. + new_value = $.trim(new_value); + + // Too short? + if (new_value.length < 2) { + return false; + } + + // + // New tag OK - apply it. + // + + this.value = ""; // Reset text field now that tag is being added + + // Add button for tag after all other tag buttons. + var new_tag_button = build_tag_button(new_value); + var tag_buttons = tag_area.children(".tag-button"); + if (tag_buttons.length !== 0) { + var last_tag_button = tag_buttons.slice(tag_buttons.length-1); + last_tag_button.after(new_tag_button); + } else { + tag_area.prepend(new_tag_button); + } + + // Add tag to internal list. + var tag_name_and_value = new_value.split(":"); + settings.tags[tag_name_and_value[0]] = tag_name_and_value[1]; + + // Update toggle link text. + var new_text = settings.get_toggle_link_text_fn(settings.tags); + toggle_link.text(new_text); + + // Commit tag to server. + var zz = $(this); + $.ajax({ + url: settings.ajax_add_tag_url, + data: { new_tag: new_value }, + error: function() { + // Failed. Roll back changes and show alert. + new_tag_button.remove(); + delete settings.tags[tag_name_and_value[0]]; + var new_text = settings.get_toggle_link_text_fn(settings.tags); + toggle_link.text(new_text); + alert( "Add tag failed" ); + }, + success: function() { + // Flush autocomplete cache because it's not out of date. + // TODO: in the future, we could remove the particular item + // that was chosen from the cache rather than flush it. + zz.data('autocompleter').cacheFlush(); + } + }); + + return false; + } + }); + + // Add autocomplete to input. + var format_item_func = function(key, row_position, num_rows, value, search_term) { + var tag_name_and_value = value.split(":"); + return (tag_name_and_value.length === 1 ? tag_name_and_value[0] : tag_name_and_value[1]); + }; + var autocomplete_options = { selectFirst: false, formatItem: format_item_func, + autoFill: false, highlight: false }; + tag_input_field.autocomplete(settings.ajax_autocomplete_tag_url, autocomplete_options); + + + // Initialize delete tag images for current tags. + this_obj.find('.delete-tag-img').each(function() { + init_delete_tag_image( $(this) ); + }); + + + // Initialize tag click function. + init_tag_click_function($(this), settings.tag_click_fn); + + // Initialize "add tag" button. + add_tag_button.click( function() { + $(this).hide(); + + // Clicking on button is the same as clicking on the tag area. + tag_area.click(); + return false; + }); + + // + // Set up tag area interactions; these are needed only if tags are editable. + // + if (settings.editable) { + // When the tag area blurs, go to "view tag" mode. + tag_area.bind("blur", function(e) { + if (obj_length(settings.tags) > 0) { + add_tag_button.show(); + tag_input_field.hide(); + tag_area.removeClass("active-tag-area"); + // tag_area.addClass("tooltip"); + } else { + // No tags, so do nothing to ensure that input is still visible. + } + }); + + // On click, enable user to add tags. + tag_area.click( function(e) { + var is_active = $(this).hasClass("active-tag-area"); + + // If a "delete image" object was pressed and area is inactive, do nothing. + if ($(e.target).hasClass("delete-tag-img") && !is_active) { + return false; + } + + // If a "tag name" object was pressed and area is inactive, do nothing. + if ($(e.target).hasClass("tag-name") && !is_active) { + return false; + } + + // Remove tooltip. + // $(this).removeClass("tooltip"); + + // Hide add tag button, show tag_input field. Change background to show + // area is active. + $(this).addClass("active-tag-area"); + add_tag_button.hide(); + tag_input_field.show(); + tag_input_field.focus(); + + // Add handler to document that will call blur when the tag area is blurred; + // a tag area is blurred when a user clicks on an element outside the area. + var handle_document_click = function(e) { + var check_click = function(tag_area, target) { + var tag_area_id = tag_area.attr("id"); + // Blur the tag area if the element clicked on is not in the tag area. + if (target !== tag_area) { + tag_area.blur(); + $(window).unbind("click.tagging_blur"); + $(this).addClass("tooltip"); + } + }; + check_click(tag_area, $(e.target)); + }; + // TODO: we should attach the click handler to all frames in order to capture + // clicks outside the frame that this element is in. + //window.parent.document.onclick = handle_document_click; + //var temp = $(window.parent.document.body).contents().find("iframe").html(); + //alert(temp); + //$(document).parent().click(handle_document_click); + $(window).bind("click.tagging_blur", handle_document_click); + + return false; + }); + } + + // If using toggle link, hide the tag area. Otherwise, show the tag area. + if (settings.use_toggle_link) { + tag_area.hide(); + } + + // + // Helper functions. + // + + // + // Collapse tag name + value into a single string. + // + function build_tag_str(tag_name, tag_value) { + return tag_name + ( tag_value ? ":" + tag_value : ""); + } + + + // Initialize a "delete tag image": when click, delete tag from UI and send delete request to server. + function init_delete_tag_image(delete_img) { + $(delete_img).mouseenter( function () { + $(this).attr("src", settings.delete_tag_img_rollover); + }); + $(delete_img).mouseleave( function () { + $(this).attr("src", settings.delete_tag_img); + }); + $(delete_img).click( function () { + // Tag button is image's parent. + var tag_button = $(this).parent(); + + // Get tag name, value. + var tag_name_elt = tag_button.find(".tag-name").eq(0); + var tag_str = tag_name_elt.text(); + var tag_name_and_value = tag_str.split(":"); + var tag_name = tag_name_and_value[0]; + var tag_value = tag_name_and_value[1]; + + var prev_button = tag_button.prev(); + tag_button.remove(); + + // Remove tag from local list for consistency. + delete settings.tags[tag_name]; + + // Update toggle link text. + var new_text = settings.get_toggle_link_text_fn(settings.tags); + toggle_link.text(new_text); + + // Delete tag. + $.ajax({ + url: settings.ajax_delete_tag_url, + data: { tag_name: tag_name }, + error: function() { + // Failed. Roll back changes and show alert. + settings.tags[tag_name] = tag_value; + if (prev_button.hasClass("tag-button")) { + prev_button.after(tag_button); + } else { + tag_area.prepend(tag_button); + } + alert( "Remove tag failed" ); + + toggle_link.text(settings.get_toggle_link_text_fn(settings.tags)); + + // TODO: no idea why it's necessary to set this up again. + delete_img.mouseenter( function () { + $(this).attr("src", settings.delete_tag_img_rollover); + }); + delete_img.mouseleave( function () { + $(this).attr("src", settings.delete_tag_img); + }); + }, + success: function() {} + }); + + return true; + }); + } + + // + // Function that builds a tag button. + // + function build_tag_button(tag_str) { + // Build "delete tag" image. + var delete_img = $("<img/>").attr("src", settings.delete_tag_img).addClass("delete-tag-img"); + init_delete_tag_image(delete_img); + + // Build tag button. + var tag_name_elt = $("<span>").text(tag_str).addClass("tag-name"); + tag_name_elt.click( function() { + var tag_name_and_value = tag_str.split(":"); + settings.tag_click_fn(tag_name_and_value[0], tag_name_and_value[1]); + return true; + }); + + var tag_button = $("<span></span>").addClass("tag-button"); + tag_button.append(tag_name_elt); + // Allow delete only if element is editable. + if (settings.editable) { + tag_button.append(delete_img); + } + + return tag_button; + } + +}; diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/galaxy/scripts/galaxy.base.js --- /dev/null +++ b/client/galaxy/scripts/galaxy.base.js @@ -0,0 +1,656 @@ +// requestAnimationFrame polyfill +(function() { + var lastTime = 0; + var vendors = ['ms', 'moz', 'webkit', 'o']; + for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) { + window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame']; + window.cancelRequestAnimationFrame = window[vendors[x]+ + 'CancelRequestAnimationFrame']; + } + + if (!window.requestAnimationFrame) + window.requestAnimationFrame = function(callback, element) { + var currTime = new Date().getTime(); + var timeToCall = Math.max(0, 16 - (currTime - lastTime)); + var id = window.setTimeout(function() { callback(currTime + timeToCall); }, + timeToCall); + lastTime = currTime + timeToCall; + return id; + }; + + if (!window.cancelAnimationFrame) + window.cancelAnimationFrame = function(id) { + clearTimeout(id); + }; +}()); + +// IE doesn't implement Array.indexOf +if (!Array.indexOf) { + Array.prototype.indexOf = function(obj) { + for (var i = 0, len = this.length; i < len; i++) { + if (this[i] == obj) { + return i; + } + } + return -1; + }; +} + +// Returns the number of keys (elements) in an array/dictionary. +function obj_length(obj) { + if (obj.length !== undefined) { + return obj.length; + } + + var count = 0; + for (var element in obj) { + count++; + } + return count; +} + +$.fn.makeAbsolute = function(rebase) { + return this.each(function() { + var el = $(this); + var pos = el.position(); + el.css({ + position: "absolute", + marginLeft: 0, marginTop: 0, + top: pos.top, left: pos.left, + right: $(window).width() - ( pos.left + el.width() ) + }); + if (rebase) { + el.remove().appendTo("body"); + } + }); +}; + +/** + * Sets up popupmenu rendering and binds options functions to the appropriate links. + * initial_options is a dict with text describing the option pointing to either (a) a + * function to perform; or (b) another dict with two required keys, 'url' and 'action' (the + * function to perform. (b) is useful for exposing the underlying URL of the option. + */ +function make_popupmenu(button_element, initial_options) { + /* Use the $.data feature to store options with the link element. + This allows options to be changed at a later time + */ + var element_menu_exists = (button_element.data("menu_options")); + button_element.data("menu_options", initial_options); + + // If element already has menu, nothing else to do since HTML and actions are already set. + if (element_menu_exists) { return; } + + button_element.bind("click.show_popup", function(e) { + // Close existing visible menus + $(".popmenu-wrapper").remove(); + + // Need setTimeouts so clicks don't interfere with each other + setTimeout( function() { + // Dynamically generate the wrapper holding all the selectable options of the menu. + var menu_element = $( "<ul class='dropdown-menu' id='" + button_element.attr('id') + "-menu'></ul>" ); + var options = button_element.data("menu_options"); + if (obj_length(options) <= 0) { + $("<li>No Options.</li>").appendTo(menu_element); + } + $.each( options, function( k, v ) { + if (v) { + // Action can be either an anonymous function and a mapped dict. + var action = v.action || v; + menu_element.append( $("<li></li>").append( $("<a>").attr("href", v.url).html(k).click(action) ) ); + } else { + menu_element.append( $("<li></li>").addClass( "head" ).append( $("<a href='#'></a>").html(k) ) ); + } + }); + var wrapper = $( "<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>" ) + .append( menu_element ).appendTo( "body" ); + + var x = e.pageX - wrapper.width() / 2 ; + x = Math.min( x, $(document).scrollLeft() + $(window).width() - $(wrapper).width() - 5 ); + x = Math.max( x, $(document).scrollLeft() + 5 ); + + wrapper.css({ + top: e.pageY, + left: x + }); + }, 10); + + setTimeout( function() { + // Bind click event to current window and all frames to remove any visible menus + // Bind to document object instead of window object for IE compat + var close_popup = function(el) { + $(el).bind("click.close_popup", function() { + $(".popmenu-wrapper").remove(); + el.unbind("click.close_popup"); + }); + }; + close_popup( $(window.document) ); // Current frame + close_popup( $(window.top.document) ); // Parent frame + for (var frame_id = window.top.frames.length; frame_id--;) { // Sibling frames + var frame = $(window.top.frames[frame_id].document); + close_popup(frame); + } + }, 50); + + return false; + }); + +} + +/** + * Convert two seperate (often adjacent) divs into galaxy popupmenu + * - div 1 contains a number of anchors which become the menu options + * - div 1 should have a 'popupmenu' attribute + * - this popupmenu attribute contains the id of div 2 + * - div 2 becomes the 'face' of the popupmenu + * + * NOTE: make_popup_menus finds and operates on all divs with a popupmenu attr (no need to point it at something) + * but (since that selector searches the dom on the page), you can send a parent in + * NOTE: make_popup_menus, and make_popupmenu are horrible names + */ +function make_popup_menus( parent ) { + // find all popupmenu menu divs (divs that contains anchors to be converted to menu options) + // either in the parent or the document if no parent passed + parent = parent || document; + $( parent ).find( "div[popupmenu]" ).each( function() { + var options = {}; + var menu = $(this); + + // find each anchor in the menu, convert them into an options map: { a.text : click_function } + menu.find( "a" ).each( function() { + var link = $(this), + link_dom = link.get(0), + confirmtext = link_dom.getAttribute( "confirm" ), + href = link_dom.getAttribute( "href" ), + target = link_dom.getAttribute( "target" ); + + // no href - no function (gen. a label) + if (!href) { + options[ link.text() ] = null; + + } else { + options[ link.text() ] = { + url: href, + action: function() { + + // if theres confirm text, send the dialog + if ( !confirmtext || confirm( confirmtext ) ) { + // link.click() doesn't use target for some reason, + // so manually do it here. + if (target) { + window.open(href, target); + return false; + } + // For all other links, do the default action. + else { + link.click(); + } + } + } + }; + } + }); + // locate the element with the id corresponding to the menu's popupmenu attr + var box = $( parent ).find( "#" + menu.attr( 'popupmenu' ) ); + + // For menus with clickable link text, make clicking on the link go through instead + // of activating the popup menu + box.find("a").bind("click", function(e) { + e.stopPropagation(); // Stop bubbling so clicking on the link goes through + return true; + }); + + // attach the click events and menu box building to the box element + make_popupmenu(box, options); + box.addClass("popup"); + menu.remove(); + }); +} + +// Alphanumeric/natural sort fn +function naturalSort(a, b) { + // setup temp-scope variables for comparison evauluation + var re = /(-?[0-9\.]+)/g, + x = a.toString().toLowerCase() || '', + y = b.toString().toLowerCase() || '', + nC = String.fromCharCode(0), + xN = x.replace( re, nC + '$1' + nC ).split(nC), + yN = y.replace( re, nC + '$1' + nC ).split(nC), + xD = (new Date(x)).getTime(), + yD = xD ? (new Date(y)).getTime() : null; + // natural sorting of dates + if ( yD ) { + if ( xD < yD ) { return -1; } + else if ( xD > yD ) { return 1; } + } + // natural sorting through split numeric strings and default strings + var oFxNcL, oFyNcL; + for ( var cLoc = 0, numS = Math.max(xN.length, yN.length); cLoc < numS; cLoc++ ) { + oFxNcL = parseFloat(xN[cLoc]) || xN[cLoc]; + oFyNcL = parseFloat(yN[cLoc]) || yN[cLoc]; + if (oFxNcL < oFyNcL) { return -1; } + else if (oFxNcL > oFyNcL) { return 1; } + } + return 0; +} + +$.fn.refresh_select2 = function() { + var select_elt = $(this); + var options = { width: "resolve", + closeOnSelect: !select_elt.is("[MULTIPLE]") + }; + return select_elt.select2( options ); +} + +// Replace select box with a text input box + autocomplete. +function replace_big_select_inputs(min_length, max_length, select_elts) { + // To do replace, the select2 plugin must be loaded. + + if (!jQuery.fn.select2) { + return; + } + + // Set default for min_length and max_length + if (min_length === undefined) { + min_length = 20; + } + if (max_length === undefined) { + max_length = 3000; + } + + select_elts = select_elts || $('select'); + + select_elts.each( function() { + var select_elt = $(this).not('[multiple]'); + // Make sure that options is within range. + var num_options = select_elt.find('option').length; + if ( (num_options < min_length) || (num_options > max_length) ) { + return; + } + + if (select_elt.hasClass("no-autocomplete")) { + return; + } + + /* Replaced jQuery.autocomplete with select2, notes: + * - multiple selects are supported + * - the original element is updated with the value, convert_to_values should not be needed + * - events are fired when updating the original element, so refresh_on_change should just work + * + * - should we still sort dbkey fields here? + */ + select_elt.refresh_select2(); + }); +} + +/** + * Make an element with text editable: (a) when user clicks on text, a textbox/area + * is provided for editing; (b) when enter key pressed, element's text is set and on_finish + * is called. + */ +// TODO: use this function to implement async_save_text (implemented below). +$.fn.make_text_editable = function(config_dict) { + // Get config options. + var num_cols = ("num_cols" in config_dict ? config_dict.num_cols : 30), + num_rows = ("num_rows" in config_dict ? config_dict.num_rows : 4), + use_textarea = ("use_textarea" in config_dict ? config_dict.use_textarea : false), + on_finish = ("on_finish" in config_dict ? config_dict.on_finish : null), + help_text = ("help_text" in config_dict ? config_dict.help_text : null); + + // Add element behavior. + var container = $(this); + container.addClass("editable-text").click(function(e) { + // If there's already an input element, editing is active, so do nothing. + if ($(this).children(":input").length > 0) { + return; + } + + container.removeClass("editable-text"); + + // Handler for setting element text. + var set_text = function(new_text) { + container.find(":input").remove(); + + if (new_text !== "") { + container.text(new_text); + } + else { + // No text; need a line so that there is a click target. + container.html("<br>"); + } + container.addClass("editable-text"); + + if (on_finish) { + on_finish(new_text); + } + }; + + // Create input element(s) for editing. + var cur_text = ("cur_text" in config_dict ? config_dict.cur_text : container.text() ), + input_elt, button_elt; + + if (use_textarea) { + input_elt = $("<textarea/>") + .attr({ rows: num_rows, cols: num_cols }).text($.trim(cur_text)) + .keyup(function(e) { + if (e.keyCode === 27) { + // Escape key. + set_text(cur_text); + } + }); + button_elt = $("<button/>").text("Done").click(function() { + set_text(input_elt.val()); + // Return false so that click does not propogate to container. + return false; + }); + } + else { + input_elt = $("<input type='text'/>").attr({ value: $.trim(cur_text), size: num_cols }) + .blur(function() { + set_text(cur_text); + }).keyup(function(e) { + if (e.keyCode === 27) { + // Escape key. + $(this).trigger("blur"); + } else if (e.keyCode === 13) { + // Enter key. + set_text($(this).val()); + } + + // Do not propogate event to avoid unwanted side effects. + e.stopPropagation(); + }); + } + + // Replace text with input object(s) and focus & select. + container.text(""); + container.append(input_elt); + if (button_elt) { + container.append(button_elt); + } + input_elt.focus(); + input_elt.select(); + + // Do not propogate to elements below b/c that blurs input and prevents it from being used. + e.stopPropagation(); + }); + + // Add help text if there some. + if (help_text) { + container.attr("title", help_text).tooltip(); + } + + return container; +}; + +/** + * Edit and save text asynchronously. + */ +function async_save_text( click_to_edit_elt, text_elt_id, save_url, + text_parm_name, num_cols, use_textarea, num_rows, on_start, on_finish ) { + // Set defaults if necessary. + if (num_cols === undefined) { + num_cols = 30; + } + if (num_rows === undefined) { + num_rows = 4; + } + + // Set up input element. + $("#" + click_to_edit_elt).click(function() { + // Check if this is already active + if ( $("#renaming-active").length > 0) { + return; + } + var text_elt = $("#" + text_elt_id), + old_text = text_elt.text(), + t; + + if (use_textarea) { + t = $("<textarea></textarea>").attr({ rows: num_rows, cols: num_cols }).text( $.trim(old_text) ); + } else { + t = $("<input type='text'></input>").attr({ value: $.trim(old_text), size: num_cols }); + } + t.attr("id", "renaming-active"); + t.blur( function() { + $(this).remove(); + text_elt.show(); + if (on_finish) { + on_finish(t); + } + }); + t.keyup( function( e ) { + if ( e.keyCode === 27 ) { + // Escape key + $(this).trigger( "blur" ); + } else if ( e.keyCode === 13 ) { + // Enter key submits + var ajax_data = {}; + ajax_data[text_parm_name] = $(this).val(); + $(this).trigger( "blur" ); + $.ajax({ + url: save_url, + data: ajax_data, + error: function() { + alert( "Text editing for elt " + text_elt_id + " failed" ); + // TODO: call finish or no? For now, let's not because error occurred. + }, + success: function(processed_text) { + // Set new text and call finish method. + if (processed_text !== "") { + text_elt.text(processed_text); + } else { + text_elt.html("<em>None</em>"); + } + if (on_finish) { + on_finish(t); + } + } + }); + } + }); + + if (on_start) { + on_start(t); + } + // Replace text with input object and focus & select. + text_elt.hide(); + t.insertAfter(text_elt); + t.focus(); + t.select(); + + return; + }); +} + +function commatize( number ) { + number += ''; // Convert to string + var rgx = /(\d+)(\d{3})/; + while (rgx.test(number)) { + number = number.replace(rgx, '$1' + ',' + '$2'); + } + return number; +} + +// Reset tool search to start state. +function reset_tool_search( initValue ) { + // Function may be called in top frame or in tool_menu_frame; + // in either case, get the tool menu frame. + var tool_menu_frame = $("#galaxy_tools").contents(); + if (tool_menu_frame.length === 0) { + tool_menu_frame = $(document); + } + + // Remove classes that indicate searching is active. + $(this).removeClass("search_active"); + tool_menu_frame.find(".toolTitle").removeClass("search_match"); + + // Reset visibility of tools and labels. + tool_menu_frame.find(".toolSectionBody").hide(); + tool_menu_frame.find(".toolTitle").show(); + tool_menu_frame.find(".toolPanelLabel").show(); + tool_menu_frame.find(".toolSectionWrapper").each( function() { + if ($(this).attr('id') !== 'recently_used_wrapper') { + // Default action. + $(this).show(); + } else if ($(this).hasClass("user_pref_visible")) { + $(this).show(); + } + }); + tool_menu_frame.find("#search-no-results").hide(); + + // Reset search input. + tool_menu_frame.find("#search-spinner").hide(); + if (initValue) { + var search_input = tool_menu_frame.find("#tool-search-query"); + search_input.val("search tools"); + } +} + +// Create GalaxyAsync object. +var GalaxyAsync = function(log_action) { + this.url_dict = {}; + this.log_action = (log_action === undefined ? false : log_action); +}; + +GalaxyAsync.prototype.set_func_url = function( func_name, url ) { + this.url_dict[func_name] = url; +}; + +// Set user preference asynchronously. +GalaxyAsync.prototype.set_user_pref = function( pref_name, pref_value ) { + // Get URL. + var url = this.url_dict[arguments.callee]; + if (url === undefined) { return false; } + $.ajax({ + url: url, + data: { "pref_name" : pref_name, "pref_value" : pref_value }, + error: function() { return false; }, + success: function() { return true; } + }); +}; + +// Log user action asynchronously. +GalaxyAsync.prototype.log_user_action = function( action, context, params ) { + if (!this.log_action) { return; } + + // Get URL. + var url = this.url_dict[arguments.callee]; + if (url === undefined) { return false; } + $.ajax({ + url: url, + data: { "action" : action, "context" : context, "params" : params }, + error: function() { return false; }, + success: function() { return true; } + }); +}; + +// Initialize refresh events. +function init_refresh_on_change () { + $("select[refresh_on_change='true']") + .off('change') + .change(function() { + var select_field = $(this), + select_val = select_field.val(), + refresh = false, + ref_on_change_vals = select_field.attr("refresh_on_change_values"); + if (ref_on_change_vals) { + ref_on_change_vals = ref_on_change_vals.split(','); + var last_selected_value = select_field.attr("last_selected_value"); + if ($.inArray(select_val, ref_on_change_vals) === -1 && $.inArray(last_selected_value, ref_on_change_vals) === -1) { + return; + } + } + $(window).trigger("refresh_on_change"); + $(document).trigger("convert_to_values"); // Convert autocomplete text to values + select_field.get(0).form.submit(); + }); + + // checkboxes refresh on change + $(":checkbox[refresh_on_change='true']") + .off('click') + .click( function() { + var select_field = $(this), + select_val = select_field.val(), + refresh = false, + ref_on_change_vals = select_field.attr("refresh_on_change_values"); + if (ref_on_change_vals) { + ref_on_change_vals = ref_on_change_vals.split(','); + var last_selected_value = select_field.attr("last_selected_value"); + if ($.inArray(select_val, ref_on_change_vals) === -1 && $.inArray(last_selected_value, ref_on_change_vals) === -1) { + return; + } + } + $(window).trigger("refresh_on_change"); + select_field.get(0).form.submit(); + }); + + // Links with confirmation + $( "a[confirm]" ) + .off('click') + .click( function() { + return confirm( $(this).attr("confirm") ); + }); +}; + + +// jQuery plugin to prevent double submission of forms +// Ref: http://stackoverflow.com/questions/2830542/prevent-double-submission-of-form... +jQuery.fn.preventDoubleSubmission = function() { + $(this).on('submit',function(e){ + var $form = $(this); + + if ($form.data('submitted') === true) { + // Previously submitted - don't submit again + e.preventDefault(); + } else { + // Mark it so that the next submit can be ignored + $form.data('submitted', true); + } + }); + + // Keep chainability + return this; +}; + +$(document).ready( function() { + + // Refresh events for form fields. + init_refresh_on_change(); + + // Tooltips + if ( $.fn.tooltip ) { + // Put tooltips below items in panel header so that they do not overlap masthead. + $(".unified-panel-header [title]").tooltip( { placement: 'bottom' } ); + + // default tooltip initialization, it will follow the data-placement tag for tooltip location + // and fallback to 'top' if not present + $("[title]").tooltip(); + } + // Make popup menus. + make_popup_menus(); + + // Replace big selects. + replace_big_select_inputs(20, 1500); + + // If galaxy_main frame does not exist and link targets galaxy_main, + // add use_panels=True and set target to self. + $("a").click( function() { + var anchor = $(this); + var galaxy_main_exists = (parent.frames && parent.frames.galaxy_main); + if ( ( anchor.attr( "target" ) == "galaxy_main" ) && ( !galaxy_main_exists ) ) { + var href = anchor.attr("href"); + if (href.indexOf("?") == -1) { + href += "?"; + } + else { + href += "&"; + } + href += "use_panels=True"; + anchor.attr("href", href); + anchor.attr("target", "_self"); + } + return anchor; + }); + +}); diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/galaxy/scripts/galaxy.frame.js --- /dev/null +++ b/client/galaxy/scripts/galaxy.frame.js @@ -0,0 +1,173 @@ +// dependencies +define(["galaxy.masthead", "mvc/ui/ui-frames"], function(mod_masthead, Frames) { + +// frame manager +var GalaxyFrame = Backbone.View.extend( +{ + // base element + el_main: 'body', + + // frame active/disabled + active: false, + + // button active + button_active: null, + + // button load + button_load : null, + + // initialize + initialize : function(options) + { + // add to masthead menu + var self = this; + + // create frames + this.frames = new Frames.View({ + visible: false, + }); + + // add activate icon + this.button_active = new mod_masthead.GalaxyMastheadIcon ( + { + icon : 'fa-th', + tooltip : 'Enable/Disable Scratchbook', + onclick : function() { self._activate(); }, + onunload : function() { + if (self.frames.length() > 0) { + return "You opened " + self.frames.length() + " frame(s) which will be lost."; + } + } + }); + + // add to masthead + Galaxy.masthead.append(this.button_active); + + // add load icon + this.button_load = new mod_masthead.GalaxyMastheadIcon ( + { + icon : 'fa-eye', + tooltip : 'Show/Hide Scratchbook', + onclick : function(e) { + if (self.frames.visible) { + self.frames.hide(); + } else { + self.frames.show(); + } + }, + with_number : true + }); + + // add to masthead + Galaxy.masthead.append(this.button_load); + + // create + this.setElement(this.frames.$el); + + // append to main + $(this.el_main).append(this.$el); + + // refresh menu + this.frames.setOnChange(function() { + self._refresh(); + }); + this._refresh(); + }, + + // adds and displays a new frame/window + add: function(options) + { + // open new tab + if (options.target == '_blank') + { + window.open(options.content); + return; + } + + // reload entire window + if (options.target == '_top' || options.target == '_parent' || options.target == '_self') + { + window.location = options.content; + return; + } + + // validate + if (!this.active) + { + // fix url if main frame is unavailable + var $galaxy_main = $(window.parent.document).find('#galaxy_main'); + if (options.target == 'galaxy_main' || options.target == 'center') + { + if ($galaxy_main.length === 0) + { + var href = options.content; + if (href.indexOf('?') == -1) + href += '?'; + else + href += '&'; + href += 'use_panels=True'; + window.location = href; + } else { + $galaxy_main.attr('src', options.content); + } + } else + window.location = options.content; + + // stop + return; + } + + // add to frames view + this.frames.add(options); + }, + + // activate/disable panel + _activate: function () + { + // check + if (this.active) + { + // disable + this.active = false; + + // toggle + this.button_active.untoggle(); + + // hide panel + this.frames.hide(); + } else { + // activate + this.active = true; + + // untoggle + this.button_active.toggle(); + } + }, + + // update frame counter + _refresh: function() + { + // update on screen counter + this.button_load.number(this.frames.length()); + + // check + if(this.frames.length() === 0) + this.button_load.hide(); + else + this.button_load.show(); + + // check + if (this.frames.visible) { + this.button_load.toggle(); + } else { + this.button_load.untoggle(); + } + } +}); + +// return +return { + GalaxyFrame: GalaxyFrame +}; + +}); diff -r ba66d120d001d6531300f57f215210056481f368 -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 client/galaxy/scripts/galaxy.library.js --- /dev/null +++ b/client/galaxy/scripts/galaxy.library.js @@ -0,0 +1,159 @@ +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM +// === MAIN GALAXY LIBRARY MODULE ==== +// MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM + +define([ + "galaxy.masthead", + "utils/utils", + "libs/toastr", + "mvc/base-mvc", + "mvc/library/library-model", + "mvc/library/library-folderlist-view", + "mvc/library/library-librarylist-view", + "mvc/library/library-librarytoolbar-view", + "mvc/library/library-foldertoolbar-view", + "mvc/library/library-dataset-view", + "mvc/library/library-library-view", + "mvc/library/library-folder-view" + ], +function(mod_masthead, + mod_utils, + mod_toastr, + mod_baseMVC, + mod_library_model, + mod_folderlist_view, + mod_librarylist_view, + mod_librarytoolbar_view, + mod_foldertoolbar_view, + mod_library_dataset_view, + mod_library_library_view, + mod_library_folder_view + ) { + +// ============================================================================ +// ROUTER +var LibraryRouter = Backbone.Router.extend({ + initialize: function() { + this.routesHit = 0; + //keep count of number of routes handled by the application + Backbone.history.on('route', function() { this.routesHit++; }, this); + }, + + routes: { + "" : "libraries", + "library/:library_id/permissions" : "library_permissions", + "folders/:folder_id/permissions" : "folder_permissions", + "folders/:id" : "folder_content", + "folders/:folder_id/datasets/:dataset_id" : "dataset_detail", + "folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions", + "folders/:folder_id/datasets/:dataset_id/versions/:ldda_id" : "dataset_version", + "folders/:folder_id/download/:format" : "download" + }, + + back: function() { + if(this.routesHit > 1) { + //more than one route hit -> user did not land to current page directly + window.history.back(); + } else { + //otherwise go to the home page. Use replaceState if available so + //the navigation doesn't create an extra history entry + this.navigate('#', {trigger:true, replace:true}); + } + } +}); + +// ============================================================================ +/** session storage for library preferences */ +var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({ + defaults : { + with_deleted : false, + sort_order : 'asc', + sort_by : 'name' + } +}); + +// ============================================================================ +// Main controller of Galaxy Library +var GalaxyLibrary = Backbone.View.extend({ + + libraryToolbarView: null, + libraryListView: null, + library_router: null, + libraryView: null, + folderToolbarView: null, + folderListView: null, + datasetView: null, + + initialize : function(){ + Galaxy.libraries = this; + + this.preferences = new LibraryPrefs( {id: 'global-lib-prefs'} ); + + this.library_router = new LibraryRouter(); + + this.library_router.on('route:libraries', function() { + Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView(); + Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView(); + }); + + this.library_router.on('route:folder_content', function(id) { + if (Galaxy.libraries.folderToolbarView){ + Galaxy.libraries.folderToolbarView.$el.unbind('click'); + } + Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id}); + Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id}); + }); + + this.library_router.on('route:download', function(folder_id, format) { + if ($('#folder_list_body').find(':checked').length === 0) { + mod_toastr.info('You have to select some datasets to download'); + Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: true, replace: true}); + } else { + Galaxy.libraries.folderToolbarView.download(folder_id, format); + Galaxy.libraries.library_router.navigate('folders/' + folder_id, {trigger: false, replace: true}); + } + }); + + this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){ + if (Galaxy.libraries.datasetView){ + Galaxy.libraries.datasetView.$el.unbind('click'); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id}); + }); + this.library_router.on('route:dataset_version', function(folder_id, dataset_id, ldda_id){ + if (Galaxy.libraries.datasetView){ + Galaxy.libraries.datasetView.$el.unbind('click'); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, ldda_id: ldda_id, show_version: true}); + }); + + this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){ + if (Galaxy.libraries.datasetView){ + Galaxy.libraries.datasetView.$el.unbind('click'); + } + Galaxy.libraries.datasetView = new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true}); + }); + + this.library_router.on('route:library_permissions', function(library_id){ + if (Galaxy.libraries.libraryView){ + Galaxy.libraries.libraryView.$el.unbind('click'); + } + Galaxy.libraries.libraryView = new mod_library_library_view.LibraryView({id: library_id, show_permissions: true}); + }); + + this.library_router.on('route:folder_permissions', function(folder_id){ + if (Galaxy.libraries.folderView){ + Galaxy.libraries.folderView.$el.unbind('click'); + } + Galaxy.libraries.folderView = new mod_library_folder_view.FolderView({id: folder_id, show_permissions: true}); + }); + + Backbone.history.start({pushState: false}); + } +}); + +return { + GalaxyApp: GalaxyLibrary +}; + +}); This diff is so big that we needed to truncate the remainder. https://bitbucket.org/galaxy/galaxy-central/commits/898a4bda2318/ Changeset: 898a4bda2318 User: carlfeberhard Date: 2014-09-16 15:41:35 Summary: Merged galaxy/galaxy-central into default Affected #: 117 files diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 README.txt --- a/README.txt +++ b/README.txt @@ -22,13 +22,13 @@ http://localhost:8080 You may wish to make changes from the default configuration. This can be done -in the universe_wsgi.ini file. Tools can be either installed from the Tool Shed +in the config/galaxy.ini file. Tools can be either installed from the Tool Shed or added manually. For details please see the Galaxy wiki: -https://wiki.galaxyproject.org/Admin/Tools/AddToolFromToolShedTutorial. +https://wiki.galaxyproject.org/Admin/Tools/AddToolFromToolShedTutorial Not all dependencies are included for the tools provided in the sample tool_conf.xml. A full list of external dependencies is available at: -https://wiki.galaxyproject.org/Admin/Tools/ToolDependencies \ No newline at end of file +https://wiki.galaxyproject.org/Admin/Tools/ToolDependencies diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 buildbot_setup.sh --- a/buildbot_setup.sh +++ b/buildbot_setup.sh @@ -43,15 +43,10 @@ " SAMPLES=" -tool_conf.xml.sample -datatypes_conf.xml.sample -universe_wsgi.ini.sample -tool_data_table_conf.xml.sample -tool_sheds_conf.xml.sample -shed_tool_data_table_conf.xml.sample -migrated_tools_conf.xml.sample -data_manager_conf.xml.sample -shed_data_manager_conf.xml.sample +config/galaxy.ini.sample +config/shed_tool_data_table_conf.xml.sample +config/migrated_tools_conf.xml.sample +config/shed_data_manager_conf.xml.sample tool-data/shared/igv/igv_build_sites.txt.sample tool-data/shared/rviewer/rviewer_build_sites.txt.sample tool-data/shared/ucsc/builds.txt.sample diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 client/galaxy/scripts/galaxy-app-base.js --- a/client/galaxy/scripts/galaxy-app-base.js +++ b/client/galaxy/scripts/galaxy-app-base.js @@ -11,7 +11,7 @@ * logger : the logger/metrics-logger * localize : the string localizer * config : the current configuration (any k/v in - * universe_wsgi.ini available from the configuration API) + * galaxy.ini available from the configuration API) * user : the current user (as a mvc/user/user-model) */ function GalaxyApp( options ){ diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/data_manager_conf.xml.sample --- /dev/null +++ b/config/data_manager_conf.xml.sample @@ -0,0 +1,3 @@ +<?xml version="1.0"?> +<data_managers> +</data_managers> diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/datatypes_conf.xml.sample --- /dev/null +++ b/config/datatypes_conf.xml.sample @@ -0,0 +1,333 @@ +<?xml version="1.0"?> +<datatypes> + <registration converters_path="lib/galaxy/datatypes/converters" display_path="display_applications"> + <datatype extension="ab1" type="galaxy.datatypes.binary:Ab1" mimetype="application/octet-stream" display_in_upload="true" description="A binary sequence file in 'ab1' format with a '.ab1' file extension. You must manually select this 'File Format' when uploading the file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Ab1"/> + <datatype extension="afg" type="galaxy.datatypes.assembly:Amos" display_in_upload="false" /> + <datatype extension="asn1" type="galaxy.datatypes.data:GenericAsn1" mimetype="text/plain" display_in_upload="true" /> + <datatype extension="asn1-binary" type="galaxy.datatypes.binary:GenericAsn1Binary" mimetype="application/octet-stream" display_in_upload="true" /> + <datatype extension="axt" type="galaxy.datatypes.sequence:Axt" display_in_upload="true" description="blastz pairwise alignment format. Each alignment block in an axt file contains three lines: a summary line and 2 sequence lines. Blocks are separated from one another by blank lines. The summary line contains chromosomal position and size information about the alignment. It consists of 9 required fields." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Axt"/> + <datatype extension="fli" type="galaxy.datatypes.tabular:FeatureLocationIndex" display_in_upload="false"/> + <datatype extension="bam" type="galaxy.datatypes.binary:Bam" mimetype="application/octet-stream" display_in_upload="true" description="A binary file compressed in the BGZF format with a '.bam' file extension." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#BAM"> + <converter file="bam_to_bai.xml" target_datatype="bai"/> + <converter file="bam_to_bigwig_converter.xml" target_datatype="bigwig"/> + <display file="ucsc/bam.xml" /> + <display file="ensembl/ensembl_bam.xml" /> + <display file="igv/bam.xml" /> + <display file="igb/bam.xml" /> + </datatype> + <datatype extension="bed" type="galaxy.datatypes.interval:Bed" display_in_upload="true" description="BED format provides a flexible way to define the data lines that are displayed in an annotation track. BED lines have three required columns and nine additional optional columns. The three required columns are chrom, chromStart and chromEnd." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Bed"> + <converter file="bed_to_gff_converter.xml" target_datatype="gff"/> + <converter file="bed_to_bgzip_converter.xml" target_datatype="bgzip"/> + <converter file="bed_to_tabix_converter.xml" target_datatype="tabix" depends_on="bgzip"/> + <converter file="bed_gff_or_vcf_to_bigwig_converter.xml" target_datatype="bigwig"/> + <converter file="bed_to_fli_converter.xml" target_datatype="fli"/> + <!-- <display file="ucsc/interval_as_bed.xml" /> --> + <display file="igb/bed.xml" /> + </datatype> + <datatype extension="bedgraph" type="galaxy.datatypes.interval:BedGraph" display_in_upload="true"> + <converter file="bedgraph_to_bigwig_converter.xml" target_datatype="bigwig"/> + <display file="igb/bedgraph.xml" /> + </datatype> + <datatype extension="bedstrict" type="galaxy.datatypes.interval:BedStrict" /> + <datatype extension="bed6" type="galaxy.datatypes.interval:Bed6"> + </datatype> + <datatype extension="bed12" type="galaxy.datatypes.interval:Bed12" /> + <datatype extension="len" type="galaxy.datatypes.chrominfo:ChromInfo" display_in_upload="true"> + <converter file="len_to_linecount.xml" target_datatype="linecount" /> + </datatype> + <datatype extension="bigbed" type="galaxy.datatypes.binary:BigBed" mimetype="application/octet-stream" display_in_upload="true"> + <display file="ucsc/bigbed.xml" /> + <display file="igb/bb.xml" /> + </datatype> + <datatype extension="bigwig" type="galaxy.datatypes.binary:BigWig" mimetype="application/octet-stream" display_in_upload="true"> + <display file="ucsc/bigwig.xml" /> + <display file="igb/bigwig.xml" /> + </datatype> + <datatype extension="chrint" type="galaxy.datatypes.interval:ChromatinInteractions" display_in_upload="True"> + <converter file="interval_to_bgzip_converter.xml" target_datatype="bgzip"/> + <converter file="interval_to_tabix_converter.xml" target_datatype="tabix" depends_on="bgzip"/> + <converter file="bed_gff_or_vcf_to_bigwig_converter.xml" target_datatype="bigwig"/> + </datatype> + <!-- MSI added Datatypes --> + <datatype extension="csv" type="galaxy.datatypes.tabular:Tabular" subclass="True" display_in_upload="true" /><!-- FIXME: csv is 'tabular'ized data, but not 'tab-delimited'; the class used here is intended for 'tab-delimited' --> + <!-- End MSI added Datatypes --> + <datatype extension="customtrack" type="galaxy.datatypes.interval:CustomTrack"/> + <datatype extension="bowtie_color_index" type="galaxy.datatypes.ngsindex:BowtieColorIndex" mimetype="text/html" display_in_upload="False"/> + <datatype extension="bowtie_base_index" type="galaxy.datatypes.ngsindex:BowtieBaseIndex" mimetype="text/html" display_in_upload="False"/> + <datatype extension="csfasta" type="galaxy.datatypes.sequence:csFasta" display_in_upload="true"/> + <datatype extension="data" type="galaxy.datatypes.data:Data" mimetype="application/octet-stream" max_optional_metadata_filesize="1048576" /> + <datatype extension="data_manager_json" type="galaxy.datatypes.data:Text" mimetype="application/json" subclass="True" display_in_upload="False"/> + <datatype extension="fasta" type="galaxy.datatypes.sequence:Fasta" display_in_upload="true" description="A sequence in FASTA format consists of a single-line description, followed by lines of sequence data. The first character of the description line is a greater-than ('>') symbol in the first column. All lines should be shorter than 80 characters." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Fasta"> + <converter file="fasta_to_tabular_converter.xml" target_datatype="tabular"/> + <converter file="fasta_to_bowtie_base_index_converter.xml" target_datatype="bowtie_base_index"/> + <converter file="fasta_to_bowtie_color_index_converter.xml" target_datatype="bowtie_color_index"/> + <converter file="fasta_to_2bit.xml" target_datatype="twobit"/> + <converter file="fasta_to_len.xml" target_datatype="len"/> + </datatype> + <datatype extension="fastq" type="galaxy.datatypes.sequence:Fastq" display_in_upload="true" description="FASTQ format is a text-based format for storing both a biological sequence (usually nucleotide sequence) and its corresponding quality scores." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Fastq"> + <converter file="fastq_to_fqtoc.xml" target_datatype="fqtoc"/> + </datatype> + <datatype extension="fastqsanger" type="galaxy.datatypes.sequence:FastqSanger" display_in_upload="true"> + <converter file="fastq_to_fqtoc.xml" target_datatype="fqtoc"/> + </datatype> + <datatype extension="fastqsolexa" type="galaxy.datatypes.sequence:FastqSolexa" display_in_upload="true" description="FastqSolexa is the Illumina (Solexa) variant of the Fastq format, which stores sequences and quality scores in a single file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#FastqSolexa"> + <converter file="fastq_to_fqtoc.xml" target_datatype="fqtoc"/> + </datatype> + <datatype extension="fastqcssanger" type="galaxy.datatypes.sequence:FastqCSSanger" display_in_upload="true"> + <converter file="fastq_to_fqtoc.xml" target_datatype="fqtoc"/> + </datatype> + <datatype extension="fastqillumina" type="galaxy.datatypes.sequence:FastqIllumina" display_in_upload="true"> + <converter file="fastq_to_fqtoc.xml" target_datatype="fqtoc"/> + </datatype> + <datatype extension="fqtoc" type="galaxy.datatypes.sequence:SequenceSplitLocations" display_in_upload="true"/> + <datatype extension="eland" type="galaxy.datatypes.tabular:Eland" display_in_upload="true"/> + <datatype extension="elandmulti" type="galaxy.datatypes.tabular:ElandMulti" display_in_upload="true"/> + <datatype extension="genetrack" type="galaxy.datatypes.tracks:GeneTrack"> + <!-- <display file="genetrack.xml" /> --> + </datatype> + <datatype extension="gff" type="galaxy.datatypes.interval:Gff" display_in_upload="true" description="GFF lines have nine required fields that must be tab-separated." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#GFF"> + <converter file="gff_to_bed_converter.xml" target_datatype="bed"/> + <converter file="gff_to_interval_index_converter.xml" target_datatype="interval_index"/> + <converter file="bed_gff_or_vcf_to_bigwig_converter.xml" target_datatype="bigwig"/> + <converter file="gff_to_fli_converter.xml" target_datatype="fli"/> + <display file="ensembl/ensembl_gff.xml" inherit="True"/> + <!-- <display file="gbrowse/gbrowse_gff.xml" inherit="True" /> --> + </datatype> + <datatype extension="gff3" type="galaxy.datatypes.interval:Gff3" display_in_upload="true" description="The GFF3 format addresses the most common extensions to GFF, while preserving backward compatibility with previous formats." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#GFF3"/> + <datatype extension="gif" type="galaxy.datatypes.images:Gif" mimetype="image/gif"/> + <datatype extension="gmaj.zip" type="galaxy.datatypes.images:Gmaj" mimetype="application/zip"/> + <datatype extension="gtf" type="galaxy.datatypes.interval:Gtf" display_in_upload="true"> + <converter file="gff_to_interval_index_converter.xml" target_datatype="interval_index"/> + <converter file="bed_gff_or_vcf_to_bigwig_converter.xml" target_datatype="bigwig"/> + <display file="igb/gtf.xml" /> + </datatype> + <datatype extension="toolshed.gz" type="galaxy.datatypes.binary:Binary" mimetype="multipart/x-gzip" subclass="True" /> + <datatype extension="h5" type="galaxy.datatypes.binary:Binary" mimetype="application/octet-stream" subclass="True" /> + <datatype extension="html" type="galaxy.datatypes.images:Html" mimetype="text/html"/> + <datatype extension="interval" type="galaxy.datatypes.interval:Interval" display_in_upload="true" description="File must start with definition line in the following format (columns may be in any order)." > + <converter file="interval_to_bed_converter.xml" target_datatype="bed"/> + <converter file="interval_to_bedstrict_converter.xml" target_datatype="bedstrict"/> + <converter file="interval_to_bed6_converter.xml" target_datatype="bed6"/> + <converter file="interval_to_bed12_converter.xml" target_datatype="bed12"/> + <converter file="interval_to_bgzip_converter.xml" target_datatype="bgzip"/> + <converter file="interval_to_tabix_converter.xml" target_datatype="tabix" depends_on="bgzip"/> + <converter file="interval_to_bigwig_converter.xml" target_datatype="bigwig"/> + <!-- <display file="ucsc/interval_as_bed.xml" inherit="True" /> --> + <display file="ensembl/ensembl_interval_as_bed.xml" inherit="True"/> + <display file="gbrowse/gbrowse_interval_as_bed.xml" inherit="True"/> + <display file="rviewer/bed.xml" inherit="True"/> + </datatype> + <datatype extension="picard_interval_list" type="galaxy.datatypes.tabular:Tabular" subclass="True" display_in_upload="True"> + <converter file="picard_interval_list_to_bed6_converter.xml" target_datatype="bed6"/> + </datatype> + <datatype extension="gatk_interval" type="galaxy.datatypes.data:Text" subclass="True" display_in_upload="True"/> + <datatype extension="gatk_report" type="galaxy.datatypes.data:Text" subclass="True" display_in_upload="True"/> + <datatype extension="gatk_dbsnp" type="galaxy.datatypes.tabular:Tabular" subclass="True" display_in_upload="True"/> + <datatype extension="gatk_tranche" type="galaxy.datatypes.tabular:Tabular" subclass="True" display_in_upload="True"/> + <datatype extension="gatk_recal" type="galaxy.datatypes.tabular:Tabular" subclass="True" display_in_upload="True"/> + <datatype extension="jpg" type="galaxy.datatypes.images:Jpg" mimetype="image/jpeg"/> + <datatype extension="tiff" type="galaxy.datatypes.images:Tiff" mimetype="image/tiff"/> + <datatype extension="bmp" type="galaxy.datatypes.images:Bmp" mimetype="image/bmp"/> + <datatype extension="im" type="galaxy.datatypes.images:Im" mimetype="image/im"/> + <datatype extension="pcd" type="galaxy.datatypes.images:Pcd" mimetype="image/pcd"/> + <datatype extension="pcx" type="galaxy.datatypes.images:Pcx" mimetype="image/pcx"/> + <datatype extension="ppm" type="galaxy.datatypes.images:Ppm" mimetype="image/ppm"/> + <datatype extension="psd" type="galaxy.datatypes.images:Psd" mimetype="image/psd"/> + <datatype extension="xbm" type="galaxy.datatypes.images:Xbm" mimetype="image/xbm"/> + <datatype extension="xpm" type="galaxy.datatypes.images:Xpm" mimetype="image/xpm"/> + <datatype extension="rgb" type="galaxy.datatypes.images:Rgb" mimetype="image/rgb"/> + <datatype extension="pbm" type="galaxy.datatypes.images:Pbm" mimetype="image/pbm"/> + <datatype extension="pgm" type="galaxy.datatypes.images:Pgm" mimetype="image/pgm"/> + <datatype extension="eps" type="galaxy.datatypes.images:Eps" mimetype="image/eps"/> + <datatype extension="rast" type="galaxy.datatypes.images:Rast" mimetype="image/rast"/> + <datatype extension="laj" type="galaxy.datatypes.images:Laj"/> + <datatype extension="lav" type="galaxy.datatypes.sequence:Lav" display_in_upload="true" description="Lav is the primary output format for BLASTZ. The first line of a .lav file begins with #:lav.." /> + <datatype extension="maf" type="galaxy.datatypes.sequence:Maf" display_in_upload="true" description="TBA and multiz multiple alignment format. The first line of a .maf file begins with ##maf. This word is followed by white-space-separated 'variable=value' pairs. There should be no white space surrounding the '='." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#MAF"> + <converter file="maf_to_fasta_converter.xml" target_datatype="fasta"/> + <converter file="maf_to_interval_converter.xml" target_datatype="interval"/> + </datatype> + <datatype extension="mafcustomtrack" type="galaxy.datatypes.sequence:MafCustomTrack"> + <display file="ucsc/maf_customtrack.xml" /> + </datatype> + <datatype extension="encodepeak" type="galaxy.datatypes.interval:ENCODEPeak" display_in_upload="True"> + <converter file="encodepeak_to_tabix_converter.xml" target_datatype="tabix" depends_on="bgzip"/> + <converter file="encodepeak_to_bgzip_converter.xml" target_datatype="bgzip"/> + <converter file="bed_gff_or_vcf_to_bigwig_converter.xml" target_datatype="bigwig"/> + </datatype> + <datatype extension="pdf" type="galaxy.datatypes.images:Pdf" mimetype="application/pdf"/> + <datatype extension="pileup" type="galaxy.datatypes.tabular:Pileup" display_in_upload="true"> + <converter file="interval_to_bgzip_converter.xml" target_datatype="bgzip"/> + <converter file="interval_to_tabix_converter.xml" target_datatype="tabix" depends_on="bgzip"/> + </datatype> + <datatype extension="png" type="galaxy.datatypes.images:Png" mimetype="image/png"/> + <datatype extension="qual" type="galaxy.datatypes.qualityscore:QualityScore" /> + <datatype extension="qualsolexa" type="galaxy.datatypes.qualityscore:QualityScoreSolexa" display_in_upload="true"/> + <datatype extension="qualillumina" type="galaxy.datatypes.qualityscore:QualityScoreIllumina" display_in_upload="true"/> + <datatype extension="qualsolid" type="galaxy.datatypes.qualityscore:QualityScoreSOLiD" display_in_upload="true"/> + <datatype extension="qual454" type="galaxy.datatypes.qualityscore:QualityScore454" display_in_upload="true"/> + <datatype extension="Roadmaps" type="galaxy.datatypes.assembly:Roadmaps" display_in_upload="false"/> + <datatype extension="sam" type="galaxy.datatypes.tabular:Sam" display_in_upload="true"> + <converter file="sam_to_bam.xml" target_datatype="bam"/> + <converter file="sam_to_bigwig_converter.xml" target_datatype="bigwig"/> + </datatype> + <datatype extension="scf" type="galaxy.datatypes.binary:Scf" mimetype="application/octet-stream" display_in_upload="true" description="A binary sequence file in 'scf' format with a '.scf' file extension. You must manually select this 'File Format' when uploading the file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Scf"/> + <datatype extension="Sequences" type="galaxy.datatypes.assembly:Sequences" display_in_upload="false"/> + <datatype extension="sff" type="galaxy.datatypes.binary:Sff" mimetype="application/octet-stream" display_in_upload="true" description="A binary file in 'Standard Flowgram Format' with a '.sff' file extension." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Sff"/> + <datatype extension="svg" type="galaxy.datatypes.images:Image" mimetype="image/svg+xml"/> + <datatype extension="taxonomy" type="galaxy.datatypes.tabular:Taxonomy" display_in_upload="true"/> + <datatype extension="tabular" type="galaxy.datatypes.tabular:Tabular" display_in_upload="true" description="Any data in tab delimited format (tabular)." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Tabular_.28tab_delimited.29"/> + <datatype extension="twobit" type="galaxy.datatypes.binary:TwoBit" mimetype="application/octet-stream" display_in_upload="true"/> + <datatype extension="sqlite" type="galaxy.datatypes.binary:SQlite" mimetype="application/octet-stream" display_in_upload="true"/> + <datatype extension="txt" type="galaxy.datatypes.data:Text" display_in_upload="true" description="Any text file." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Plain_text"/> + <datatype extension="linecount" type="galaxy.datatypes.data:LineCount" display_in_upload="false"/> + <datatype extension="memexml" type="galaxy.datatypes.xml:MEMEXml" mimetype="application/xml" display_in_upload="true"/> + <datatype extension="cisml" type="galaxy.datatypes.xml:CisML" mimetype="application/xml" display_in_upload="true"/> + <datatype extension="xml" type="galaxy.datatypes.xml:GenericXml" mimetype="application/xml" display_in_upload="true"/> + <datatype extension="vcf" type="galaxy.datatypes.tabular:Vcf" display_in_upload="true"> + <converter file="vcf_to_bgzip_converter.xml" target_datatype="bgzip"/> + <converter file="vcf_to_vcf_bgzip_converter.xml" target_datatype="vcf_bgzip"/> + <converter file="vcf_to_tabix_converter.xml" target_datatype="tabix" depends_on="bgzip"/> + <converter file="bed_gff_or_vcf_to_bigwig_converter.xml" target_datatype="bigwig"/> + <display file="ucsc/vcf.xml" /> + <display file="igv/vcf.xml" /> + <display file="rviewer/vcf.xml" inherit="True"/> + </datatype> + <datatype extension="bcf" type="galaxy.datatypes.binary:Bcf" mimetype="application/octet-stream" display_in_upload="True"/> + <datatype extension="velvet" type="galaxy.datatypes.assembly:Velvet" display_in_upload="false"/> + <datatype extension="wig" type="galaxy.datatypes.interval:Wiggle" display_in_upload="true" description="The wiggle format is line-oriented. Wiggle data is preceded by a track definition line, which adds a number of options for controlling the default display of this track." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Wig"> + <converter file="wig_to_bigwig_converter.xml" target_datatype="bigwig"/> + <converter file="wiggle_to_simple_converter.xml" target_datatype="interval"/> + <!-- <display file="gbrowse/gbrowse_wig.xml" /> --> + <display file="igb/wig.xml" /> + </datatype> + <datatype extension="interval_index" type="galaxy.datatypes.binary:Binary" subclass="True" /> + <datatype extension="tabix" type="galaxy.datatypes.binary:Binary" subclass="True" /> + <datatype extension="bgzip" type="galaxy.datatypes.binary:Binary" subclass="True" /> + <datatype extension="vcf_bgzip" type_extension="bgzip" subclass="True" > + <display file="igv/vcf.xml" /> + <converter file="vcf_bgzip_to_tabix_converter.xml" target_datatype="tabix"/> + </datatype> + <!-- Phylogenetic tree datatypes --> + <datatype extension="phyloxml" type="galaxy.datatypes.xml:Phyloxml" display_in_upload="true" /> + <datatype extension="nhx" type="galaxy.datatypes.data:Newick" display_in_upload="true" /> + <datatype extension="nex" type="galaxy.datatypes.data:Nexus" display_in_upload="true" /> + <!-- Start RGenetics Datatypes --> + <datatype extension="affybatch" type="galaxy.datatypes.genetics:Affybatch" display_in_upload="true"/> + <!-- eigenstrat pedigree input file --> + <datatype extension="eigenstratgeno" type="galaxy.datatypes.genetics:Eigenstratgeno"/> + <!-- eigenstrat pca output file for adjusted eigenQTL eg --> + <datatype extension="eigenstratpca" type="galaxy.datatypes.genetics:Eigenstratpca"/> + <datatype extension="eset" type="galaxy.datatypes.genetics:Eset" display_in_upload="true" /> + <!-- fbat/pbat format pedigree (header row of marker names) --> + <datatype extension="fped" type="galaxy.datatypes.genetics:Fped" display_in_upload="true"/> + <!-- phenotype file - fbat format --> + <datatype extension="fphe" type="galaxy.datatypes.genetics:Fphe" display_in_upload="true" mimetype="text/html"/> + <!-- genome graphs ucsc file - first col is always marker then numeric values to plot --> + <datatype extension="gg" type="galaxy.datatypes.genetics:GenomeGraphs"/> + <!-- part of linkage format pedigree --> + <!-- information redundancy (LD) filtered plink pbed --> + <datatype extension="ldindep" type="galaxy.datatypes.genetics:ldIndep" display_in_upload="true"> + </datatype> + <datatype extension="malist" type="galaxy.datatypes.genetics:MAlist" display_in_upload="true"/> + <!-- linkage format pedigree (separate .map file) --> + <datatype extension="lped" type="galaxy.datatypes.genetics:Lped" display_in_upload="true"> + <converter file="lped_to_fped_converter.xml" target_datatype="fped"/> + <converter file="lped_to_pbed_converter.xml" target_datatype="pbed"/> + </datatype> + <!-- plink compressed file - has bed extension unfortunately --> + <datatype extension="pbed" type="galaxy.datatypes.genetics:Pbed" display_in_upload="true"> + <converter file="pbed_to_lped_converter.xml" target_datatype="lped"/> + <converter file="pbed_ldreduced_converter.xml" target_datatype="ldindep"/> + </datatype> + <datatype extension="pheno" type="galaxy.datatypes.genetics:Pheno"/> + <!-- phenotype file - plink format --> + <datatype extension="pphe" type="galaxy.datatypes.genetics:Pphe" display_in_upload="true" mimetype="text/html"/> + <datatype extension="rexpbase" type="galaxy.datatypes.genetics:RexpBase"/> + <datatype extension="rgenetics" type="galaxy.datatypes.genetics:Rgenetics"/> + <datatype extension="snptest" type="galaxy.datatypes.genetics:Snptest" display_in_upload="true"/> + <datatype extension="snpmatrix" type="galaxy.datatypes.genetics:SNPMatrix" display_in_upload="true"/> + <datatype extension="xls" type="galaxy.datatypes.tabular:Tabular"/> + <!-- End RGenetics Datatypes --> + <!-- graph datatypes --> + <datatype extension="xgmml" type="galaxy.datatypes.graph:Xgmml" display_in_upload="true"/> + <datatype extension="sif" type="galaxy.datatypes.graph:Sif" display_in_upload="true"/> + <datatype extension="rdf" type="galaxy.datatypes.graph:Rdf" display_in_upload="true"/> + </registration> + <sniffers> + <!-- + The order in which Galaxy attempts to determine data types is + important because some formats are much more loosely defined + than others. The following list should be the most rigidly + defined format first, followed by next-most rigidly defined, + and so on. + --> + <sniffer type="galaxy.datatypes.tabular:Vcf"/> + <sniffer type="galaxy.datatypes.binary:TwoBit"/> + <sniffer type="galaxy.datatypes.binary:SQlite"/> + <sniffer type="galaxy.datatypes.binary:Bam"/> + <sniffer type="galaxy.datatypes.binary:Sff"/> + <sniffer type="galaxy.datatypes.xml:Phyloxml"/> + <sniffer type="galaxy.datatypes.xml:GenericXml"/> + <sniffer type="galaxy.datatypes.sequence:Maf"/> + <sniffer type="galaxy.datatypes.sequence:Lav"/> + <sniffer type="galaxy.datatypes.sequence:csFasta"/> + <sniffer type="galaxy.datatypes.qualityscore:QualityScoreSOLiD"/> + <sniffer type="galaxy.datatypes.qualityscore:QualityScore454"/> + <sniffer type="galaxy.datatypes.sequence:Fasta"/> + <sniffer type="galaxy.datatypes.sequence:Fastq"/> + <sniffer type="galaxy.datatypes.interval:Wiggle"/> + <sniffer type="galaxy.datatypes.images:Html"/> + <sniffer type="galaxy.datatypes.images:Pdf"/> + <sniffer type="galaxy.datatypes.sequence:Axt"/> + <sniffer type="galaxy.datatypes.interval:Bed"/> + <sniffer type="galaxy.datatypes.interval:CustomTrack"/> + <sniffer type="galaxy.datatypes.interval:Gtf"/> + <sniffer type="galaxy.datatypes.interval:Gff"/> + <sniffer type="galaxy.datatypes.interval:Gff3"/> + <sniffer type="galaxy.datatypes.tabular:Pileup"/> + <sniffer type="galaxy.datatypes.interval:Interval"/> + <sniffer type="galaxy.datatypes.tabular:Sam"/> + <sniffer type="galaxy.datatypes.data:Newick"/> + <sniffer type="galaxy.datatypes.data:Nexus"/> + <sniffer type="galaxy.datatypes.images:Jpg"/> + <sniffer type="galaxy.datatypes.images:Png"/> + <sniffer type="galaxy.datatypes.images:Tiff"/> + <sniffer type="galaxy.datatypes.images:Bmp"/> + <sniffer type="galaxy.datatypes.images:Gif"/> + <sniffer type="galaxy.datatypes.images:Im"/> + <sniffer type="galaxy.datatypes.images:Pcd"/> + <sniffer type="galaxy.datatypes.images:Pcx"/> + <sniffer type="galaxy.datatypes.images:Ppm"/> + <sniffer type="galaxy.datatypes.images:Psd"/> + <sniffer type="galaxy.datatypes.images:Xbm"/> + <sniffer type="galaxy.datatypes.images:Rgb"/> + <sniffer type="galaxy.datatypes.images:Pbm"/> + <sniffer type="galaxy.datatypes.images:Pgm"/> + <sniffer type="galaxy.datatypes.images:Xpm"/> + <sniffer type="galaxy.datatypes.images:Eps"/> + <sniffer type="galaxy.datatypes.images:Rast"/> + <!-- + Keep this commented until the sniff method in the assembly.py + module is fixed to not read the entire file. + <sniffer type="galaxy.datatypes.assembly:Amos"/> + --> + </sniffers> + <build_sites> + <!-- + Build sites define the builds (dbkeys) available at sites used by display + applications and the URL to those sites. + + The `display` attributes on the `ucsc` and `gbrowse` sites replace the + `ucsc_display_sites` and `gbrowse_display_sites` options in galaxy.ini. + Because these are used by "old-style" display applications, their types + cannot change if you want the old-style display links for these sites to + work. + --> + <site type="ucsc" file="tool-data/shared/ucsc/ucsc_build_sites.txt" display="main,test,archaea,ucla"/> + <site type="gbrowse" file="tool-data/shared/gbrowse/gbrowse_build_sites.txt" display="modencode,sgd_yeast,tair,wormbase,wormbase_ws120,wormbase_ws140,wormbase_ws170,wormbase_ws180,wormbase_ws190,wormbase_ws200,wormbase_ws204,wormbase_ws210,wormbase_ws220,wormbase_ws225"/> + <site type="ensembl" file="tool-data/shared/ensembl/ensembl_sites.txt"/> + <site type="ensembl_data_url" file="tool-data/shared/ensembl/ensembl_sites_data_URL.txt"/> + <site type="igv" file="tool-data/shared/igv/igv_build_sites.txt"/> + <site type="rviewer" file="tool-data/shared/rviewer/rviewer_build_sites.txt"/> + </build_sites> +</datatypes> diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/demo_sequencer_wsgi.ini.sample --- /dev/null +++ b/config/demo_sequencer_wsgi.ini.sample @@ -0,0 +1,66 @@ +# ---- HTTP Server ---------------------------------------------------------- + +[server:main] + +use = egg:Paste#http +port = 9011 +host = 0.0.0.0 +use_threadpool = true +threadpool_workers = 10 + +# ---- Galaxy Demo Sequencer Emulator Interface ------------------------------------------------- + +[app:main] + +# Specifies the factory for the universe WSGI application +paste.app_factory = galaxy.webapps.demo_sequencer.buildapp:app_factory +log_level = DEBUG + +# Where dataset files are saved +file_path = database/demo_sequencer_files +# Temporary storage for additional datasets, this should be shared through the cluster +new_file_path = database/tmp + +# Sequencer emulator actions +sequencer_actions_config_file = %(here)s/lib/galaxy/webapps/demo_sequencer/sequencer_actions.xml + +# Session support (beaker) +use_beaker_session = True +session_type = memory +session_data_dir = %(here)s/database/beaker_sessions +session_key = galaxysessions +session_secret = changethisinproduction + +# Galaxy session security +id_secret = changethisinproductiontoo + +# Configuration for debugging middleware +debug = true +use_lint = false + +# NEVER enable this on a public site (even test or QA) +# use_interactive = true + +# this should be a comma-separated list of valid Galaxy users +#admin_users = test@bx.psu.edu + +# Force everyone to log in (disable anonymous access) +require_login = False + +# Write thread status periodically to 'heartbeat.log' (careful, uses disk space rapidly!) +## use_heartbeat = True + +# Profiling middleware (cProfile based) +## use_profile = True + +# Use the new iframe / javascript based layout +use_new_layout = true + +# Serving static files (needed if running standalone) +static_enabled = True +static_cache_time = 360 +static_dir = %(here)s/static/ +static_images_dir = %(here)s/static/images +static_favicon_dir = %(here)s/static/favicon.ico +static_scripts_dir = %(here)s/static/scripts/ +static_style_dir = %(here)s/static/june_2007_style/blue diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/external_service_types_conf.xml.sample --- /dev/null +++ b/config/external_service_types_conf.xml.sample @@ -0,0 +1,5 @@ +<?xml version="1.0"?> +<external_service_types> + <external_service_type file="simple_unknown_sequencer.xml" visible="False"/> + <external_service_type file="applied_biosystems_solid.xml" visible="True"/> +</external_service_types> diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/galaxy.ini.sample --- /dev/null +++ b/config/galaxy.ini.sample @@ -0,0 +1,889 @@ +# +# Galaxy is configured by default to be useable in a single-user development +# environment. To tune the application for a multi-user production +# environment, see the documentation at: +# +# http://usegalaxy.org/production +# + +# Throughout this sample configuration file, except where stated otherwise, +# uncommented values override the default if left unset, whereas commented +# values are set to the default value. Relative paths are relative to the root +# Galaxy directory. +# +# Examples of many of these options are explained in more detail in the wiki: +# +# https://wiki.galaxyproject.org/Admin/Config +# +# Config hackers are encouraged to check there before asking for help. + +# ---- HTTP Server ---------------------------------------------------------- + +# Configuration of the internal HTTP server. + +[server:main] + +# The internal HTTP server to use. Currently only Paste is provided. This +# option is required. +use = egg:Paste#http + +# The port on which to listen. +#port = 8080 + +# The address on which to listen. By default, only listen to localhost (Galaxy +# will not be accessible over the network). Use '0.0.0.0' to listen on all +# available network interfaces. +#host = 127.0.0.1 + +# Use a threadpool for the web server instead of creating a thread for each +# request. +use_threadpool = True + +# Number of threads in the web server thread pool. +#threadpool_workers = 10 + +# Set the number of seconds a thread can work before you should kill it (assuming it will never finish) to 3 hours. +threadpool_kill_thread_limit = 10800 + +# ---- Filters -------------------------------------------------------------- + +# Filters sit between Galaxy and the HTTP server. + +# These filters are disabled by default. They can be enabled with +# 'filter-with' in the [app:main] section below. + +# Define the gzip filter. +[filter:gzip] +use = egg:Paste#gzip + +# Define the proxy-prefix filter. +[filter:proxy-prefix] +use = egg:PasteDeploy#prefix +prefix = /galaxy + +# ---- Galaxy --------------------------------------------------------------- + +# Configuration of the Galaxy application. + +[app:main] + +# -- Application and filtering + +# The factory for the WSGI application. This should not be changed. +paste.app_factory = galaxy.web.buildapp:app_factory + +# If not running behind a proxy server, you may want to enable gzip compression +# to decrease the size of data transferred over the network. If using a proxy +# server, please enable gzip compression there instead. +#filter-with = gzip + +# If running behind a proxy server and Galaxy is served from a subdirectory, +# enable the proxy-prefix filter and set the prefix in the +# [filter:proxy-prefix] section above. +#filter-with = proxy-prefix + +# If proxy-prefix is enabled and you're running more than one Galaxy instance +# behind one hostname, you will want to set this to the same path as the prefix +# in the filter above. This value becomes the "path" attribute set in the +# cookie so the cookies from each instance will not clobber each other. +#cookie_path = None + +# -- Database + +# By default, Galaxy uses a SQLite database at 'database/universe.sqlite'. You +# may use a SQLAlchemy connection string to specify an external database +# instead. This string takes many options which are explained in detail in the +# config file documentation. +#database_connection = sqlite:///./database/universe.sqlite?isolation_level=IMMEDIATE + +# If the server logs errors about not having enough database pool connections, +# you will want to increase these values, or consider running more Galaxy +# processes. +#database_engine_option_pool_size = 5 +#database_engine_option_max_overflow = 10 + +# If using MySQL and the server logs the error "MySQL server has gone away", +# you will want to set this to some positive value (7200 should work). +#database_engine_option_pool_recycle = -1 + +# If large database query results are causing memory or response time issues in +# the Galaxy process, leave the result on the server instead. This option is +# only available for PostgreSQL and is highly recommended. +#database_engine_option_server_side_cursors = False + +# Log all database transactions, can be useful for debugging and performance +# profiling. Logging is done via Python's 'logging' module under the qualname +# 'galaxy.model.orm.logging_connection_proxy' +#database_query_profiling_proxy = False + +# By default, Galaxy will use the same database to track user data and +# tool shed install data. There are many situtations in which it is +# valuable to seperate these - for instance bootstrapping fresh Galaxy +# instances with pretested installs. The following optin can be used to +# separate the tool shed install database (all other options listed above +# but prefixed with install_ are also available). +#install_database_connection = sqlite:///./database/universe.sqlite?isolation_level=IMMEDIATE + +# -- Files and directories + +# Dataset files are stored in this directory. +#file_path = database/files + +# Temporary files are stored in this directory. +#new_file_path = database/tmp + +# Tool config files, defines what tools are available in Galaxy. +# Tools can be locally developed or installed from Galaxy tool sheds. +# (config/tool_conf.xml.sample will be used if left unset and +# config/tool_conf.xml does not exist). +#tool_config_file = config/tool_conf.xml,shed_tool_conf.xml + +# Enable / disable checking if any tools defined in the above non-shed tool_config_files +# (i.e., tool_conf.xml) have been migrated from the Galaxy code distribution to the Tool +# Shed. This setting should generally be set to False only for development Galaxy environments +# that are often rebuilt from scratch where migrated tools do not need to be available in the +# Galaxy tool panel. If the following setting remains commented, the default setting will be True. +#check_migrate_tools = True + +# Tool config maintained by tool migration scripts. If you use the migration +# scripts to install tools that have been migrated to the tool shed upon a new +# release, they will be added to this tool config file. +#migrated_tools_config = migrated_tools_conf.xml + +# File that contains the XML section and tool tags from all tool panel config +# files integrated into a single file that defines the tool panel layout. This +# file can be changed by the Galaxy administrator to alter the layout of the +# tool panel. If not present, Galaxy will create it. +#integrated_tool_panel_config = integrated_tool_panel.xml + +# Default path to the directory containing the tools defined in tool_conf.xml. +# Other tool config files must include the tool_path as an attribute in the <toolbox> tag. +#tool_path = tools + +# Path to the directory in which tool dependencies are placed. This is used by +# the tool shed to install dependencies and can also be used by administrators +# to manually install or link to dependencies. For details, see: +# https://wiki.galaxyproject.org/Admin/Config/ToolDependencies +# If this option is not set to a valid path, installing tools with dependencies +# from the Tool Shed will fail. +#tool_dependency_dir = None + +# File containing the Galaxy Tool Sheds that should be made available to +# install from in the admin interface (.sample used if default does not exist). +#tool_sheds_config_file = config/tool_sheds_conf.xml + +# Enable automatic polling of relative tool sheds to see if any updates +# are available for installed repositories. Ideally only one Galaxy +# server process should be able to check for repository updates. The +# setting for hours_between_check should be an integer between 1 and 24. +#enable_tool_shed_check = False +#hours_between_check = 12 + +# Enable use of an in-memory registry with bi-directional relationships +# between repositories (i.e., in addition to lists of dependencies for a +# repository, keep an in-memory registry of dependent items for each repository. +#manage_dependency_relationships = False + +# XML config file that contains data table entries for the +# ToolDataTableManager. This file is manually # maintained by the Galaxy +# administrator (.sample used if default does not exist). +#tool_data_table_config_path = config/tool_data_table_conf.xml + +# XML config file that contains additional data table entries for the ToolDataTableManager. This file +# is automatically generated based on the current installed tool shed repositories that contain valid +# tool_data_table_conf.xml.sample files. At the time of installation, these entries are automatically +# added to the following file, which is parsed and applied to the ToolDataTableManager at server start up. +#shed_tool_data_table_config = config/shed_tool_data_table_conf.xml + +# Directory where data used by tools is located, see the samples in that +# directory and the wiki for help: +# https://wiki.galaxyproject.org/Admin/DataIntegration +#tool_data_path = tool-data + +# File containing old-style genome builds +#builds_file_path = tool-data/shared/ucsc/builds.txt + +# Directory where chrom len files are kept, currently mainly used by trackster +#len_file_path = tool-data/shared/ucsc/chrom + +# Datatypes config file, defines what data (file) types are available in +# Galaxy (.sample is used if default does not exist). +#datatypes_config_file = config/datatypes_conf.xml + +# Disable the 'Auto-detect' option for file uploads +#datatypes_disable_auto = False + +# Visualizations config directory: where to look for individual visualization plugins. +# The path is relative to the Galaxy root dir. To use an absolute path begin the path +# with '/'. Defaults to "config/plugins/visualizations". +#visualization_plugins_directory = config/plugins/visualizations + +# Each job is given a unique empty directory as its current working directory. +# This option defines in what parent directory those directories will be +# created. +#job_working_directory = database/job_working_directory + +# If using a cluster, Galaxy will write job scripts and stdout/stderr to this +# directory. +#cluster_files_directory = database/pbs + +# Mako templates are compiled as needed and cached for reuse, this directory is +# used for the cache +#template_cache_path = database/compiled_templates + +# Citation related caching. Tool citations information maybe fetched from +# external sources such as http://dx.doi.org/ by Galaxy - the following parameters +# can be used to control the caching used to store this information. +#citation_cache_type = file +#citation_cache_data_dir = database/citations/data +#citation_cache_lock_dir = database/citations/lock + +# External service types config file, defines what types of external_services configurations +# are available in Galaxy (.sample is used if default does not exist). +#external_service_type_config_file = config/external_service_types_conf.xml + +# Path to the directory containing the external_service_types defined in the config. +#external_service_type_path = external_service_types + +# Tools with a number of outputs not known until runtime can write these +# outputs to a directory for collection by Galaxy when the job is done. +# Previously, this directory was new_file_path, but using one global directory +# can cause performance problems, so using job_working_directory ('.' or cwd +# when a job is run) is encouraged. By default, both are checked to avoid +# breaking existing tools. +#collect_outputs_from = new_file_path,job_working_directory + +# -- Data Storage (Object Store) +# +# Configuration file for the object store +# If this is set and exists, it overrides any other objectstore settings. +# object_store_config_file = config/object_store_conf.xml + +# Object store backend module (valid options are: disk, s3, swift, irods, +# distributed, hierarchical) +#object_store = disk + +# *Extremely* old Galaxy instances created datasets at the root of the +# `file_path` defined above. If your Galaxy instance has datasets at the root +# (instead of in directories composed by hashing the dataset id), you should +# enable this option to allow Galaxy to find them. +#object_store_check_old_style = False + +# Credentials used by certain (s3, swift) object store backends +#os_access_key = <your cloud object store access key> +#os_secret_key = <your cloud object store secret key> +#os_bucket_name = <name of an existing object store bucket or container> + +# If using 'swift' object store, you must specify the following connection +# properties +#os_host = swift.rc.nectar.org.au +#os_port = 8888 +#os_is_secure = False +#os_conn_path = / + +# Reduced redundancy can be used only with the 's3' object store +#os_use_reduced_redundancy = False + +# Path to cache directory for object store backends that utilize a cache (s3, +# swift, irods) +#object_store_cache_path = database/files/ + +# Size (in GB) that the cache used by object store should be limited to. +# If the value is not specified, the cache size will be limited only by the +# file system size. +#object_store_cache_size = 100 + +# Configuration file for the distributed object store, if object_store = +# distributed. See the sample at distributed_object_store_conf.xml.sample +#distributed_object_store_config_file = None + + +# -- Mail and notification + +# Galaxy sends mail for various things: Subscribing users to the mailing list +# if they request it, emailing password resets, notification from the Galaxy +# Sample Tracking system, reporting dataset errors, and sending activation emails. +# To do this, it needs to send mail through an SMTP server, which you may define here (host:port). +# Galaxy will automatically try STARTTLS but will continue upon failure. +#smtp_server = None + +# If your SMTP server requires a username and password, you can provide them +# here (password in cleartext here, but if your server supports STARTTLS it +# will be sent over the network encrypted). +#smtp_username = None +#smtp_password = None + +# If your SMTP server requires SSL from the beginning of the connection +# smtp_ssl = False + +# On the user registration form, users may choose to join the mailing list. +# This is the address of the list they'll be subscribed to. +#mailing_join_addr = galaxy-announce-join@bx.psu.edu + +# Datasets in an error state include a link to report the error. Those reports +# will be sent to this address. Error reports are disabled if no address is set. +# Also this email is shown as a contact to user in case of Galaxy misconfiguration and other events user may encounter. +#error_email_to = None + +# Activation email is used as a sender ('from' field) for the account activation mail. +# We recommend using string in the following format: Galaxy Project <galaxy-no-reply@example.com> +#activation_email = None + +# URL of the support resource for the galaxy instance. Used in activation emails. +#instance_resource_url = http://wiki.galaxyproject.org/ + +# E-mail domains blacklist is used for filtering out users that are using disposable email address +# during the registration. If their address domain matches any domain in the BL they are refused the registration. +#blacklist_file = config/disposable_email_blacklist.conf + +# Registration warning message is used to discourage people from registering multiple accounts. Applies mostly for the main Galaxy instance. +# If no message specified the warning box will not be shown. +#registration_warning_message = Please register only one account - we provide this service free of charge and have limited computational resources. Multi-accounts are tracked and will be subjected to account termination and data deletion. + +# When users opt to reset passwords, new ones are created, this option +# specifies the length of these passwords. +#reset_password_length = 15 + + +# -- Account activation + +# This is user account activation feature global flag. If set to "False" the rest of the Account +# activation configuration is ignored and user activation is disabled (a.k.a. accounts are active since registration). +# Note the activation is also not working in case the smtp server is not defined. +#user_activation_on = False + +# Activation grace period. Activation is not forced (login is not disabled) until +# grace period has passed. Users under grace period can't run jobs (see inactivity_box_content). +# In hours. Default is 3. Enter 0 to disable grace period. +# Users with OpenID logins have grace period forever. +#activation_grace_period = 0 + +# Used for warning box for inactive accounts (unable to run jobs). +# In use only if activation_grace_period is set. +#inactivity_box_content = Your account has not been activated yet. Feel free to browse around and see what's available, but you won't be able to upload data or run jobs until you have verified your email address. + + +# -- Display sites + +# Galaxy can display data at various external browsers. These options specify +# which browsers should be available. URLs and builds available at these +# browsers are defined in the specifield files. + +# If use_remote_user = True, display application servers will be denied access +# to Galaxy and so displaying datasets in these sites will fail. +# display_servers contains a list of hostnames which should be allowed to +# bypass security to display datasets. Please be aware that there are security +# implications if this is allowed. More details (including required changes to +# the proxy server config) are available in the Apache proxy documentation on +# the wiki. +# +# The list of servers in this sample config are for the UCSC Main, Test and +# Archaea browsers, but the default if left commented is to not allow any +# display sites to bypass security (you must uncomment the line below to allow +# them). +#display_servers = hgw1.cse.ucsc.edu,hgw2.cse.ucsc.edu,hgw3.cse.ucsc.edu,hgw4.cse.ucsc.edu,hgw5.cse.ucsc.edu,hgw6.cse.ucsc.edu,hgw7.cse.ucsc.edu,hgw8.cse.ucsc.edu,lowepub.cse.ucsc.edu + +# To disable the old-style display applications that are hardcoded into datatype classes, +# set enable_old_display_applications = False. +# This may be desirable due to using the new-style, XML-defined, display applications that +# have been defined for many of the datatypes that have the old-style. +# There is also a potential security concern with the old-style applications, +# where a malicious party could provide a link that appears to reference the Galaxy server, +# but contains a redirect to a third-party server, tricking a Galaxy user to access said +# site. +#enable_old_display_applications = True + +# -- Next gen LIMS interface on top of existing Galaxy Sample/Request management code. + +use_nglims = False +nglims_config_file = tool-data/nglims.yaml + +# -- UI Localization + +# Show a message box under the masthead. +#message_box_visible = False +#message_box_content = None +#message_box_class = info + +# Append "/{brand}" to the "Galaxy" text in the masthead. +#brand = None + +# Format string used when showing date and time information. +# The string may contain: +# - the directives used by Python time.strftime() function (see http://docs.python.org/2/library/time.html#time.strftime ), +# - $locale (complete format string for the server locale), +# - $iso8601 (complete format string as specified by ISO 8601 international standard). +# pretty_datetime_format = $locale (UTC) + +# The URL of the page to display in Galaxy's middle pane when loaded. This can be +# an absolute or relative URL. +#welcome_url = /static/welcome.html + +# The URL linked by the "Galaxy/brand" text. +#logo_url = / + +# The URL linked by the "Wiki" link in the "Help" menu. +#wiki_url = http://wiki.galaxyproject.org/ + +# The URL linked by the "Support" link in the "Help" menu. +#support_url = http://wiki.galaxyproject.org/Support + +# The URL linked by the "How to Cite Galaxy" link in the "Help" menu. +#citation_url = http://wiki.galaxyproject.org/CitingGalaxy + +#The URL linked by the "Search" link in the "Help" menu. +#search_url = http://galaxyproject.org/search/usegalaxy/ + +#The URL linked by the "Mailing Lists" link in the "Help" menu. +#mailing_lists_url = http://wiki.galaxyproject.org/MailingLists + +#The URL linked by the "Videos" link in the "Help" menu. +#videos_url = http://vimeo.com/galaxyproject + +# The URL linked by the "Terms and Conditions" link in the "Help" menu, as well +# as on the user registration and login forms and in the activation emails. +#terms_url = None + +# The URL linked by the "Galaxy Q&A" link in the "Help" menu +# The Galaxy Q&A site is under development; when the site is done, this URL +# will be set and uncommented. +#qa_url = + +# Serve static content, which must be enabled if you're not serving it via a +# proxy server. These options should be self explanatory and so are not +# documented individually. You can use these paths (or ones in the proxy +# server) to point to your own styles. +#static_enabled = True +#static_cache_time = 360 +#static_dir = static/ +#static_images_dir = static/images +#static_favicon_dir = static/favicon.ico +#static_scripts_dir = static/scripts/ +#static_style_dir = static/june_2007_style/blue +#static_robots_txt = static/robots.txt + +# Pack javascript at launch (/static/scripts/*.js) +# This only happens if the modified timestamp of the source .js is newer +# than the version (if it exists) in /static/scripts/packed/ +# Note that this requires java > 1.4 for executing yuicompressor.jar +#pack_scripts = False + +# Cloud Launch + +#enable_cloud_launch = False +#cloudlaunch_default_ami = ami-a7dbf6ce + +# Incremental Display Options + +#display_chunk_size = 65536 + +# -- Advanced proxy features + +# For help on configuring the Advanced proxy features, see: +# http://usegalaxy.org/production + +# Apache can handle file downloads (Galaxy-to-user) via mod_xsendfile. Set +# this to True to inform Galaxy that mod_xsendfile is enabled upstream. +#apache_xsendfile = False + +# The same download handling can be done by nginx using X-Accel-Redirect. This +# should be set to the path defined in the nginx config as an internal redirect +# with access to Galaxy's data files (see documentation linked above). +#nginx_x_accel_redirect_base = False + +# nginx can make use of mod_zip to create zip files containing multiple library +# files. If using X-Accel-Redirect, this can be the same value as that option. +#nginx_x_archive_files_base = False + +# If using compression in the upstream proxy server, use this option to disable +# gzipping of library .tar.gz and .zip archives, since the proxy server will do +# it faster on the fly. +#upstream_gzip = False + +# nginx can also handle file uploads (user-to-Galaxy) via nginx_upload_module. +# Configuration for this is complex and explained in detail in the +# documentation linked above. The upload store is a temporary directory in +# which files uploaded by the upload module will be placed. +#nginx_upload_store = False + +# This value overrides the action set on the file upload form, e.g. the web +# path where the nginx_upload_module has been configured to intercept upload +# requests. +#nginx_upload_path = False + +# -- Logging and Debugging + +# Verbosity of console log messages. Acceptable values can be found here: +# http://docs.python.org/library/logging.html#logging-levels +#log_level = DEBUG + +# Print database operations to the server log (warning, quite verbose!). +#database_engine_option_echo = False + +# Print database pool operations to the server log (warning, quite verbose!). +#database_engine_option_echo_pool = False + +# Turn on logging of application events and some user events to the database. +#log_events = True + +# Turn on logging of user actions to the database. Actions currently logged are +# grid views, tool searches, and use of "recently" used tools menu. The +# log_events and log_actions functionality will eventually be merged. +#log_actions = True + +# Sanitize All HTML Tool Output +# By default, all tool output served as 'text/html' will be sanitized +# thoroughly. This can be disabled if you have special tools that require +# unaltered output. +#sanitize_all_html = True + +# By default Galaxy will serve non-HTML tool output that may potentially +# contain browser executable JavaScript content as plain text. This will for +# instance cause SVG datasets to not render properly and so may be disabled +# by setting the following option to True. +#serve_xss_vulnerable_mimetypes = False + +# Debug enables access to various config options useful for development and +# debugging: use_lint, use_profile, use_printdebug and use_interactive. It +# also causes the files used by PBS/SGE (submission script, output, and error) +# to remain on disk after the job is complete. Debug mode is disabled if +# commented, but is uncommented by default in the sample config. +debug = True + +# Check for WSGI compliance. +#use_lint = False + +# Run the Python profiler on each request. +#use_profile = False + +# Intercept print statements and show them on the returned page. +#use_printdebug = True + +# Enable live debugging in your browser. This should NEVER be enabled on a +# public site. Enabled in the sample config for development. +use_interactive = True + +# Write thread status periodically to 'heartbeat.log', (careful, uses disk +# space rapidly!). Useful to determine why your processes may be consuming a +# lot of CPU. +#use_heartbeat = False + +# Enable the memory debugging interface (careful, negatively impacts server +# performance). +#use_memdump = False + +# -- Data Libraries + +# These library upload options are described in much more detail in the wiki: +# https://wiki.galaxyproject.org/Admin/DataLibraries/UploadingLibraryFiles + +# Add an option to the library upload form which allows administrators to +# upload a directory of files. +#library_import_dir = None + +# Add an option to the library upload form which allows authorized +# non-administrators to upload a directory of files. The configured directory +# must contain sub-directories named the same as the non-admin user's Galaxy +# login ( email ). The non-admin user is restricted to uploading files or +# sub-directories of files contained in their directory. +#user_library_import_dir = None + +# Add an option to the admin library upload tool allowing admins to paste +# filesystem paths to files and directories in a box, and these paths will be +# added to a library. Set to True to enable. Please note the security +# implication that this will give Galaxy Admins access to anything your Galaxy +# user has access to. +#allow_library_path_paste = False + +# Users may choose to download multiple files from a library in an archive. By +# default, Galaxy allows users to select from a few different archive formats +# if testing shows that Galaxy is able to create files using these formats. +# Specific formats can be disabled with this option, separate more than one +# format with commas. Available formats are currently 'zip', 'gz', and 'bz2'. +#disable_library_comptypes = + +# Some sequencer integration features in beta allow you to automatically +# transfer datasets. This is done using a lightweight transfer manager which +# runs outside of Galaxy (but is spawned by it automatically). Galaxy will +# communicate with this manager over the port specified here. +#transfer_manager_port = 8163 + +# Search data libraries with whoosh +#enable_whoosh_library_search = True +# Whoosh indexes are stored in this directory. +#whoosh_index_dir = database/whoosh_indexes + +# Search data libraries with lucene +#enable_lucene_library_search = False +# maxiumum file size to index for searching, in MB +#fulltext_max_size = 500 +#fulltext_noindex_filetypes = bam,sam,wig,bigwig,fasta,fastq,fastqsolexa,fastqillumina,fastqsanger +# base URL of server providing search functionality using lucene +#fulltext_url = http://localhost:8081 + +# -- Users and Security + +# Galaxy encodes various internal values when these values will be output in +# some format (for example, in a URL or cookie). You should set a key to be +# used by the algorithm that encodes and decodes these values. It can be any +# string. If left unchanged, anyone could construct a cookie that would grant +# them access to others' sessions. +#id_secret = USING THE DEFAULT IS NOT SECURE! + +# User authentication can be delegated to an upstream proxy server (usually +# Apache). The upstream proxy should set a REMOTE_USER header in the request. +# Enabling remote user disables regular logins. For more information, see: +# https://wiki.galaxyproject.org/Admin/Config/ApacheProxy +#use_remote_user = False + +# If use_remote_user is enabled and your external authentication +# method just returns bare usernames, set a default mail domain to be appended +# to usernames, to become your Galaxy usernames (email addresses). +#remote_user_maildomain = None + +# If use_remote_user is enabled, the header that the upstream proxy provides +# the remote username in defaults to HTTP_REMOTE_USER (the 'HTTP_' is prepended +# by WSGI). This option allows you to change the header. Note, you still need +# to prepend 'HTTP_' to the header in this option, but your proxy server should +# *not* include 'HTTP_' at the beginning of the header name. +#remote_user_header = HTTP_REMOTE_USER + +# If use_remote_user is enabled, you can set this to a URL that will log your +# users out. +#remote_user_logout_href = None + +# If your proxy and/or authentication source does not normalize e-mail +# addresses or user names being passed to Galaxy - set the following option +# to True to force these to lower case. +#normalize_remote_user_email = False + +# Administrative users - set this to a comma-separated list of valid Galaxy +# users (email addresses). These users will have access to the Admin section +# of the server, and will have access to create users, groups, roles, +# libraries, and more. For more information, see: +# https://wiki.galaxyproject.org/Admin/Interface +#admin_users = None + +# Force everyone to log in (disable anonymous access). +#require_login = False + +# Allow unregistered users to create new accounts (otherwise, they will have to +# be created by an admin). +#allow_user_creation = True + +# Allow administrators to delete accounts. +#allow_user_deletion = False + +# Allow administrators to log in as other users (useful for debugging) +#allow_user_impersonation = False + +# Allow users to remove their datasets from disk immediately (otherwise, +# datasets will be removed after a time period specified by an administrator in +# the cleanup scripts run via cron) +#allow_user_dataset_purge = False + +# By default, users' data will be public, but setting this to True will cause +# it to be private. Does not affect existing users and data, only ones created +# after this option is set. Users may still change their default back to +# public. +#new_user_dataset_access_role_default_private = False + +# -- Beta features + +# Enable Galaxy to communicate directly with a sequencer +#enable_sequencer_communication = False + +# Enable authentication via OpenID. Allows users to log in to their Galaxy +# account by authenticating with an OpenID provider. +#enable_openid = False +# .sample used if default does not exist +#openid_config_file = config/openid_conf.xml +#openid_consumer_cache_path = database/openid_consumer_cache + +# Optional list of email addresses of API users who can make calls on behalf of +# other users +#api_allow_run_as = None + +# Master key that allows many API admin actions to be used without actually +# having a defined admin user in the database/config. Only set this if you need +# to bootstrap Galaxy, you probably do not want to set this on public servers. +#master_api_key = changethis + +# Enable tool tags (associating tools with tags). This has its own option +# since its implementation has a few performance implications on startup for +# large servers. +#enable_tool_tags = False + +# Enable a feature when running workflows. When enabled, default datasets +# are selected for "Set at Runtime" inputs from the history such that the +# same input will not be selected twice, unless there are more inputs than +# compatible datasets in the history. +# When False, the most recently added compatible item in the history will +# be used for each "Set at Runtime" input, independent of others in the Workflow +#enable_unique_workflow_defaults = False + +# The URL to the myExperiment instance being used (omit scheme but include port) +#myexperiment_url = www.myexperiment.org:80 + +# Enable Galaxy's "Upload via FTP" interface. You'll need to install and +# configure an FTP server (we've used ProFTPd since it can use Galaxy's +# database for authentication) and set the following two options. + +# This should point to a directory containing subdirectories matching users' +# email addresses, where Galaxy will look for files. +#ftp_upload_dir = None + +# This should be the hostname of your FTP server, which will be provided to +# users in the help text. +#ftp_upload_site = None + +# Enable enforcement of quotas. Quotas can be set from the Admin interface. +#enable_quotas = False + +# This option allows users to see the full path of datasets via the "View +# Details" option in the history. Administrators can always see this. +#expose_dataset_path = False + +# Data manager configuration options +# Allow non-admin users to view available Data Manager options +#enable_data_manager_user_view = False +# File where Data Managers are configured (.sample used if default does not +# exist) +#data_manager_config_file = config/data_manager_conf.xml +# File where Tool Shed based Data Managers are configured +#shed_data_manager_config_file = config/shed_data_manager_conf.xml +# Directory to store Data Manager based tool-data; defaults to tool_data_path +#galaxy_data_manager_data_path = tool-data + +# -- Job Execution + +# To increase performance of job execution and the web interface, you can +# separate Galaxy into multiple processes. There are more than one way to do +# this, and they are explained in detail in the documentation: +# +# https://wiki.galaxyproject.org/Admin/Config/Performance/Scaling + +# By default, Galaxy manages and executes jobs from within a single process and +# notifies itself of new jobs via in-memory queues. Jobs are run locally on +# the system on which Galaxy is started. Advanced job running capabilities can +# be configured through the job configuration file. +#job_config_file = config/job_conf.xml + +# In multiprocess configurations, notification between processes about new jobs +# is done via the database. In single process configurations, this is done in +# memory, which is a bit quicker. Galaxy tries to automatically determine +# which method it should used based on your handler configuration in the job +# config file, but you can explicitly override this behavior by setting the +# following option to True or False. +#track_jobs_in_database = None + +# This enables splitting of jobs into tasks, if specified by the particular tool config. +# This is a new feature and not recommended for production servers yet. +#use_tasked_jobs = False +#local_task_queue_workers = 2 + +# Enable job recovery (if Galaxy is restarted while cluster jobs are running, +# it can "recover" them when it starts). This is not safe to use if you are +# running more than one Galaxy server using the same database. +#enable_job_recovery = True + +# Although it is fairly reliable, setting metadata can occasionally fail. In +# these instances, you can choose to retry setting it internally or leave it in +# a failed state (since retrying internally may cause the Galaxy process to be +# unresponsive). If this option is set to False, the user will be given the +# option to retry externally, or set metadata manually (when possible). +#retry_metadata_internally = True + +# If (for example) you run on a cluster and your datasets (by default, +# database/files/) are mounted read-only, this option will override tool output +# paths to write outputs to the working directory instead, and the job manager +# will move the outputs to their proper place in the dataset directory on the +# Galaxy server after the job completes. +#outputs_to_working_directory = False + +# If your network filesystem's caching prevents the Galaxy server from seeing +# the job's stdout and stderr files when it completes, you can retry reading +# these files. The job runner will retry the number of times specified below, +# waiting 1 second between tries. For NFS, you may want to try the -noac mount +# option (Linux) or -actimeo=0 (Solaris). +#retry_job_output_collection = 0 + +# Clean up various bits of jobs left on the filesystem after completion. These +# bits include the job working directory, external metadata temporary files, +# and DRM stdout and stderr files (if using a DRM). Possible values are: +# always, onsuccess, never +#cleanup_job = always + +# File to source to set up the environment when running jobs. By default, the +# environment in which the Galaxy server starts is used when running jobs +# locally, and the environment set up per the DRM's submission method and +# policy is used when running jobs on a cluster (try testing with `qsub` on the +# command line). environment_setup_file can be set to the path of a file on +# the cluster that should be sourced by the user to set up the environment +# prior to running tools. This can be especially useful for running jobs as +# the actual user, to remove the need to configure each user's environment +# individually. +#environment_setup_file = None + + +# Optional file containing job resource data entry fields definition. +# These fields will be presented to users in the tool forms and allow them to +# overwrite default job resources such as number of processors, memory, and walltime. +#job_resource_params_file = config/job_resource_params_conf.xml + +# If using job concurrency limits (configured in job_config_file), several +# extra database queries must be performed to determine the number of jobs a +# user has dispatched to a given destination. By default, these queries will +# happen for every job that is waiting to run, but if cache_user_job_count is +# set to True, it will only happen once per iteration of the handler queue. +# Although better for performance due to reduced queries, the tradeoff is a +# greater possibility that jobs will be dispatched past the configured limits +# if running many handlers. +#cache_user_job_count = False + +# ToolBox filtering +# Modules from lib/galaxy/tools/filters/ can be specified in the following lines. +# tool_* filters will be applied for all users and can not be changed by them. +# user_tool_* filters will be shown under user preferences and can be toogled +# on and off by runtime +#tool_filters +#tool_label_filters +#tool_section_filters +#user_tool_filters = examples:restrict_upload_to_admins, examples:restrict_encode +#user_tool_section_filters = examples:restrict_text +#user_tool_label_filters = examples:restrict_upload_to_admins, examples:restrict_encode + +# Galaxy Application Internal Message Queue + +# Galaxy uses AMQP internally TODO more documentation on what for. +# For examples, see http://ask.github.io/kombu/userguide/connections.html +# +# Without specifying anything here, galaxy will first attempt to use your +# specified database_connection above. If that's not specified either, Galaxy +# will automatically create and use a separate sqlite database located in your +# <galaxy>/database folder (indicated in the commented out line below). + +#amqp_internal_connection = sqlalchemy+sqlite:///./database/control.sqlite?isolation_level=IMMEDIATE + + + +# ---- Galaxy External Message Queue ------------------------------------------------- + +# Galaxy uses AMQ protocol to receive messages from external sources like +# bar code scanners. Galaxy has been tested against RabbitMQ AMQP implementation. +# For Galaxy to receive messages from a message queue the RabbitMQ server has +# to be set up with a user account and other parameters listed below. The 'host' +# and 'port' fields should point to where the RabbitMQ server is running. + +[galaxy_amqp] + +#host = 127.0.0.1 +#port = 5672 +#userid = galaxy +#password = galaxy +#virtual_host = galaxy_messaging_engine +#queue = galaxy_queue +#exchange = galaxy_exchange +#routing_key = bar_code_scanner +#rabbitmqctl_path = /path/to/rabbitmqctl + diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/job_conf.xml.sample_advanced --- /dev/null +++ b/config/job_conf.xml.sample_advanced @@ -0,0 +1,482 @@ +<?xml version="1.0"?> +<job_conf> + <plugins workers="4"> + <!-- "workers" is the number of threads for the runner's work queue. + The default from <plugins> is used if not defined for a <plugin>. + --> + <plugin id="local" type="runner" load="galaxy.jobs.runners.local:LocalJobRunner"/> + <plugin id="pbs" type="runner" load="galaxy.jobs.runners.pbs:PBSJobRunner" workers="2"/> + <plugin id="drmaa" type="runner" load="galaxy.jobs.runners.drmaa:DRMAAJobRunner"> + <!-- Different DRMs handle successfully completed jobs differently, + these options can be changed to handle such differences and + are explained in detail on the Galaxy wiki. Defaults are shown --> + <param id="invalidjobexception_state">ok</param> + <param id="invalidjobexception_retries">0</param> + <param id="internalexception_state">ok</param> + <param id="internalexception_retries">0</param> + </plugin> + <plugin id="sge" type="runner" load="galaxy.jobs.runners.drmaa:DRMAAJobRunner"> + <!-- Override the $DRMAA_LIBRARY_PATH environment variable --> + <param id="drmaa_library_path">/sge/lib/libdrmaa.so</param> + </plugin> + <plugin id="cli" type="runner" load="galaxy.jobs.runners.cli:ShellJobRunner" /> + <plugin id="condor" type="runner" load="galaxy.jobs.runners.condor:CondorJobRunner" /> + <plugin id="slurm" type="runner" load="galaxy.jobs.runners.slurm:SlurmJobRunner" /> + <plugin id="dynamic" type="runner"> + <!-- The dynamic runner is not a real job running plugin and is + always loaded, so it does not need to be explicitly stated in + <plugins>. However, if you wish to change the base module + containing your dynamic rules, you can do so. + + The `load` attribute is not required (and ignored if + included). + --> + <param id="rules_module">galaxy.jobs.rules</param> + </plugin> + <!-- Pulsar runners (see more at https://pulsar.readthedocs.org) --> + <plugin id="pulsar_rest" type="runner" load="galaxy.jobs.runners.pulsar:PulsarRESTJobRunner"> + <!-- Allow optimized HTTP calls with libcurl (defaults to urllib) --> + <!-- <param id="transport">curl</param> --> + + <!-- *Experimental Caching*: Next parameter enables caching. + Likely will not work with newer features such as MQ support. + + If this is enabled be sure to specify a `file_cache_dir` in + the remote Pulsar's servers main configuration file. + --> + <!-- <param id="cache">True</param> --> + </plugin> + <plugin id="pulsar_mq" type="runner" load="galaxy.jobs.runners.pulsar:PulsarMQJobRunner"> + <!-- AMQP URL to connect to. --> + <param id="amqp_url">amqp://guest:guest@localhost:5672//</param> + <!-- URL remote Pulsar apps should transfer files to this Galaxy + instance to/from. --> + <param id="galaxy_url">http://localhost:8080</param> + <!-- Pulsar job manager to communicate with (see Pulsar + docs for information on job managers). --> + <!-- <param id="manager">_default_</param> --> + <!-- The AMQP client can provide an SSL client certificate (e.g. for + validation), the following options configure that certificate + (see for reference: + http://kombu.readthedocs.org/en/latest/reference/kombu.connection.html + ). If you simply want to use SSL but not use/validate a client + cert, just use the ?ssl=1 query on the amqp URL instead. --> + <!-- <param id="amqp_connect_ssl_ca_certs">/path/to/cacert.pem</param> --> + <!-- <param id="amqp_connect_ssl_keyfile">/path/to/key.pem</param> --> + <!-- <param id="amqp_connect_ssl_certfile">/path/to/cert.pem</param> --> + <!-- <param id="amqp_connect_ssl_cert_reqs">cert_required</param> --> + <!-- By default, the AMQP consumer uses a nonblocking connection with + a 0.2 second timeout. In testing, this works fine for + unencrypted AMQP connections, but with SSL it will cause the + client to reconnect to the server after each timeout. Set to a + higher value (in seconds) (or `None` to use blocking connections). --> + <!-- <param id="amqp_consumer_timeout">None</param> --> + </plugin> + <plugin id="pulsar_legacy" type="runner" load="galaxy.jobs.runners.pulsar:PulsarLegacyJobRunner"> + <!-- Pulsar job runner with default parameters matching those + of old LWR job runner. If your Pulsar server is running on a + Windows machine for instance this runner should still be used. + + These destinations still needs to target a Pulsar server, + older LWR plugins and destinations still work in Galaxy can + target LWR servers, but this support should be considered + deprecated and will disappear with a future release of Galaxy. + --> + </plugin> + </plugins> + <handlers default="handlers"> + <!-- Additional job handlers - the id should match the name of a + [server:<id>] in galaxy.ini. + --> + <handler id="handler0" tags="handlers"/> + <handler id="handler1" tags="handlers"/> + <!-- Handlers will load all plugins defined in the <plugins> collection + above by default, but can be limited to a subset using <plugin> + tags. This is useful for heterogenous environments where the DRMAA + plugin would need to be loaded more than once with different + configs. + --> + <handler id="sge_handler"> + <plugin id="sge"/> + </handler> + <handler id="special_handler0" tags="special_handlers"/> + <handler id="special_handler1" tags="special_handlers"/> + <handler id="trackster_handler"/> + </handlers> + <destinations default="local"> + <!-- Destinations define details about remote resources and how jobs + should be executed on those remote resources. + --> + <destination id="local" runner="local"/> + <destination id="multicore_local" runner="local"> + <param id="local_slots">4</param><!-- Specify GALAXY_SLOTS for local jobs. --> + <!-- Warning: Local slot count doesn't tie up additional worker threads, to prevent over + allocating machine define a second local runner with different name and fewer workers + to run this destination. --> + <param id="embed_metadata_in_job">True</param> + <!-- Above parameter will be default (with no option to set + to False) in an upcoming release of Galaxy, but you can + try it early - it will slightly speed up local jobs by + embedding metadata calculation in job script itself. + --> + <job_metrics /> + <!-- Above element demonstrates embedded job metrics definition - see + job_metrics_conf.xml.sample for full documentation on possible nested + elements. This empty block will simply disable job metrics for the + corresponding destination. --> + </destination> + <destination id="docker_local" runner="local"> + <param id="docker_enabled">true</param> + <!-- docker_volumes can be used to configure volumes to expose to docker, + For added isolation append :ro to the path to mount it read only. + Galaxy will attempt to infer a reasonable set of defaults which + volumes should be exposed how based on Galaxy's settings and the + destination - but be sure to add any library paths or data incides + that may be needed read-only. + --> + <!-- + <param id="docker_volumes">$defaults,/mnt/galaxyData/libraries:ro,/mnt/galaxyData/indices:ro</param> + --> + <!-- For a stock Galaxy instance and traditional job runner $defaults will + expand out as: + + $galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:rw + + This assumes most of what is needed is available under Galaxy's root directory, + the tool directory, and the Galaxy's file_path (if using object store creatively + you will definitely need to expand defaults). + + This configuration allows any docker instance to write to any Galaxy + file - for greater isolation set outputs_to_working_directory in + galaxy.ini. This will cause $defaults to allow writing to much + less. It will then expand as follows: + + $galaxy_root:ro,$tool_directory:ro,$working_directory:rw,$default_file_path:ro + + If using the Pulsar, defaults will be even further restricted because the + Pulsar will (by default) stage all needed inputs into the job's job_directory + (so there is not need to allow the docker container to read all the + files - let alone write over them). Defaults in this case becomes: + + $job_directory:ro,$tool_directory:ro,$job_directory/outputs:rw,$working_directory:rw + + Python string.Template is used to expand volumes and values $defaults, + $galaxy_root, $default_file_path, $tool_directory, $working_directory, + are available to all jobs and $job_directory is also available for + Pulsar jobs. + --> + <!-- One can run docker using volumes-from tag by setting the following + parameter. For more information on volumes-from check out the following + docker tutorial. https://docs.docker.com/userguide/dockervolumes/ + --> + <!-- <param id="docker_volumes_from">parent_container_name</param> --> + <!-- Control memory allocatable by docker container with following option: + --> + <!-- <param id="docker_memory">24G</param> --> + <!-- By default Docker will need to runnable by Galaxy using + password-less sudo - this can be configured by adding the + following line to the sudoers file of all compute nodes + with docker enabled: + + galaxy ALL = (root) NOPASSWD: SETENV: /usr/bin/docker + + The follow option is set to false to disable sudo (docker + must likewise be configured to allow this). + --> + <!-- <param id="docker_sudo">false</param> --> + <!-- Following option can be used to tweak sudo command used by + default. --> + <!-- <param id="docker_sudo_cmd">/usr/bin/sudo -extra_param</param> --> + <!-- By default, docker container will not have any networking + enabled. host networking can be bridged by uncommenting next option + http://docs.docker.io/reference/run/#network-settings + --> + <!-- <param id="docker_net">bridge</param> --> + <!-- Following command can be used to tweak docker command. --> + <!-- <param id="docker_cmd">/usr/local/custom_docker/docker</param> --> + <!-- Following can be used to connect to docke server in different + ways (translated as -H argument to docker client). --> + <!-- <param id="docker_host">unix:///var/run/docker.sock</param> --> + <!-- <param id="docker_host">:5555</param> --> + <!-- <param id="docker_host">:5555</param> --> + <!-- <param id="docker_host">tcp://127.0.0.1:4243</param> --> + + <!-- If deployer wants to use docker for isolation, but does not + trust tool's specified container - a destination wide override + can be set. This will cause all jobs on this destination to use + that docker image. --> + <!-- <param id="docker_container_id_override">busybox:ubuntu-14.04</param> --> + + <!-- Likewise, if deployer wants to use docker for isolation and + does trust tool's specified container - but also wants tool's not + configured to run in a container the following option can provide + a fallback. --> + <!-- <param id="docker_default_container_id">busybox:ubuntu-14.04</param> --> + + </destination> + <destination id="pbs" runner="pbs" tags="mycluster"/> + <destination id="pbs_longjobs" runner="pbs" tags="mycluster,longjobs"> + <!-- Define parameters that are native to the job runner plugin. --> + <param id="Resource_List">walltime=72:00:00</param> + </destination> + <destination id="remote_cluster" runner="drmaa" tags="longjobs"/> + <destination id="java_cluster" runner="drmaa"> + <!-- set arbitrary environment variables at runtime. General + dependencies for tools should be configured via + tool_dependency_dir and package options and these + options should be reserved for defining cluster + specific options. + --> + <env id="_JAVA_OPTIONS">-Xmx=6GB</env> + <env id="ANOTHER_OPTION" raw="true">'5'</env><!-- raw disables auto quoting --> + <env file="/mnt/java_cluster/environment_setup.sh" /><!-- will be sourced --> + <env exec="module load javastuff/2.10" /><!-- will be sourced --> + <!-- files to source and exec statements will be handled on remote + clusters. These don't need to be available on the Galaxy server + itself. + --> + </destination> + <destination id="real_user_cluster" runner="drmaa"> + <!-- TODO: The real user options should maybe not be considered runner params. --> + <param id="galaxy_external_runjob_script">scripts/drmaa_external_runner.py</param> + <param id="galaxy_external_killjob_script">scripts/drmaa_external_killer.py</param> + <param id="galaxy_external_chown_script">scripts/external_chown_script.py</param> + </destination> + <destination id="dynamic" runner="dynamic"> + <!-- A destination that represents a method in the dynamic runner. --> + <param id="function">foo</param> + </destination> + <destination id="load_balance" runner="dynamic"> + <param id="type">choose_one</param> + <!-- Randomly assign jobs to various static destination ids --> + <param id="destination_ids">cluster1,cluster2,cluster3</param> + </destination> + <destination id="load_balance_with_data_locality" runner="dynamic"> + <!-- Randomly assign jobs to various static destination ids, + but keep jobs in the same workflow invocation together and + for those jobs ran outside of workflows keep jobs in same + history together. + --> + <param id="type">choose_one</param> + <param id="destination_ids">cluster1,cluster2,cluster3</param> + <param id="hash_by">workflow_invocation,history</param> + </destination> + <destination id="burst_out" runner="dynamic"> + <!-- Burst out from static destination local_cluster_8_core to + static destination shared_cluster_8_core when there are about + 50 Galaxy jobs assigned to any of the local_cluster_XXX + destinations (either running or queued). If there are fewer + than 50 jobs, just use local_cluster_8_core destination. + + Uncomment job_state parameter to make this bursting happen when + roughly 50 jobs are queued instead. + --> + <param id="type">burst</param> + <param id="from_destination_ids">local_cluster_8_core,local_cluster_1_core,local_cluster_16_core</param> + <param id="to_destination_id">shared_cluster_8_core</param> + <param id="num_jobs">50</param> + <!-- <param id="job_states">queued</param> --> + </destination> + <destination id="docker_dispatch" runner="dynamic"> + <!-- Follow dynamic destination type will send all tool's that + support docker to static destination defined by + docker_destination_id (docker_cluster in this example) and all + other tools to default_destination_id (normal_cluster in this + example). + --> + <param id="type">docker_dispatch</param> + <param id="docker_destination_id">docker_cluster</param> + <param id="default_destination_id">normal_cluster</param> + </destination> + <destination id="secure_pulsar_rest_dest" runner="pulsar_rest"> + <param id="url">https://examle.com:8913/</param> + <!-- If set, private_token must match token in remote Pulsar's + configuration. --> + <param id="private_token">123456789changeme</param> + <!-- Uncomment the following statement to disable file staging (e.g. + if there is a shared file system between Galaxy and the Pulsar + server). Alternatively action can be set to 'copy' - to replace + http transfers with file system copies, 'remote_transfer' to cause + the Pulsar to initiate HTTP transfers instead of Galaxy, or + 'remote_copy' to cause Pulsar to initiate file system copies. + If setting this to 'remote_transfer' be sure to specify a + 'galaxy_url' attribute on the runner plugin above. --> + <!-- <param id="default_file_action">none</param> --> + <!-- The above option is just the default, the transfer behavior + none|copy|http can be configured on a per path basis via the + following file. See Pulsar documentation for more details and + examples. + --> + <!-- <param id="file_action_config">file_actions.yaml</param> --> + <!-- The non-legacy Pulsar runners will attempt to resolve Galaxy + dependencies remotely - to enable this set a tool_dependency_dir + in Pulsar's configuration (can work with all the same dependency + resolutions mechanisms as Galaxy - tool Shed installs, Galaxy + packages, etc...). To disable this behavior, set the follow parameter + to none. To generate the dependency resolution command locally + set the following parameter local. + --> + <!-- <param id="dependency_resolution">none</params> --> + <!-- Uncomment following option to enable setting metadata on remote + Pulsar server. The 'use_remote_datatypes' option is available for + determining whether to use remotely configured datatypes or local + ones (both alternatives are a little brittle). --> + <!-- <param id="remote_metadata">true</param> --> + <!-- <param id="use_remote_datatypes">false</param> --> + <!-- <param id="remote_property_galaxy_home">/path/to/remote/galaxy-central</param> --> + <!-- If remote Pulsar server is configured to run jobs as the real user, + uncomment the following line to pass the current Galaxy user + along. --> + <!-- <param id="submit_user">$__user_name__</param> --> + <!-- Various other submission parameters can be passed along to the Pulsar + whose use will depend on the remote Pulsar's configured job manager. + For instance: + --> + <!-- <param id="submit_native_specification">-P bignodes -R y -pe threads 8</param> --> + <!-- Disable parameter rewriting and rewrite generated commands + instead. This may be required if remote host is Windows machine + but probably not otherwise. + --> + <!-- <param id="rewrite_parameters">false</params> --> + </destination> + <destination id="pulsar_mq_dest" runner="amqp_pulsar" > + <!-- The RESTful Pulsar client sends a request to Pulsar + to populate various system properties. This + extra step can be disabled and these calculated here + on client by uncommenting jobs_directory and + specifying any additional remote_property_ of + interest, this is not optional when using message + queues. + --> + <param id="jobs_directory">/path/to/remote/pulsar/files/staging/</param> + <!-- Otherwise MQ and Legacy pulsar destinations can be supplied + all the same destination parameters as the RESTful client documented + above (though url and private_token are ignored when using a MQ). + --> + </destination> + <destination id="ssh_torque" runner="cli"> + <param id="shell_plugin">SecureShell</param> + <param id="job_plugin">Torque</param> + <param id="shell_username">foo</param> + <param id="shell_hostname">foo.example.org</param> + <param id="job_Resource_List">walltime=24:00:00,ncpus=4</param> + </destination> + + <!-- Example CLI Slurm runner. --> + <destination id="ssh_slurm" runner="cli"> + <param id="shell_plugin">SecureShell</param> + <param id="job_plugin">Slurm</param> + <param id="shell_username">foo</param> + <param id="shell_hostname">my_host</param> + <param id="job_time">2:00:00</param> + <param id="job_ncpus">4</param> + <param id="job_partition">my_partition</param> + </destination> + + <destination id="condor" runner="condor"> + <!-- With no params, jobs are submitted to the 'vanilla' universe with: + notification = NEVER + getenv = true + Additional/override query ClassAd params can be specified with + <param> tags. + --> + <param id="request_cpus">8</param> + </destination> + + <!-- Jobs that hit the walltime on one destination can be automatically + resubmitted to another destination. Walltime detection is + currently only implemented in the slurm runner. + + Multiple resubmit tags can be defined, the first resubmit matching + the terminal condition of a job will be used. + + The 'condition' attribute is optional, if not present, the + resubmit destination will be used for all conditions. Currently, + only the "walltime_reached" condition is implemented. + + The 'handler' tag is optional, if not present, the job's original + handler will be reused for the resubmitted job. + --> + <destination id="short_fast" runner="slurm"> + <param id="nativeSpecification">--time=00:05:00 --nodes=1</param> + <resubmit condition="walltime_reached" destination="long_slow" handler="sge_handler" /> + </destination> + <destination id="long_slow" runner="sge"> + <!-- The destination that you resubmit jobs to can be any runner type --> + <param id="nativeSpecification">-l h_rt=96:00:00</param> + </destination> + + </destinations> + <resources default="default"> + <!-- Group different parameters defined in job_resource_params_conf.xml + together and assign these groups ids. Tool section below can map + tools to different groups. This is experimental functionality! + --> + <group id="default"></group> + <group id="memoryonly">memory</group> + <group id="all">processors,memory,time,project</group> + </resources> + <tools> + <!-- Tools can be configured to use specific destinations or handlers, + identified by either the "id" or "tags" attribute. If assigned to + a tag, a handler or destination that matches that tag will be + chosen at random. + --> + <tool id="foo" handler="trackster_handler"> + <param id="source">trackster</param> + </tool> + <tool id="bar" destination="dynamic"/> + <!-- Next example defines resource group to insert into tool interface + and pass to dynamic destination (as resource_params argument). --> + <tool id="longbar" destination="dynamic" resources="all" /> + <tool id="baz" handler="special_handlers" destination="bigmem"/> + </tools> + <limits> + <!-- Certain limits can be defined. The 'concurrent_jobs' limits all + control the number of jobs that can be "active" at a time, that + is, dispatched to a runner and in the 'queued' or 'running' + states. + + A race condition exists that will allow destination_* concurrency + limits to be surpassed when multiple handlers are allowed to + handle jobs for the same destination. To prevent this, assign all + jobs for a specific destination to a single handler. + --> + <!-- registered_user_concurrent_jobs: + Limit on the number of jobs a user with a registered Galaxy + account can have active across all destinations. + --> + <limit type="registered_user_concurrent_jobs">2</limit> + <!-- anonymous_user_concurrent_jobs: + Likewise, but for unregistered/anonymous users. + --> + <limit type="anonymous_user_concurrent_jobs">1</limit> + <!-- destination_user_concurrent_jobs: + The number of jobs a user can have active in the specified + destination, or across all destinations identified by the + specified tag. (formerly: concurrent_jobs) + --> + <limit type="destination_user_concurrent_jobs" id="local">1</limit> + <limit type="destination_user_concurrent_jobs" tag="mycluster">2</limit> + <limit type="destination_user_concurrent_jobs" tag="longjobs">1</limit> + <!-- destination_total_concurrent_jobs: + The number of jobs that can be active in the specified + destination (or across all destinations identified by the + specified tag) by any/all users. + --> + <limit type="destination_total_concurrent_jobs" id="local">16</limit> + <limit type="destination_total_concurrent_jobs" tag="longjobs">100</limit> + <!-- walltime: + Amount of time a job can run (in any destination) before it + will be terminated by Galaxy. + --> + <limit type="walltime">24:00:00</limit> + <!-- output_size: + Size that any defined tool output can grow to before the job + will be terminated. This does not include temporary files + created by the job. Format is flexible, e.g.: + '10GB' = '10g' = '10240 Mb' = '10737418240' + --> + <limit type="output_size">10GB</limit> + </limits> +</job_conf> diff -r 773bae7768c1fed8d6fcd2e2c374fc0245ed06f4 -r 898a4bda231824bc0453d5e593e0b86a9e1004e9 config/job_conf.xml.sample_basic --- /dev/null +++ b/config/job_conf.xml.sample_basic @@ -0,0 +1,13 @@ +<?xml version="1.0"?> +<!-- A sample job config that explicitly configures job running the way it is configured by default (if there is no explicit config). --> +<job_conf> + <plugins> + <plugin id="local" type="runner" load="galaxy.jobs.runners.local:LocalJobRunner" workers="4"/> + </plugins> + <handlers> + <handler id="main"/> + </handlers> + <destinations> + <destination id="local" runner="local"/> + </destinations> +</job_conf> This diff is so big that we needed to truncate the remainder. Repository URL: https://bitbucket.org/galaxy/galaxy-central/ -- This is a commit notification from bitbucket.org. You are receiving this because you have the service enabled, addressing the recipient of this email.
participants (1)
-
commits-noreply@bitbucket.org