mirror of
https://github.com/galaxyproject/galaxy.git
synced 2026-10-24 02:04:04 +08:00
Merge remote-tracking branch 'upstream/dev' into managers.history-contents
This commit is contained in:
+1
-1
@@ -86,7 +86,7 @@ tool-data/genome/*
|
||||
tool-data/*.sample
|
||||
tool-data/testtoolshed.g2.bx.psu.edu/
|
||||
tool-data/toolshed.g2.bx.psu.edu/
|
||||
|
||||
tool-data/**/*.fa
|
||||
|
||||
# Test output
|
||||
test-data-cache
|
||||
|
||||
+1
-1
@@ -24,5 +24,5 @@ module.exports = function(grunt) {
|
||||
// see the sub directory grunt-tasks/ for individual task definitions
|
||||
grunt.loadTasks( 'grunt-tasks' );
|
||||
// note: 'handlebars' *not* 'templates' since handlebars doesn't call uglify
|
||||
grunt.registerTask( 'default', [ 'check-modules', 'handlebars', 'uglify' ] );
|
||||
grunt.registerTask( 'default', [ 'check-modules', 'uglify', 'webpack' ] );
|
||||
};
|
||||
|
||||
+19
-7
@@ -46,19 +46,31 @@ This will:
|
||||
|
||||
1. compress the files in client/galaxy/scripts and place them in static/scripts
|
||||
2. generate source maps and place them in static/maps
|
||||
3. rebuild the webpack-based client apps
|
||||
|
||||
|
||||
Templates
|
||||
=========
|
||||
Rebuilding Scripts Only
|
||||
=======================
|
||||
|
||||
You can change and recompile the templates by using:
|
||||
To re-minify all the individual javascript files:
|
||||
|
||||
grunt templates
|
||||
grunt scripts
|
||||
|
||||
This will:
|
||||
|
||||
1. recompile the templates in client/galaxy/scripts/templates to client/galaxy/scripts/templates/compiled
|
||||
2. minify and generate source maps for the compiled templates
|
||||
Rebuilding Webpack Apps
|
||||
=======================
|
||||
|
||||
To rebuild the webpack bundles for apps (compressed for production):
|
||||
|
||||
grunt webpack
|
||||
|
||||
To rebuild the apps without compression:
|
||||
|
||||
grunt webpack-dev
|
||||
|
||||
To rebuild without compression and watch and rebuild when scripts change:
|
||||
|
||||
grunt webpack-watch
|
||||
|
||||
|
||||
Changing Styles/CSS
|
||||
|
||||
+1
-2
@@ -14,7 +14,7 @@
|
||||
"underscore": "~1.7.0",
|
||||
"backbone": "~1.1.2",
|
||||
"bootstrap": "~3.3.2",
|
||||
"bootstrap-tour":"~0.10.2",
|
||||
"bootstrap-tour": "~0.10.2",
|
||||
"d3": "~3.5.3",
|
||||
"farbtastic": "~2.0.0-alpha.1",
|
||||
"toastr": "~2.1.0",
|
||||
@@ -31,7 +31,6 @@
|
||||
"jstree": "~3.0.9",
|
||||
"jquery-ui": "git://github.com/jquery/jquery-ui.git#~1.11.2",
|
||||
"threedubmedia.jquery.event": "*",
|
||||
"handlebars": "~3.0.0",
|
||||
"jquery-migrate": "~1.2.1",
|
||||
"requirejs": "~2.1.17"
|
||||
},
|
||||
|
||||
@@ -30,7 +30,6 @@ window.app = function app( options, bootstrapped ){
|
||||
toolPanel = new ToolPanel({
|
||||
el : '#left',
|
||||
userIsAnonymous : Galaxy.user.isAnonymous(),
|
||||
spinner_url : config.spinner_url,
|
||||
search_url : config.search_url,
|
||||
toolbox : config.toolbox,
|
||||
toolbox_in_panel : config.toolbox_in_panel,
|
||||
|
||||
@@ -17,7 +17,6 @@ var ToolPanel = LeftPanel.extend({
|
||||
|
||||
// create tool search, tool panel, and tool panel view.
|
||||
var tool_search = new Tools.ToolSearch({
|
||||
spinner_url : options.spinner_url,
|
||||
search_url : options.search_url,
|
||||
hidden : false
|
||||
});
|
||||
|
||||
@@ -173,7 +173,7 @@ var Collection = Backbone.Collection.extend({
|
||||
if ( !Galaxy.user.id ){
|
||||
var userTab = {
|
||||
id : 'user',
|
||||
icon : 'fa-user',
|
||||
title : 'User',
|
||||
cls : 'loggedout-only',
|
||||
tooltip : 'Account registration or login',
|
||||
menu : [{
|
||||
@@ -191,7 +191,7 @@ var Collection = Backbone.Collection.extend({
|
||||
} else {
|
||||
var userTab = {
|
||||
id : 'user',
|
||||
icon : 'fa-user',
|
||||
title : 'User',
|
||||
cls : 'loggedin-only',
|
||||
tooltip : 'Account preferences and saved data',
|
||||
menu : [{
|
||||
@@ -243,77 +243,64 @@ var Collection = Backbone.Collection.extend({
|
||||
/** Masthead tab **/
|
||||
var Tab = Backbone.View.extend({
|
||||
initialize: function ( options ) {
|
||||
var self = this;
|
||||
this.model = options.model;
|
||||
this.setElement( this._template() );
|
||||
this.$dropdown = this.$( '.dropdown' );
|
||||
this.$toggle = this.$( '.dropdown-toggle' );
|
||||
this.$menu = this.$( '.dropdown-menu' );
|
||||
this.$note = this.$( '.dropdown-note' );
|
||||
this.model = options.model;
|
||||
this.$el.attr( 'id', this.model.id );
|
||||
this.model.on( 'init change:title', function() {
|
||||
this.get( 'title' ) && self.$toggle.html( this.get( 'title' ) );
|
||||
}).on( 'init change:visible', function() {
|
||||
self.$el.css( { visibility : this.get( 'visible' ) && 'visible' || 'hidden' } );
|
||||
}).on( 'init change:note', function() {
|
||||
self.$note.html( this.get( 'note' ) );
|
||||
}).on( 'init change:note_cls', function() {
|
||||
this._prevNoteCls && self.$note.removeClass( this._prevNoteCls );
|
||||
this.get( 'note_cls' ) && self.$note.addClass( this._prevNoteCls = this.get( 'note_cls' ) );
|
||||
}).on( 'init change:show_note', function() {
|
||||
self.$note.css( { 'display' : this.get( 'show_note' ) && 'block' || 'none' } );
|
||||
}).on( 'init change:target', function() {
|
||||
self.$toggle.attr( 'target', this.get( 'target' ) );
|
||||
}).on( 'init change:url', function() {
|
||||
this.set( 'url', self._formatUrl( this.get( 'url' ) ) );
|
||||
self.$toggle.attr( 'href', this.get( 'url' ) );
|
||||
}).on( 'init change:tooltip', function() {
|
||||
$( '.tooltip' ).remove();
|
||||
self.$toggle.tooltip( 'destroy' ).attr( 'title', this.get( 'tooltip' ) );
|
||||
this.get( 'tooltip' ) && self.$toggle.tooltip( { placement: 'bottom' } );
|
||||
}).on( 'init change:cls', function() {
|
||||
this._prevCls && self.$toggle.removeClass( this._prevCls );
|
||||
this.get( 'cls' ) && self.$toggle.addClass( this._prevCls = this.get( 'cls' ) );
|
||||
}).on( 'init change:icon', function() {
|
||||
this._prevIcon && self.$toggle.removeClass( this._prevIcon );
|
||||
this.get( 'icon' ) && self.$toggle.addClass( this._prevIcon = 'fa fa-2x ' + this.get( 'icon' ) );
|
||||
}).on( 'init change:toggle', function() {
|
||||
self.$toggle[ this.get( 'toggle' ) && 'addClass' || 'removeClass' ]( 'toggle' );
|
||||
}).on( 'init change:disabled', function() {
|
||||
self.$toggle[ this.get( 'disabled' ) && 'addClass' || 'removeClass' ]( 'disabled' );
|
||||
self._configurePopover();
|
||||
}).on( 'init change:active', function() {
|
||||
self.$dropdown[ this.get( 'active' ) && 'addClass' || 'removeClass' ]( 'active' );
|
||||
}).on( 'init change:show_menu', function() {
|
||||
if ( this.get( 'menu' ) && this.get( 'show_menu' ) ) {
|
||||
self.$menu.show();
|
||||
$( '#dd-helper' ).show().off().on( 'click', function() {
|
||||
$( '#dd-helper' ).hide();
|
||||
self.model.set( 'show_menu', false );
|
||||
});
|
||||
} else {
|
||||
self.$menu.hide();
|
||||
$( '#dd-helper' ).hide();
|
||||
}
|
||||
}).on( 'init change:menu', function() {
|
||||
self.$menu.empty().removeClass( 'dropdown-menu' );
|
||||
self.$toggle.find( 'b' ).remove();
|
||||
if ( this.get( 'menu' ) ) {
|
||||
_.each( this.get( 'menu' ), function( menuItem ) {
|
||||
self.$menu.append( self._buildMenuItem( menuItem ) );
|
||||
menuItem.divider && self.$menu.append( $( '<li/>' ).addClass( 'divider' ) );
|
||||
});
|
||||
self.$menu.addClass( 'dropdown-menu' );
|
||||
self.$toggle.append( $( '<b/>' ).addClass( 'caret' ) );
|
||||
}
|
||||
}).trigger( 'init' );
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
},
|
||||
|
||||
/** Attach events */
|
||||
events: {
|
||||
'click .dropdown-toggle' : '_toggleClick'
|
||||
},
|
||||
|
||||
render: function() {
|
||||
var self = this;
|
||||
$( '.tooltip' ).remove();
|
||||
this.$el.attr( 'id', this.model.id )
|
||||
.css( { visibility : this.model.get( 'visible' ) && 'visible' || 'hidden' } );
|
||||
this.model.set( 'url', this._formatUrl( this.model.get( 'url' ) ) );
|
||||
this.$note.html( this.model.get( 'note' ) || '' )
|
||||
.removeClass().addClass( 'dropdown-note' )
|
||||
.addClass( this.model.get( 'note_cls' ) )
|
||||
.css( { 'display' : this.model.get( 'show_note' ) && 'block' || 'none' } )
|
||||
this.$toggle.html( this.model.get( 'title' ) || '' )
|
||||
.removeClass().addClass( 'dropdown-toggle' )
|
||||
.addClass( this.model.get( 'cls' ) )
|
||||
.addClass( this.model.get( 'icon' ) && 'fa fa-2x ' + this.model.get( 'icon' ) )
|
||||
.addClass( this.model.get( 'toggle' ) && 'toggle' )
|
||||
.attr( 'target', this.model.get( 'target' ) )
|
||||
.attr( 'href', this.model.get( 'url' ) )
|
||||
.attr( 'title', this.model.get( 'tooltip' ) )
|
||||
.tooltip( 'destroy' );
|
||||
this.model.get( 'tooltip' ) && this.$toggle.tooltip( { placement: 'bottom' } );
|
||||
this.$dropdown.removeClass().addClass( 'dropdown' )
|
||||
.addClass( this.model.get( 'disabled' ) && 'disabled' )
|
||||
.addClass( this.model.get( 'active' ) && 'active' );
|
||||
if ( this.model.get( 'menu' ) && this.model.get( 'show_menu' ) ) {
|
||||
this.$menu.show();
|
||||
$( '#dd-helper' ).show().off().on( 'click', function() {
|
||||
$( '#dd-helper' ).hide();
|
||||
self.model.set( 'show_menu', false );
|
||||
});
|
||||
} else {
|
||||
self.$menu.hide();
|
||||
$( '#dd-helper' ).hide();
|
||||
}
|
||||
this.$menu.empty().removeClass( 'dropdown-menu' );
|
||||
if ( this.model.get( 'menu' ) ) {
|
||||
_.each( this.model.get( 'menu' ), function( menuItem ) {
|
||||
self.$menu.append( self._buildMenuItem( menuItem ) );
|
||||
menuItem.divider && self.$menu.append( $( '<li/>' ).addClass( 'divider' ) );
|
||||
});
|
||||
self.$menu.addClass( 'dropdown-menu' );
|
||||
self.$toggle.append( $( '<b/>' ).addClass( 'caret' ) );
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
/** Add new menu item */
|
||||
_buildMenuItem: function ( options ) {
|
||||
var self = this;
|
||||
@@ -354,26 +341,21 @@ var Tab = Backbone.View.extend({
|
||||
} else {
|
||||
model.set( 'show_menu', true );
|
||||
}
|
||||
} else {
|
||||
function buildLink( label, url ) {
|
||||
return $( '<div/>' ).append( $( '<a/>' ).attr( 'href', Galaxy.root + url ).html( label ) ).html()
|
||||
}
|
||||
this.$toggle.popover && this.$toggle.popover( 'destroy' );
|
||||
this.$toggle.popover({
|
||||
html : true,
|
||||
placement : 'bottom',
|
||||
content : 'Please ' + buildLink( 'login', 'user/login?use_panels=True' ) + ' or ' +
|
||||
buildLink( 'register', 'user/create?use_panels=True' ) + ' to use this feature.'
|
||||
}).popover( 'show' );
|
||||
setTimeout( function() { self.$toggle.popover( 'destroy' ) }, 5000 );
|
||||
}
|
||||
},
|
||||
|
||||
/** Configures login notification/popover */
|
||||
_configurePopover: function() {
|
||||
var self = this;
|
||||
function buildLink( label, url ) {
|
||||
return $( '<div/>' ).append( $( '<a/>' ).attr( 'href', Galaxy.root + url ).html( label ) ).html()
|
||||
}
|
||||
this.$toggle.popover && this.$toggle.popover( 'destroy' );
|
||||
this.model.get( 'disabled' ) && this.$toggle.popover({
|
||||
html : true,
|
||||
placement : 'bottom',
|
||||
content : 'Please ' + buildLink( 'login', 'user/login?use_panels=True' ) + ' or ' +
|
||||
buildLink( 'register', 'user/create?use_panels=True' ) + ' to use this feature.'
|
||||
}).on( 'shown.bs.popover', function() {
|
||||
setTimeout( function() { self.$toggle.popover( 'hide' ) }, 5000 );
|
||||
});
|
||||
},
|
||||
|
||||
/** Url formatting */
|
||||
_formatUrl: function( url ) {
|
||||
return typeof url == 'string' && url.indexOf( '//' ) === -1 && url.charAt( 0 ) != '/' ? Galaxy.root + url : url;
|
||||
|
||||
@@ -1,881 +0,0 @@
|
||||
/*!
|
||||
|
||||
handlebars v3.0.3
|
||||
|
||||
Copyright (C) 2011-2014 by Yehuda Katz
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
||||
@license
|
||||
*/
|
||||
(function webpackUniversalModuleDefinition(root, factory) {
|
||||
if(typeof exports === 'object' && typeof module === 'object')
|
||||
module.exports = factory();
|
||||
else if(typeof define === 'function' && define.amd)
|
||||
define(factory);
|
||||
else if(typeof exports === 'object')
|
||||
exports["Handlebars"] = factory();
|
||||
else
|
||||
root["Handlebars"] = factory();
|
||||
})(this, function() {
|
||||
return /******/ (function(modules) { // webpackBootstrap
|
||||
/******/ // The module cache
|
||||
/******/ var installedModules = {};
|
||||
|
||||
/******/ // The require function
|
||||
/******/ function __webpack_require__(moduleId) {
|
||||
|
||||
/******/ // Check if module is in cache
|
||||
/******/ if(installedModules[moduleId])
|
||||
/******/ return installedModules[moduleId].exports;
|
||||
|
||||
/******/ // Create a new module (and put it into the cache)
|
||||
/******/ var module = installedModules[moduleId] = {
|
||||
/******/ exports: {},
|
||||
/******/ id: moduleId,
|
||||
/******/ loaded: false
|
||||
/******/ };
|
||||
|
||||
/******/ // Execute the module function
|
||||
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
|
||||
|
||||
/******/ // Flag the module as loaded
|
||||
/******/ module.loaded = true;
|
||||
|
||||
/******/ // Return the exports of the module
|
||||
/******/ return module.exports;
|
||||
/******/ }
|
||||
|
||||
|
||||
/******/ // expose the modules object (__webpack_modules__)
|
||||
/******/ __webpack_require__.m = modules;
|
||||
|
||||
/******/ // expose the module cache
|
||||
/******/ __webpack_require__.c = installedModules;
|
||||
|
||||
/******/ // __webpack_public_path__
|
||||
/******/ __webpack_require__.p = "";
|
||||
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ return __webpack_require__(0);
|
||||
/******/ })
|
||||
/************************************************************************/
|
||||
/******/ ([
|
||||
/* 0 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var _interopRequireWildcard = __webpack_require__(7)['default'];
|
||||
|
||||
exports.__esModule = true;
|
||||
|
||||
var _import = __webpack_require__(1);
|
||||
|
||||
var base = _interopRequireWildcard(_import);
|
||||
|
||||
// Each of these augment the Handlebars object. No need to setup here.
|
||||
// (This is done to easily share code between commonjs and browse envs)
|
||||
|
||||
var _SafeString = __webpack_require__(2);
|
||||
|
||||
var _SafeString2 = _interopRequireWildcard(_SafeString);
|
||||
|
||||
var _Exception = __webpack_require__(3);
|
||||
|
||||
var _Exception2 = _interopRequireWildcard(_Exception);
|
||||
|
||||
var _import2 = __webpack_require__(4);
|
||||
|
||||
var Utils = _interopRequireWildcard(_import2);
|
||||
|
||||
var _import3 = __webpack_require__(5);
|
||||
|
||||
var runtime = _interopRequireWildcard(_import3);
|
||||
|
||||
var _noConflict = __webpack_require__(6);
|
||||
|
||||
var _noConflict2 = _interopRequireWildcard(_noConflict);
|
||||
|
||||
// For compatibility and usage outside of module systems, make the Handlebars object a namespace
|
||||
function create() {
|
||||
var hb = new base.HandlebarsEnvironment();
|
||||
|
||||
Utils.extend(hb, base);
|
||||
hb.SafeString = _SafeString2['default'];
|
||||
hb.Exception = _Exception2['default'];
|
||||
hb.Utils = Utils;
|
||||
hb.escapeExpression = Utils.escapeExpression;
|
||||
|
||||
hb.VM = runtime;
|
||||
hb.template = function (spec) {
|
||||
return runtime.template(spec, hb);
|
||||
};
|
||||
|
||||
return hb;
|
||||
}
|
||||
|
||||
var inst = create();
|
||||
inst.create = create;
|
||||
|
||||
_noConflict2['default'](inst);
|
||||
|
||||
inst['default'] = inst;
|
||||
|
||||
exports['default'] = inst;
|
||||
module.exports = exports['default'];
|
||||
|
||||
/***/ },
|
||||
/* 1 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var _interopRequireWildcard = __webpack_require__(7)['default'];
|
||||
|
||||
exports.__esModule = true;
|
||||
exports.HandlebarsEnvironment = HandlebarsEnvironment;
|
||||
exports.createFrame = createFrame;
|
||||
|
||||
var _import = __webpack_require__(4);
|
||||
|
||||
var Utils = _interopRequireWildcard(_import);
|
||||
|
||||
var _Exception = __webpack_require__(3);
|
||||
|
||||
var _Exception2 = _interopRequireWildcard(_Exception);
|
||||
|
||||
var VERSION = '3.0.1';
|
||||
exports.VERSION = VERSION;
|
||||
var COMPILER_REVISION = 6;
|
||||
|
||||
exports.COMPILER_REVISION = COMPILER_REVISION;
|
||||
var REVISION_CHANGES = {
|
||||
1: '<= 1.0.rc.2', // 1.0.rc.2 is actually rev2 but doesn't report it
|
||||
2: '== 1.0.0-rc.3',
|
||||
3: '== 1.0.0-rc.4',
|
||||
4: '== 1.x.x',
|
||||
5: '== 2.0.0-alpha.x',
|
||||
6: '>= 2.0.0-beta.1'
|
||||
};
|
||||
|
||||
exports.REVISION_CHANGES = REVISION_CHANGES;
|
||||
var isArray = Utils.isArray,
|
||||
isFunction = Utils.isFunction,
|
||||
toString = Utils.toString,
|
||||
objectType = '[object Object]';
|
||||
|
||||
function HandlebarsEnvironment(helpers, partials) {
|
||||
this.helpers = helpers || {};
|
||||
this.partials = partials || {};
|
||||
|
||||
registerDefaultHelpers(this);
|
||||
}
|
||||
|
||||
HandlebarsEnvironment.prototype = {
|
||||
constructor: HandlebarsEnvironment,
|
||||
|
||||
logger: logger,
|
||||
log: log,
|
||||
|
||||
registerHelper: function registerHelper(name, fn) {
|
||||
if (toString.call(name) === objectType) {
|
||||
if (fn) {
|
||||
throw new _Exception2['default']('Arg not supported with multiple helpers');
|
||||
}
|
||||
Utils.extend(this.helpers, name);
|
||||
} else {
|
||||
this.helpers[name] = fn;
|
||||
}
|
||||
},
|
||||
unregisterHelper: function unregisterHelper(name) {
|
||||
delete this.helpers[name];
|
||||
},
|
||||
|
||||
registerPartial: function registerPartial(name, partial) {
|
||||
if (toString.call(name) === objectType) {
|
||||
Utils.extend(this.partials, name);
|
||||
} else {
|
||||
if (typeof partial === 'undefined') {
|
||||
throw new _Exception2['default']('Attempting to register a partial as undefined');
|
||||
}
|
||||
this.partials[name] = partial;
|
||||
}
|
||||
},
|
||||
unregisterPartial: function unregisterPartial(name) {
|
||||
delete this.partials[name];
|
||||
}
|
||||
};
|
||||
|
||||
function registerDefaultHelpers(instance) {
|
||||
instance.registerHelper('helperMissing', function () {
|
||||
if (arguments.length === 1) {
|
||||
// A missing field in a {{foo}} constuct.
|
||||
return undefined;
|
||||
} else {
|
||||
// Someone is actually trying to call something, blow up.
|
||||
throw new _Exception2['default']('Missing helper: "' + arguments[arguments.length - 1].name + '"');
|
||||
}
|
||||
});
|
||||
|
||||
instance.registerHelper('blockHelperMissing', function (context, options) {
|
||||
var inverse = options.inverse,
|
||||
fn = options.fn;
|
||||
|
||||
if (context === true) {
|
||||
return fn(this);
|
||||
} else if (context === false || context == null) {
|
||||
return inverse(this);
|
||||
} else if (isArray(context)) {
|
||||
if (context.length > 0) {
|
||||
if (options.ids) {
|
||||
options.ids = [options.name];
|
||||
}
|
||||
|
||||
return instance.helpers.each(context, options);
|
||||
} else {
|
||||
return inverse(this);
|
||||
}
|
||||
} else {
|
||||
if (options.data && options.ids) {
|
||||
var data = createFrame(options.data);
|
||||
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.name);
|
||||
options = { data: data };
|
||||
}
|
||||
|
||||
return fn(context, options);
|
||||
}
|
||||
});
|
||||
|
||||
instance.registerHelper('each', function (context, options) {
|
||||
if (!options) {
|
||||
throw new _Exception2['default']('Must pass iterator to #each');
|
||||
}
|
||||
|
||||
var fn = options.fn,
|
||||
inverse = options.inverse,
|
||||
i = 0,
|
||||
ret = '',
|
||||
data = undefined,
|
||||
contextPath = undefined;
|
||||
|
||||
if (options.data && options.ids) {
|
||||
contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]) + '.';
|
||||
}
|
||||
|
||||
if (isFunction(context)) {
|
||||
context = context.call(this);
|
||||
}
|
||||
|
||||
if (options.data) {
|
||||
data = createFrame(options.data);
|
||||
}
|
||||
|
||||
function execIteration(field, index, last) {
|
||||
if (data) {
|
||||
data.key = field;
|
||||
data.index = index;
|
||||
data.first = index === 0;
|
||||
data.last = !!last;
|
||||
|
||||
if (contextPath) {
|
||||
data.contextPath = contextPath + field;
|
||||
}
|
||||
}
|
||||
|
||||
ret = ret + fn(context[field], {
|
||||
data: data,
|
||||
blockParams: Utils.blockParams([context[field], field], [contextPath + field, null])
|
||||
});
|
||||
}
|
||||
|
||||
if (context && typeof context === 'object') {
|
||||
if (isArray(context)) {
|
||||
for (var j = context.length; i < j; i++) {
|
||||
execIteration(i, i, i === context.length - 1);
|
||||
}
|
||||
} else {
|
||||
var priorKey = undefined;
|
||||
|
||||
for (var key in context) {
|
||||
if (context.hasOwnProperty(key)) {
|
||||
// We're running the iterations one step out of sync so we can detect
|
||||
// the last iteration without have to scan the object twice and create
|
||||
// an itermediate keys array.
|
||||
if (priorKey) {
|
||||
execIteration(priorKey, i - 1);
|
||||
}
|
||||
priorKey = key;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (priorKey) {
|
||||
execIteration(priorKey, i - 1, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (i === 0) {
|
||||
ret = inverse(this);
|
||||
}
|
||||
|
||||
return ret;
|
||||
});
|
||||
|
||||
instance.registerHelper('if', function (conditional, options) {
|
||||
if (isFunction(conditional)) {
|
||||
conditional = conditional.call(this);
|
||||
}
|
||||
|
||||
// Default behavior is to render the positive path if the value is truthy and not empty.
|
||||
// The `includeZero` option may be set to treat the condtional as purely not empty based on the
|
||||
// behavior of isEmpty. Effectively this determines if 0 is handled by the positive path or negative.
|
||||
if (!options.hash.includeZero && !conditional || Utils.isEmpty(conditional)) {
|
||||
return options.inverse(this);
|
||||
} else {
|
||||
return options.fn(this);
|
||||
}
|
||||
});
|
||||
|
||||
instance.registerHelper('unless', function (conditional, options) {
|
||||
return instance.helpers['if'].call(this, conditional, { fn: options.inverse, inverse: options.fn, hash: options.hash });
|
||||
});
|
||||
|
||||
instance.registerHelper('with', function (context, options) {
|
||||
if (isFunction(context)) {
|
||||
context = context.call(this);
|
||||
}
|
||||
|
||||
var fn = options.fn;
|
||||
|
||||
if (!Utils.isEmpty(context)) {
|
||||
if (options.data && options.ids) {
|
||||
var data = createFrame(options.data);
|
||||
data.contextPath = Utils.appendContextPath(options.data.contextPath, options.ids[0]);
|
||||
options = { data: data };
|
||||
}
|
||||
|
||||
return fn(context, options);
|
||||
} else {
|
||||
return options.inverse(this);
|
||||
}
|
||||
});
|
||||
|
||||
instance.registerHelper('log', function (message, options) {
|
||||
var level = options.data && options.data.level != null ? parseInt(options.data.level, 10) : 1;
|
||||
instance.log(level, message);
|
||||
});
|
||||
|
||||
instance.registerHelper('lookup', function (obj, field) {
|
||||
return obj && obj[field];
|
||||
});
|
||||
}
|
||||
|
||||
var logger = {
|
||||
methodMap: { 0: 'debug', 1: 'info', 2: 'warn', 3: 'error' },
|
||||
|
||||
// State enum
|
||||
DEBUG: 0,
|
||||
INFO: 1,
|
||||
WARN: 2,
|
||||
ERROR: 3,
|
||||
level: 1,
|
||||
|
||||
// Can be overridden in the host environment
|
||||
log: function log(level, message) {
|
||||
if (typeof console !== 'undefined' && logger.level <= level) {
|
||||
var method = logger.methodMap[level];
|
||||
(console[method] || console.log).call(console, message); // eslint-disable-line no-console
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
exports.logger = logger;
|
||||
var log = logger.log;
|
||||
|
||||
exports.log = log;
|
||||
|
||||
function createFrame(object) {
|
||||
var frame = Utils.extend({}, object);
|
||||
frame._parent = object;
|
||||
return frame;
|
||||
}
|
||||
|
||||
/* [args, ]options */
|
||||
|
||||
/***/ },
|
||||
/* 2 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.__esModule = true;
|
||||
// Build out our basic SafeString type
|
||||
function SafeString(string) {
|
||||
this.string = string;
|
||||
}
|
||||
|
||||
SafeString.prototype.toString = SafeString.prototype.toHTML = function () {
|
||||
return '' + this.string;
|
||||
};
|
||||
|
||||
exports['default'] = SafeString;
|
||||
module.exports = exports['default'];
|
||||
|
||||
/***/ },
|
||||
/* 3 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.__esModule = true;
|
||||
|
||||
var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack'];
|
||||
|
||||
function Exception(message, node) {
|
||||
var loc = node && node.loc,
|
||||
line = undefined,
|
||||
column = undefined;
|
||||
if (loc) {
|
||||
line = loc.start.line;
|
||||
column = loc.start.column;
|
||||
|
||||
message += ' - ' + line + ':' + column;
|
||||
}
|
||||
|
||||
var tmp = Error.prototype.constructor.call(this, message);
|
||||
|
||||
// Unfortunately errors are not enumerable in Chrome (at least), so `for prop in tmp` doesn't work.
|
||||
for (var idx = 0; idx < errorProps.length; idx++) {
|
||||
this[errorProps[idx]] = tmp[errorProps[idx]];
|
||||
}
|
||||
|
||||
if (Error.captureStackTrace) {
|
||||
Error.captureStackTrace(this, Exception);
|
||||
}
|
||||
|
||||
if (loc) {
|
||||
this.lineNumber = line;
|
||||
this.column = column;
|
||||
}
|
||||
}
|
||||
|
||||
Exception.prototype = new Error();
|
||||
|
||||
exports['default'] = Exception;
|
||||
module.exports = exports['default'];
|
||||
|
||||
/***/ },
|
||||
/* 4 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
exports.__esModule = true;
|
||||
exports.extend = extend;
|
||||
|
||||
// Older IE versions do not directly support indexOf so we must implement our own, sadly.
|
||||
exports.indexOf = indexOf;
|
||||
exports.escapeExpression = escapeExpression;
|
||||
exports.isEmpty = isEmpty;
|
||||
exports.blockParams = blockParams;
|
||||
exports.appendContextPath = appendContextPath;
|
||||
var escape = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': ''',
|
||||
'`': '`'
|
||||
};
|
||||
|
||||
var badChars = /[&<>"'`]/g,
|
||||
possible = /[&<>"'`]/;
|
||||
|
||||
function escapeChar(chr) {
|
||||
return escape[chr];
|
||||
}
|
||||
|
||||
function extend(obj /* , ...source */) {
|
||||
for (var i = 1; i < arguments.length; i++) {
|
||||
for (var key in arguments[i]) {
|
||||
if (Object.prototype.hasOwnProperty.call(arguments[i], key)) {
|
||||
obj[key] = arguments[i][key];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
var toString = Object.prototype.toString;
|
||||
|
||||
exports.toString = toString;
|
||||
// Sourced from lodash
|
||||
// https://github.com/bestiejs/lodash/blob/master/LICENSE.txt
|
||||
/*eslint-disable func-style, no-var */
|
||||
var isFunction = function isFunction(value) {
|
||||
return typeof value === 'function';
|
||||
};
|
||||
// fallback for older versions of Chrome and Safari
|
||||
/* istanbul ignore next */
|
||||
if (isFunction(/x/)) {
|
||||
exports.isFunction = isFunction = function (value) {
|
||||
return typeof value === 'function' && toString.call(value) === '[object Function]';
|
||||
};
|
||||
}
|
||||
var isFunction;
|
||||
exports.isFunction = isFunction;
|
||||
/*eslint-enable func-style, no-var */
|
||||
|
||||
/* istanbul ignore next */
|
||||
var isArray = Array.isArray || function (value) {
|
||||
return value && typeof value === 'object' ? toString.call(value) === '[object Array]' : false;
|
||||
};exports.isArray = isArray;
|
||||
|
||||
function indexOf(array, value) {
|
||||
for (var i = 0, len = array.length; i < len; i++) {
|
||||
if (array[i] === value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
function escapeExpression(string) {
|
||||
if (typeof string !== 'string') {
|
||||
// don't escape SafeStrings, since they're already safe
|
||||
if (string && string.toHTML) {
|
||||
return string.toHTML();
|
||||
} else if (string == null) {
|
||||
return '';
|
||||
} else if (!string) {
|
||||
return string + '';
|
||||
}
|
||||
|
||||
// Force a string conversion as this will be done by the append regardless and
|
||||
// the regex test will do this transparently behind the scenes, causing issues if
|
||||
// an object's to string has escaped characters in it.
|
||||
string = '' + string;
|
||||
}
|
||||
|
||||
if (!possible.test(string)) {
|
||||
return string;
|
||||
}
|
||||
return string.replace(badChars, escapeChar);
|
||||
}
|
||||
|
||||
function isEmpty(value) {
|
||||
if (!value && value !== 0) {
|
||||
return true;
|
||||
} else if (isArray(value) && value.length === 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function blockParams(params, ids) {
|
||||
params.path = ids;
|
||||
return params;
|
||||
}
|
||||
|
||||
function appendContextPath(contextPath, id) {
|
||||
return (contextPath ? contextPath + '.' : '') + id;
|
||||
}
|
||||
|
||||
/***/ },
|
||||
/* 5 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
'use strict';
|
||||
|
||||
var _interopRequireWildcard = __webpack_require__(7)['default'];
|
||||
|
||||
exports.__esModule = true;
|
||||
exports.checkRevision = checkRevision;
|
||||
|
||||
// TODO: Remove this line and break up compilePartial
|
||||
|
||||
exports.template = template;
|
||||
exports.wrapProgram = wrapProgram;
|
||||
exports.resolvePartial = resolvePartial;
|
||||
exports.invokePartial = invokePartial;
|
||||
exports.noop = noop;
|
||||
|
||||
var _import = __webpack_require__(4);
|
||||
|
||||
var Utils = _interopRequireWildcard(_import);
|
||||
|
||||
var _Exception = __webpack_require__(3);
|
||||
|
||||
var _Exception2 = _interopRequireWildcard(_Exception);
|
||||
|
||||
var _COMPILER_REVISION$REVISION_CHANGES$createFrame = __webpack_require__(1);
|
||||
|
||||
function checkRevision(compilerInfo) {
|
||||
var compilerRevision = compilerInfo && compilerInfo[0] || 1,
|
||||
currentRevision = _COMPILER_REVISION$REVISION_CHANGES$createFrame.COMPILER_REVISION;
|
||||
|
||||
if (compilerRevision !== currentRevision) {
|
||||
if (compilerRevision < currentRevision) {
|
||||
var runtimeVersions = _COMPILER_REVISION$REVISION_CHANGES$createFrame.REVISION_CHANGES[currentRevision],
|
||||
compilerVersions = _COMPILER_REVISION$REVISION_CHANGES$createFrame.REVISION_CHANGES[compilerRevision];
|
||||
throw new _Exception2['default']('Template was precompiled with an older version of Handlebars than the current runtime. ' + 'Please update your precompiler to a newer version (' + runtimeVersions + ') or downgrade your runtime to an older version (' + compilerVersions + ').');
|
||||
} else {
|
||||
// Use the embedded version info since the runtime doesn't know about this revision yet
|
||||
throw new _Exception2['default']('Template was precompiled with a newer version of Handlebars than the current runtime. ' + 'Please update your runtime to a newer version (' + compilerInfo[1] + ').');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function template(templateSpec, env) {
|
||||
/* istanbul ignore next */
|
||||
if (!env) {
|
||||
throw new _Exception2['default']('No environment passed to template');
|
||||
}
|
||||
if (!templateSpec || !templateSpec.main) {
|
||||
throw new _Exception2['default']('Unknown template object: ' + typeof templateSpec);
|
||||
}
|
||||
|
||||
// Note: Using env.VM references rather than local var references throughout this section to allow
|
||||
// for external users to override these as psuedo-supported APIs.
|
||||
env.VM.checkRevision(templateSpec.compiler);
|
||||
|
||||
function invokePartialWrapper(partial, context, options) {
|
||||
if (options.hash) {
|
||||
context = Utils.extend({}, context, options.hash);
|
||||
}
|
||||
|
||||
partial = env.VM.resolvePartial.call(this, partial, context, options);
|
||||
var result = env.VM.invokePartial.call(this, partial, context, options);
|
||||
|
||||
if (result == null && env.compile) {
|
||||
options.partials[options.name] = env.compile(partial, templateSpec.compilerOptions, env);
|
||||
result = options.partials[options.name](context, options);
|
||||
}
|
||||
if (result != null) {
|
||||
if (options.indent) {
|
||||
var lines = result.split('\n');
|
||||
for (var i = 0, l = lines.length; i < l; i++) {
|
||||
if (!lines[i] && i + 1 === l) {
|
||||
break;
|
||||
}
|
||||
|
||||
lines[i] = options.indent + lines[i];
|
||||
}
|
||||
result = lines.join('\n');
|
||||
}
|
||||
return result;
|
||||
} else {
|
||||
throw new _Exception2['default']('The partial ' + options.name + ' could not be compiled when running in runtime-only mode');
|
||||
}
|
||||
}
|
||||
|
||||
// Just add water
|
||||
var container = {
|
||||
strict: function strict(obj, name) {
|
||||
if (!(name in obj)) {
|
||||
throw new _Exception2['default']('"' + name + '" not defined in ' + obj);
|
||||
}
|
||||
return obj[name];
|
||||
},
|
||||
lookup: function lookup(depths, name) {
|
||||
var len = depths.length;
|
||||
for (var i = 0; i < len; i++) {
|
||||
if (depths[i] && depths[i][name] != null) {
|
||||
return depths[i][name];
|
||||
}
|
||||
}
|
||||
},
|
||||
lambda: function lambda(current, context) {
|
||||
return typeof current === 'function' ? current.call(context) : current;
|
||||
},
|
||||
|
||||
escapeExpression: Utils.escapeExpression,
|
||||
invokePartial: invokePartialWrapper,
|
||||
|
||||
fn: function fn(i) {
|
||||
return templateSpec[i];
|
||||
},
|
||||
|
||||
programs: [],
|
||||
program: function program(i, data, declaredBlockParams, blockParams, depths) {
|
||||
var programWrapper = this.programs[i],
|
||||
fn = this.fn(i);
|
||||
if (data || depths || blockParams || declaredBlockParams) {
|
||||
programWrapper = wrapProgram(this, i, fn, data, declaredBlockParams, blockParams, depths);
|
||||
} else if (!programWrapper) {
|
||||
programWrapper = this.programs[i] = wrapProgram(this, i, fn);
|
||||
}
|
||||
return programWrapper;
|
||||
},
|
||||
|
||||
data: function data(value, depth) {
|
||||
while (value && depth--) {
|
||||
value = value._parent;
|
||||
}
|
||||
return value;
|
||||
},
|
||||
merge: function merge(param, common) {
|
||||
var obj = param || common;
|
||||
|
||||
if (param && common && param !== common) {
|
||||
obj = Utils.extend({}, common, param);
|
||||
}
|
||||
|
||||
return obj;
|
||||
},
|
||||
|
||||
noop: env.VM.noop,
|
||||
compilerInfo: templateSpec.compiler
|
||||
};
|
||||
|
||||
function ret(context) {
|
||||
var options = arguments[1] === undefined ? {} : arguments[1];
|
||||
|
||||
var data = options.data;
|
||||
|
||||
ret._setup(options);
|
||||
if (!options.partial && templateSpec.useData) {
|
||||
data = initData(context, data);
|
||||
}
|
||||
var depths = undefined,
|
||||
blockParams = templateSpec.useBlockParams ? [] : undefined;
|
||||
if (templateSpec.useDepths) {
|
||||
depths = options.depths ? [context].concat(options.depths) : [context];
|
||||
}
|
||||
|
||||
return templateSpec.main.call(container, context, container.helpers, container.partials, data, blockParams, depths);
|
||||
}
|
||||
ret.isTop = true;
|
||||
|
||||
ret._setup = function (options) {
|
||||
if (!options.partial) {
|
||||
container.helpers = container.merge(options.helpers, env.helpers);
|
||||
|
||||
if (templateSpec.usePartial) {
|
||||
container.partials = container.merge(options.partials, env.partials);
|
||||
}
|
||||
} else {
|
||||
container.helpers = options.helpers;
|
||||
container.partials = options.partials;
|
||||
}
|
||||
};
|
||||
|
||||
ret._child = function (i, data, blockParams, depths) {
|
||||
if (templateSpec.useBlockParams && !blockParams) {
|
||||
throw new _Exception2['default']('must pass block params');
|
||||
}
|
||||
if (templateSpec.useDepths && !depths) {
|
||||
throw new _Exception2['default']('must pass parent depths');
|
||||
}
|
||||
|
||||
return wrapProgram(container, i, templateSpec[i], data, 0, blockParams, depths);
|
||||
};
|
||||
return ret;
|
||||
}
|
||||
|
||||
function wrapProgram(container, i, fn, data, declaredBlockParams, blockParams, depths) {
|
||||
function prog(context) {
|
||||
var options = arguments[1] === undefined ? {} : arguments[1];
|
||||
|
||||
return fn.call(container, context, container.helpers, container.partials, options.data || data, blockParams && [options.blockParams].concat(blockParams), depths && [context].concat(depths));
|
||||
}
|
||||
prog.program = i;
|
||||
prog.depth = depths ? depths.length : 0;
|
||||
prog.blockParams = declaredBlockParams || 0;
|
||||
return prog;
|
||||
}
|
||||
|
||||
function resolvePartial(partial, context, options) {
|
||||
if (!partial) {
|
||||
partial = options.partials[options.name];
|
||||
} else if (!partial.call && !options.name) {
|
||||
// This is a dynamic partial that returned a string
|
||||
options.name = partial;
|
||||
partial = options.partials[partial];
|
||||
}
|
||||
return partial;
|
||||
}
|
||||
|
||||
function invokePartial(partial, context, options) {
|
||||
options.partial = true;
|
||||
|
||||
if (partial === undefined) {
|
||||
throw new _Exception2['default']('The partial ' + options.name + ' could not be found');
|
||||
} else if (partial instanceof Function) {
|
||||
return partial(context, options);
|
||||
}
|
||||
}
|
||||
|
||||
function noop() {
|
||||
return '';
|
||||
}
|
||||
|
||||
function initData(context, data) {
|
||||
if (!data || !('root' in data)) {
|
||||
data = data ? _COMPILER_REVISION$REVISION_CHANGES$createFrame.createFrame(data) : {};
|
||||
data.root = context;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/***/ },
|
||||
/* 6 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
/* WEBPACK VAR INJECTION */(function(global) {'use strict';
|
||||
|
||||
exports.__esModule = true;
|
||||
/*global window */
|
||||
|
||||
exports['default'] = function (Handlebars) {
|
||||
/* istanbul ignore next */
|
||||
var root = typeof global !== 'undefined' ? global : window,
|
||||
$Handlebars = root.Handlebars;
|
||||
/* istanbul ignore next */
|
||||
Handlebars.noConflict = function () {
|
||||
if (root.Handlebars === Handlebars) {
|
||||
root.Handlebars = $Handlebars;
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
module.exports = exports['default'];
|
||||
/* WEBPACK VAR INJECTION */}.call(exports, (function() { return this; }())))
|
||||
|
||||
/***/ },
|
||||
/* 7 */
|
||||
/***/ function(module, exports, __webpack_require__) {
|
||||
|
||||
"use strict";
|
||||
|
||||
exports["default"] = function (obj) {
|
||||
return obj && obj.__esModule ? obj : {
|
||||
"default": obj
|
||||
};
|
||||
};
|
||||
|
||||
exports.__esModule = true;
|
||||
|
||||
/***/ }
|
||||
/******/ ])
|
||||
});
|
||||
;
|
||||
@@ -4,6 +4,9 @@ define([
|
||||
'utils/add-logging',
|
||||
'utils/localization'
|
||||
], function( _, Backbone, addLogging, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
/** @class Mixin to add logging capabilities to an object.
|
||||
* Designed to allow switching an objects log output off/on at one central
|
||||
|
||||
@@ -4,7 +4,8 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DC_LI, DATASET_LI_EDIT, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
|
||||
'use strict';
|
||||
//==============================================================================
|
||||
var DCListItemView = DC_LI.DCListItemView;
|
||||
/** @class Edit view for DatasetCollection.
|
||||
|
||||
@@ -4,7 +4,8 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_ITEM, DATASET_LI, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
|
||||
'use strict';
|
||||
//==============================================================================
|
||||
var FoldoutListItemView = LIST_ITEM.FoldoutListItemView,
|
||||
ListItemView = LIST_ITEM.ListItemView;
|
||||
@@ -33,11 +34,11 @@ var DCListItemView = FoldoutListItemView.extend(
|
||||
_setUpListeners : function(){
|
||||
FoldoutListItemView.prototype._setUpListeners.call( this );
|
||||
// re-rendering on deletion
|
||||
this.model.on( 'change', function( model, options ){
|
||||
this.listenTo( this.model, 'change', function( model, options ){
|
||||
if( _.isEqual( _.keys( model.changed ), [ 'deleted' ] ) ){
|
||||
this.render();
|
||||
}
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
// ......................................................................... rendering
|
||||
|
||||
@@ -4,6 +4,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( DATASET_MODEL, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'collections';
|
||||
//==============================================================================
|
||||
/*
|
||||
|
||||
@@ -6,6 +6,8 @@ define([
|
||||
"utils/localization",
|
||||
"ui/editable-text",
|
||||
], function( DC_VIEW, DC_MODEL, DC_EDIT, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( LIST_VIEW, DC_MODEL, DC_LI, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'collections';
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
@@ -83,12 +85,14 @@ var CollectionView = _super.extend(
|
||||
_super.prototype._setUpItemViewListeners.call( panel, view );
|
||||
|
||||
// use pub-sub to: handle drilldown expansion and collapse
|
||||
view.on( 'expanded:drilldown', function( v, drilldown ){
|
||||
this._expandDrilldownPanel( drilldown );
|
||||
}, this );
|
||||
view.on( 'collapsed:drilldown', function( v, drilldown ){
|
||||
this._collapseDrilldownPanel( drilldown );
|
||||
}, this );
|
||||
panel.listenTo( view, {
|
||||
'expanded:drilldown': function( v, drilldown ){
|
||||
this._expandDrilldownPanel( drilldown );
|
||||
},
|
||||
'collapsed:drilldown': function( v, drilldown ){
|
||||
this._collapseDrilldownPanel( drilldown );
|
||||
}
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ define([
|
||||
"ui/hoverhighlight"
|
||||
], function( HDCA, STATES, BASE_MVC, UI_MODAL, naturalSort, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'collections';
|
||||
/*==============================================================================
|
||||
TODO:
|
||||
|
||||
@@ -7,6 +7,8 @@ define([
|
||||
"ui/hoverhighlight"
|
||||
], function( levenshteinDistance, naturalSort, LIST_COLLECTION_CREATOR, baseMVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'collections';
|
||||
/* ============================================================================
|
||||
TODO:
|
||||
|
||||
@@ -5,6 +5,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( LIST_CREATOR, HDCA, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'collections';
|
||||
/*==============================================================================
|
||||
TODO:
|
||||
|
||||
@@ -5,6 +5,7 @@ define([
|
||||
'mvc/base-mvc',
|
||||
'utils/localization'
|
||||
], function( DATASET, DATASET_LIST, MODAL, BASE_MVC, _l ){
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'dataset';
|
||||
/* ============================================================================
|
||||
|
||||
@@ -7,6 +7,8 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( STATES, DATASET_LI, TAGS, ANNOTATIONS, faIconButton, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
//==============================================================================
|
||||
var _super = DATASET_LI.DatasetListItemView;
|
||||
/** @class Editing view for DatasetAssociation.
|
||||
|
||||
@@ -5,7 +5,7 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_ITEM, STATES, faIconButton, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'dataset';
|
||||
/*==============================================================================
|
||||
@@ -44,7 +44,7 @@ var DatasetListItemView = _super.extend(
|
||||
_super.prototype._setUpListeners.call( this );
|
||||
|
||||
// re-rendering on any model changes
|
||||
this.model.on( 'change', function( model, options ){
|
||||
this.listenTo( this.model, 'change', function( model, options ){
|
||||
// if the model moved into the ready state and is expanded without details, fetch those details now
|
||||
if( this.model.changedAttributes().state && this.model.inReadyState()
|
||||
&& this.expanded && !this.model.hasDetails() ){
|
||||
@@ -54,7 +54,7 @@ var DatasetListItemView = _super.extend(
|
||||
} else {
|
||||
this.render();
|
||||
}
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
// ......................................................................... expandable
|
||||
|
||||
@@ -4,6 +4,7 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( LIST_VIEW, DATASET_LI, BASE_MVC, _l ){
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'dataset';
|
||||
/* =============================================================================
|
||||
|
||||
@@ -3,6 +3,7 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( STATES, BASE_MVC, _l ){
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'dataset';
|
||||
//==============================================================================
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
define([
|
||||
], function(){
|
||||
|
||||
'use strict';
|
||||
//==============================================================================
|
||||
/** Map of possible HDA/collection/job states to their string equivalents.
|
||||
* A port of galaxy.model.Dataset.states.
|
||||
|
||||
@@ -31,14 +31,14 @@ define([ 'utils/utils' ], function( Utils ) {
|
||||
var dict = {};
|
||||
this._iterate( this.app.section.$el, dict );
|
||||
|
||||
// add to result dictionary
|
||||
// add to result dictionary, label elements
|
||||
var result_dict = {};
|
||||
this.flat_dict = {};
|
||||
function add( flat_id, input_id, input_value ) {
|
||||
self.flat_dict[ flat_id ] = input_id;
|
||||
result_dict[ flat_id ] = input_value;
|
||||
};
|
||||
|
||||
self.app.element_list[ input_id ] && self.app.element_list[ input_id ].$el.attr( 'tour_id', flat_id );
|
||||
}
|
||||
// converter between raw dictionary and job dictionary
|
||||
function convert( identifier, head ) {
|
||||
for ( var index in head ) {
|
||||
@@ -73,7 +73,7 @@ define([ 'utils/utils' ], function( Utils ) {
|
||||
break;
|
||||
case 'conditional':
|
||||
var value = self.app.field_list[ input.id ].value();
|
||||
add ( flat_id + '|' + input.test_param.name, input.id, value );
|
||||
add( flat_id + '|' + input.test_param.name, input.id, value );
|
||||
var selectedCase = matchCase( input, value );
|
||||
if ( selectedCase != -1 ) {
|
||||
convert( flat_id, head[ input.id + '-section-' + selectedCase ] );
|
||||
@@ -90,10 +90,10 @@ define([ 'utils/utils' ], function( Utils ) {
|
||||
if ( field.collapsed && input.collapsible_value ) {
|
||||
value = input.collapsible_value;
|
||||
}
|
||||
add ( flat_id, input.id, value );
|
||||
add( flat_id, input.id, value );
|
||||
if ( input.payload ) {
|
||||
for ( var p_id in input.payload ) {
|
||||
add ( p_id, input.id, input.payload[ p_id ] );
|
||||
add( p_id, input.id, input.payload[ p_id ] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ define([], function() {
|
||||
/** Main Template
|
||||
*/
|
||||
_template: function(options) {
|
||||
var tmp = '<div class="ui-form-element input-name-' + options.name + '">' +
|
||||
var tmp = '<div class="ui-form-element">' +
|
||||
'<div class="ui-form-error ui-error">' +
|
||||
'<span class="fa fa-arrow-down"/><span class="ui-form-error-text"/>' +
|
||||
'</div>' +
|
||||
|
||||
@@ -179,14 +179,13 @@ define(['utils/utils',
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// create input element
|
||||
var self = this;
|
||||
return new Ui.Input({
|
||||
id : 'field-' + input_def.id,
|
||||
area : input_def.area,
|
||||
onchange : function() {
|
||||
self.app.trigger('change');
|
||||
onchange : function( new_value ) {
|
||||
input_def.onchange ? input_def.onchange( new_value ) : self.app.trigger( 'change' );
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
@@ -5,9 +5,8 @@ define(['utils/utils', 'mvc/ui/ui-table', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc']
|
||||
/** This class creates a ui component which enables the dynamic creation of portlets
|
||||
*/
|
||||
var View = Backbone.View.extend({
|
||||
/** Initialize
|
||||
*/
|
||||
initialize : function(options) {
|
||||
var self = this;
|
||||
this.options = Utils.merge(options, {
|
||||
title : 'Section',
|
||||
empty_text : 'Not available.',
|
||||
@@ -15,13 +14,12 @@ var View = Backbone.View.extend({
|
||||
min : null
|
||||
});
|
||||
this.setElement('<div/>');
|
||||
var self = this;
|
||||
|
||||
// create button
|
||||
this.button_new = new Ui.ButtonIcon({
|
||||
icon : 'fa-plus',
|
||||
title : 'Insert ' + options.title_new,
|
||||
tooltip : 'Add new ' + options.title_new + ' block',
|
||||
title : 'Insert ' + this.options.title_new,
|
||||
tooltip : 'Add new ' + this.options.title_new + ' block',
|
||||
floating: 'clear',
|
||||
onclick : function() {
|
||||
if (options.onnew) {
|
||||
|
||||
@@ -190,7 +190,7 @@ define(['utils/utils', 'mvc/ui/ui-portlet', 'mvc/ui/ui-misc', 'mvc/form/form-sec
|
||||
});
|
||||
|
||||
// append message
|
||||
this.portlet.append(this.message.$el.addClass('ui-margin-top'));
|
||||
this.portlet.append(this.message.$el);
|
||||
|
||||
// append tool section
|
||||
this.portlet.append(this.section.$el);
|
||||
|
||||
@@ -3,7 +3,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( MODAL, _l ){
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
* A dialog/modal that allows copying a user history or 'importing' from user
|
||||
|
||||
@@ -4,6 +4,9 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET_LI_EDIT, HDA_LI, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
var _super = DATASET_LI_EDIT.DatasetListItemEdit;
|
||||
/** @class Editing view for HistoryDatasetAssociation.
|
||||
|
||||
@@ -3,7 +3,9 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET_LI, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
var _super = DATASET_LI.DatasetListItemView;
|
||||
/** @class Read only view for HistoryDatasetAssociation.
|
||||
|
||||
@@ -4,6 +4,9 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( DATASET, HISTORY_CONTENT, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
var _super = DATASET.DatasetAssociation,
|
||||
hcontentMixin = HISTORY_CONTENT.HistoryContentMixin;
|
||||
|
||||
@@ -4,6 +4,9 @@ define([
|
||||
"ui/fa-icon-button",
|
||||
"utils/localization"
|
||||
], function( HDCA_LI, DC_VIEW_EDIT, faIconButton, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
var _super = HDCA_LI.HDCAListItemView;
|
||||
/** @class Editing view for HistoryDatasetCollectionAssociation.
|
||||
|
||||
@@ -5,7 +5,9 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( STATES, DC_LI, DC_VIEW, BASE_MVC, _l ){
|
||||
/* global Backbone */
|
||||
|
||||
'use strict';
|
||||
|
||||
//==============================================================================
|
||||
var _super = DC_LI.DCListItemView;
|
||||
/** @class Read only view for HistoryDatasetCollectionAssociation (a dataset collection inside a history).
|
||||
@@ -22,9 +24,9 @@ var HDCAListItemView = _super.extend(
|
||||
_setUpListeners : function(){
|
||||
_super.prototype._setUpListeners.call( this );
|
||||
|
||||
this.model.on({
|
||||
this.listenTo( this.model, {
|
||||
'change:populated change:visible' : function( model, options ){ this.render(); },
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
/** Override to provide the proper collections panels as the foldout */
|
||||
|
||||
@@ -3,6 +3,9 @@ define([
|
||||
"mvc/history/history-content-model",
|
||||
"utils/localization"
|
||||
], function( DC_MODEL, HISTORY_CONTENT, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
/*==============================================================================
|
||||
|
||||
Models for DatasetCollections contained within a history.
|
||||
|
||||
@@ -4,6 +4,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( STATES, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'history';
|
||||
//==============================================================================
|
||||
/** How the type_id attribute is built for the history's mixed contents collection */
|
||||
|
||||
@@ -6,6 +6,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( HISTORY_CONTENT, HDA_MODEL, HDCA_MODEL, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'history';
|
||||
//==============================================================================
|
||||
/** @class Backbone collection for history content.
|
||||
|
||||
@@ -6,6 +6,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( HISTORY_CONTENTS, UTILS, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'history';
|
||||
//==============================================================================
|
||||
/** @class Model for a Galaxy history resource - both a record of user
|
||||
@@ -78,7 +80,7 @@ var History = Backbone.Model
|
||||
if( this.contents ){
|
||||
this.contents.historyId = newId;
|
||||
}
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
//TODO: see base-mvc
|
||||
@@ -540,7 +542,7 @@ var HistoryCollection = Backbone.Collection
|
||||
this.trigger( 'no-longer-current', oldCurrentId );
|
||||
this.currentHistoryId = history.id;
|
||||
}
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
/** override to allow passing options.order and setting the sort order to one of sortOrders */
|
||||
|
||||
@@ -9,6 +9,8 @@ define([
|
||||
'libs/d3'
|
||||
], function( JobDAG, JOB, JOB_LI, HISTORY_CONTENT, DATASET_LI, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'history';
|
||||
// ============================================================================
|
||||
/*
|
||||
@@ -157,8 +159,8 @@ var HistoryStructureComponent = Backbone.View.extend( BASE_MVC.LoggableMixin ).e
|
||||
|
||||
// create the bbone view for the job (to be positioned later accrd. to the layout) and cache
|
||||
var li = new view.JobItemClass({ model: job, tool: jobData.tool, jobData: jobData });
|
||||
li.on( 'expanding expanded collapsing collapsed', view.renderGraph, view );
|
||||
li.foldout.on( 'view:expanding view:expanded view:collapsing view:collapsed', view.renderGraph, view );
|
||||
view.listenTo( li, 'expanding expanded collapsing collapsed', view.renderGraph );
|
||||
view.listenTo( li.foldout, 'view:expanding view:expanded view:collapsing view:collapsed', view.renderGraph );
|
||||
return li;
|
||||
},
|
||||
|
||||
@@ -169,7 +171,7 @@ var HistoryStructureComponent = Backbone.View.extend( BASE_MVC.LoggableMixin ).e
|
||||
typeId = HISTORY_CONTENT.typeIdStr( content.history_content_type, content.id );
|
||||
content = view.model.contents.get( typeId );
|
||||
var li = new view.ContentItemClass({ model: content });
|
||||
li.on( 'expanding expanded collapsing collapsed', view.renderGraph, view );
|
||||
view.listenTo( li, 'expanding expanded collapsing collapsed', view.renderGraph );
|
||||
return li;
|
||||
},
|
||||
|
||||
|
||||
@@ -5,6 +5,9 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( HISTORY_VIEW, HDA_LI, HDCA_LI, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
|
||||
|
||||
@@ -4,6 +4,9 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( HISTORY_MODEL, HISTORY_VIEW_EDIT, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
/** session storage for history panel preferences (and to maintain state)
|
||||
*/
|
||||
@@ -158,12 +161,12 @@ var CurrentHistoryView = _super.extend(
|
||||
//TODO:?? may not be needed? see history-view-edit, 369
|
||||
// if a hidden item is created (gen. by a workflow), moves thru the updater to the ready state,
|
||||
// then: remove it from the collection if the panel is set to NOT show hidden datasets
|
||||
this.collection.on( 'state:ready', function( model, newState, oldState ){
|
||||
this.listenTo( this.collection, 'state:ready', function( model, newState, oldState ){
|
||||
if( ( !model.get( 'visible' ) )
|
||||
&& ( !this.storage.get( 'show_hidden' ) ) ){
|
||||
this.removeItemView( model );
|
||||
}
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
/** listening for history events */
|
||||
@@ -257,27 +260,28 @@ var CurrentHistoryView = _super.extend(
|
||||
_renderTags : function( $where ){
|
||||
var panel = this;
|
||||
// render tags and show/hide based on preferences
|
||||
_super.prototype._renderTags.call( this, $where );
|
||||
if( this.preferences.get( 'tagsEditorShown' ) ){
|
||||
this.tagsEditor.toggle( true );
|
||||
_super.prototype._renderTags.call( panel, $where );
|
||||
if( panel.preferences.get( 'tagsEditorShown' ) ){
|
||||
panel.tagsEditor.toggle( true );
|
||||
}
|
||||
// store preference when shown or hidden
|
||||
this.tagsEditor.on( 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
|
||||
panel.listenTo( panel.tagsEditor, 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
|
||||
function( tagsEditor ){
|
||||
panel.preferences.set( 'tagsEditorShown', tagsEditor.hidden );
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
|
||||
/** In this override, get and set current panel preferences when editor is used */
|
||||
_renderAnnotation : function( $where ){
|
||||
var panel = this;
|
||||
// render annotation and show/hide based on preferences
|
||||
_super.prototype._renderAnnotation.call( this, $where );
|
||||
if( this.preferences.get( 'annotationEditorShown' ) ){
|
||||
this.annotationEditor.toggle( true );
|
||||
_super.prototype._renderAnnotation.call( panel, $where );
|
||||
if( panel.preferences.get( 'annotationEditorShown' ) ){
|
||||
panel.annotationEditor.toggle( true );
|
||||
}
|
||||
// store preference when shown or hidden
|
||||
this.annotationEditor.on( 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
|
||||
panel.listenTo( panel.annotationEditor, 'hiddenUntilActivated:shown hiddenUntilActivated:hidden',
|
||||
function( annotationEditor ){
|
||||
panel.preferences.set( 'annotationEditorShown', annotationEditor.hidden );
|
||||
}
|
||||
@@ -325,12 +329,12 @@ var CurrentHistoryView = _super.extend(
|
||||
_super.prototype._setUpItemViewListeners.call( panel, view );
|
||||
|
||||
// use pub-sub to: handle drilldown expansion and collapse
|
||||
view.on( 'expanded:drilldown', function( v, drilldown ){
|
||||
panel.listenTo( view, 'expanded:drilldown', function( v, drilldown ){
|
||||
this._expandDrilldownPanel( drilldown );
|
||||
}, this );
|
||||
view.on( 'collapsed:drilldown', function( v, drilldown ){
|
||||
});
|
||||
panel.listenTo( view, 'collapsed:drilldown', function( v, drilldown ){
|
||||
this._collapseDrilldownPanel( drilldown );
|
||||
}, this );
|
||||
});
|
||||
|
||||
// when content is manipulated, make it the current-content
|
||||
// view.on( 'visualize', function( v, ev ){
|
||||
@@ -376,7 +380,7 @@ var CurrentHistoryView = _super.extend(
|
||||
// ........................................................................ external objects/MVC
|
||||
listenToGalaxy : function( galaxy ){
|
||||
// TODO: MEM: questionable reference island / closure practice
|
||||
galaxy.on( 'galaxy_main:load', function( data ){
|
||||
this.listenTo( galaxy, 'galaxy_main:load', function( data ){
|
||||
var pathToMatch = data.fullpath,
|
||||
useToURLRegexMap = {
|
||||
'display' : /datasets\/([a-f0-9]+)\/display/,
|
||||
@@ -401,7 +405,7 @@ var CurrentHistoryView = _super.extend(
|
||||
// need to type mangle to go from web route to history contents
|
||||
hdaId = 'dataset-' + hdaId;
|
||||
this._setCurrentContentById( hdaId );
|
||||
}, this );
|
||||
});
|
||||
},
|
||||
|
||||
//TODO: remove quota meter from panel and remove this
|
||||
|
||||
@@ -30,6 +30,9 @@ define([
|
||||
PopupMenu,
|
||||
_l
|
||||
){
|
||||
|
||||
'use strict';
|
||||
|
||||
/* =============================================================================
|
||||
TODO:
|
||||
|
||||
@@ -90,7 +93,7 @@ var HistoryViewEdit = _super.extend(
|
||||
});
|
||||
panel.on( 'view:attached view:removed', function(){
|
||||
panel._renderCounts();
|
||||
}, panel );
|
||||
});
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ listeners
|
||||
@@ -98,19 +101,21 @@ var HistoryViewEdit = _super.extend(
|
||||
_setUpCollectionListeners : function(){
|
||||
_super.prototype._setUpCollectionListeners.call( this );
|
||||
|
||||
this.collection.on( 'change:deleted', this._handleHdaDeletionChange, this );
|
||||
this.collection.on( 'change:visible', this._handleHdaVisibleChange, this );
|
||||
this.collection.on( 'change:purged', function( model ){
|
||||
// hafta get the new nice-size w/o the purged model
|
||||
this.model.fetch();
|
||||
}, this );
|
||||
this.listenTo( this.collection, {
|
||||
'change:deleted': this._handleHdaDeletionChange,
|
||||
'change:visible': this._handleHdaVisibleChange,
|
||||
'change:purged' : function( model ){
|
||||
// hafta get the new nice-size w/o the purged model
|
||||
this.model.fetch();
|
||||
}
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
/** listening for history and HDA events */
|
||||
_setUpModelListeners : function(){
|
||||
_super.prototype._setUpModelListeners.call( this );
|
||||
this.model.on( 'change:size', this.updateHistoryDiskSize, this );
|
||||
this.listenTo( this.model, 'change:size', this.updateHistoryDiskSize );
|
||||
return this;
|
||||
},
|
||||
|
||||
|
||||
@@ -23,6 +23,8 @@ define([
|
||||
_l
|
||||
){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'history';
|
||||
|
||||
// ============================================================================
|
||||
@@ -377,11 +379,13 @@ var HistoryView = _super.extend(
|
||||
|
||||
//TODO:?? could use 'view:expanded' here?
|
||||
// maintain a list of items whose bodies are expanded
|
||||
view.on( 'expanded', function( v ){
|
||||
panel.storage.addExpanded( v.model );
|
||||
});
|
||||
view.on( 'collapsed', function( v ){
|
||||
panel.storage.removeExpanded( v.model );
|
||||
panel.listenTo( view, {
|
||||
'expanded': function( v ){
|
||||
panel.storage.addExpanded( v.model );
|
||||
},
|
||||
'collapsed': function( v ){
|
||||
panel.storage.removeExpanded( v.model );
|
||||
}
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
@@ -2,6 +2,9 @@ define([
|
||||
'utils/graph',
|
||||
'utils/add-logging'
|
||||
],function( GRAPH, addLogging ){
|
||||
|
||||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
var _super = GRAPH.Graph;
|
||||
/** A Directed acyclic Graph built from a history's job data.
|
||||
|
||||
@@ -8,6 +8,8 @@ define([
|
||||
"ui/search-input"
|
||||
], function( HISTORY_MODEL, HISTORY_VIEW_EDIT, historyCopyDialog, baseMVC, ajaxQueue ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'history';
|
||||
/* ==============================================================================
|
||||
TODO:
|
||||
|
||||
@@ -5,7 +5,8 @@ define([
|
||||
"utils/localization"
|
||||
], function( PopupMenu, historyCopyDialog, BASE_MVC, _l ){
|
||||
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// ============================================================================
|
||||
var menu = [
|
||||
{
|
||||
|
||||
@@ -3,6 +3,8 @@ define([
|
||||
'utils/localization'
|
||||
], function( BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'list';
|
||||
//==============================================================================
|
||||
/** A view which, when first rendered, shows only summary data/attributes, but
|
||||
@@ -475,7 +477,7 @@ var FoldoutListItemView = ListItemView.extend({
|
||||
_expandByDrilldown : function(){
|
||||
var view = this;
|
||||
// attachment and rendering done by listener
|
||||
view.foldout.on( 'close', function(){
|
||||
view.listenTo( view.foldout, 'close', function(){
|
||||
view.trigger( 'collapsed:drilldown', view, view.foldout );
|
||||
});
|
||||
view.trigger( 'expanded:drilldown', view, view.foldout );
|
||||
|
||||
@@ -6,6 +6,8 @@ define([
|
||||
"ui/search-input"
|
||||
], function( LIST_ITEM, LoadingIndicator, BASE_MVC, _l ){
|
||||
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'list';
|
||||
/* ============================================================================
|
||||
TODO:
|
||||
@@ -120,29 +122,30 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
|
||||
|
||||
//TODO: move errorHandler down into list-view from history-view or
|
||||
// pass to global error handler (Galaxy)
|
||||
this.on( 'error', function( model, xhr, options, msg, details ){
|
||||
//this.errorHandler( model, xhr, options, msg, details );
|
||||
console.error( model, xhr, options, msg, details );
|
||||
}, this );
|
||||
|
||||
// show hide the loading indicator
|
||||
this.on( 'loading', function(){
|
||||
this._showLoadingIndicator( 'loading...', 40 );
|
||||
}, this );
|
||||
this.on( 'loading-done', function(){
|
||||
this._hideLoadingIndicator( 40 );
|
||||
}, this );
|
||||
this.on({
|
||||
error: function( model, xhr, options, msg, details ){
|
||||
//this.errorHandler( model, xhr, options, msg, details );
|
||||
console.error( model, xhr, options, msg, details );
|
||||
},
|
||||
// show hide the loading indicator
|
||||
loading: function(){
|
||||
this._showLoadingIndicator( 'loading...', 40 );
|
||||
},
|
||||
'loading-done': function(){
|
||||
this._hideLoadingIndicator( 40 );
|
||||
},
|
||||
});
|
||||
|
||||
// throw the first render up as a diff namespace using once (for outside consumption)
|
||||
this.once( 'rendered', function(){
|
||||
this.trigger( 'rendered:initial', this );
|
||||
}, this );
|
||||
});
|
||||
|
||||
// debugging
|
||||
if( this.logger ){
|
||||
this.on( 'all', function( event ){
|
||||
this.log( this + '', arguments );
|
||||
}, this );
|
||||
});
|
||||
}
|
||||
|
||||
this._setUpCollectionListeners();
|
||||
@@ -156,21 +159,22 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
|
||||
this.collection.off();
|
||||
|
||||
// bubble up error events
|
||||
this.collection.on( 'error', function( model, xhr, options, msg, details ){
|
||||
this.trigger( 'error', model, xhr, options, msg, details );
|
||||
}, this );
|
||||
|
||||
this.collection.on( 'reset', function(){
|
||||
this.renderItems();
|
||||
}, this );
|
||||
this.collection.on( 'add', this.addItemView, this );
|
||||
this.collection.on( 'remove', this.removeItemView, this );
|
||||
this.listenTo( this.collection, {
|
||||
error : function( model, xhr, options, msg, details ){
|
||||
this.trigger( 'error', model, xhr, options, msg, details );
|
||||
},
|
||||
reset : function(){
|
||||
this.renderItems();
|
||||
},
|
||||
add : this.addItemView,
|
||||
remove : this.removeItemView
|
||||
});
|
||||
|
||||
// debugging
|
||||
if( this.logger ){
|
||||
this.collection.on( 'all', function( event ){
|
||||
this.listenTo( this.collection, 'all', function( event ){
|
||||
this.info( this + '(collection)', arguments );
|
||||
}, this );
|
||||
});
|
||||
}
|
||||
return this;
|
||||
},
|
||||
@@ -180,23 +184,25 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
|
||||
this.log( this + '._setUpViewListeners' );
|
||||
|
||||
// shift to select a range
|
||||
this.on( 'view:selected', function( view, ev ){
|
||||
if( ev && ev.shiftKey && this.lastSelected ){
|
||||
var lastSelectedView = this.viewFromModelId( this.lastSelected );
|
||||
if( lastSelectedView ){
|
||||
this.selectRange( view, lastSelectedView );
|
||||
this.on({
|
||||
'view:selected': function( view, ev ){
|
||||
if( ev && ev.shiftKey && this.lastSelected ){
|
||||
var lastSelectedView = this.viewFromModelId( this.lastSelected );
|
||||
if( lastSelectedView ){
|
||||
this.selectRange( view, lastSelectedView );
|
||||
}
|
||||
} else if( ev && ev.altKey && !this.selecting ){
|
||||
this.showSelectors();
|
||||
}
|
||||
} else if( ev && ev.altKey && !this.selecting ){
|
||||
this.showSelectors();
|
||||
}
|
||||
this.selected.push( view.model.id );
|
||||
this.lastSelected = view.model.id;
|
||||
}, this );
|
||||
this.selected.push( view.model.id );
|
||||
this.lastSelected = view.model.id;
|
||||
},
|
||||
|
||||
this.on( 'view:de-selected', function( view, ev ){
|
||||
this.selected = _.without( this.selected, view.model.id );
|
||||
//this.lastSelected = view.model.id;
|
||||
}, this );
|
||||
'view:de-selected': function( view, ev ){
|
||||
this.selected = _.without( this.selected, view.model.id );
|
||||
//this.lastSelected = view.model.id;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ------------------------------------------------------------------------ rendering
|
||||
@@ -426,14 +432,14 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend(/** @lends
|
||||
_setUpItemViewListeners : function( view ){
|
||||
var panel = this;
|
||||
// send all events to the panel, re-namspaceing them with the view prefix
|
||||
view.on( 'all', function(){
|
||||
this.listenTo( view, 'all', function(){
|
||||
var args = Array.prototype.slice.call( arguments, 0 );
|
||||
args[0] = 'view:' + args[0];
|
||||
panel.trigger.apply( panel, args );
|
||||
});
|
||||
|
||||
// drag multiple - hijack ev.setData to add all selected items
|
||||
view.on( 'draggable:dragstart', function( ev, v ){
|
||||
this.listenTo( view, 'draggable:dragstart', function( ev, v ){
|
||||
//TODO: set multiple drag data here
|
||||
var json = {},
|
||||
selected = this.getSelectedModels();
|
||||
@@ -912,7 +918,7 @@ var ModelListPanel = ListPanel.extend({
|
||||
// override
|
||||
this.log( this + '._setUpModelListeners', this.model );
|
||||
// bounce model errors up to the panel
|
||||
this.model.on( 'error', function(){
|
||||
this.listenTo( this.model, 'error', function(){
|
||||
var args = Array.prototype.slice.call( arguments, 0 );
|
||||
//args.unshift( 'model:error' );
|
||||
args.unshift( 'error' );
|
||||
|
||||
@@ -7,9 +7,8 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
|
||||
// create form view
|
||||
var View = ToolFormBase.extend({
|
||||
initialize: function(options) {
|
||||
// link this
|
||||
var self = this;
|
||||
this.hasLabelListeners = false;
|
||||
this.workflow = options.workflow;
|
||||
|
||||
// link with node representation in workflow module
|
||||
this.node = options.node;
|
||||
@@ -40,7 +39,6 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
|
||||
// module information for the tool to update the workflow
|
||||
// state stored on the client with. User needs to save
|
||||
// for this to take effect.
|
||||
self.initializeLabelListener();
|
||||
self.node.update_field_data(data);
|
||||
self.errors(data && data.tool_model)
|
||||
}
|
||||
@@ -73,29 +71,6 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
|
||||
ToolFormBase.prototype.initialize.call(this, options);
|
||||
},
|
||||
|
||||
initializeLabelListener: function() {
|
||||
var self = this;
|
||||
if(this.hasLabelListeners !== false) {
|
||||
return;
|
||||
}
|
||||
this.hasLabelListeners = [];
|
||||
var outputSections = _.where(this.options.inputs, {outputSection: true});
|
||||
var labelInputs = outputSections.map(function(entry) {
|
||||
var sectionId = entry.id;
|
||||
var outputId = entry.outputId;
|
||||
var $section = $("#" + sectionId);
|
||||
var $labelRow = $section.find(".section-row").first();
|
||||
var labelTextInput = $labelRow.find("input")[0];
|
||||
$(labelTextInput).bind('input propertychange', function() {
|
||||
var newLabel = $(labelTextInput).val();
|
||||
var workflow = self.node.app.workflow;
|
||||
workflow.attemptUpdateOutputLabel( self.node, outputId, newLabel );
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
|
||||
/** Builds all sub sections
|
||||
*/
|
||||
_makeSections: function(options){
|
||||
@@ -150,6 +125,7 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
|
||||
*/
|
||||
_makeSection: function(output_id, datatypes){
|
||||
// format datatypes
|
||||
var self = this;
|
||||
var extensions = [];
|
||||
var input_terminal_names = [];
|
||||
|
||||
@@ -188,15 +164,14 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
|
||||
title : 'Configure Output: \'' + output_id + '\'',
|
||||
type : 'section',
|
||||
flat : true,
|
||||
outputSection: true,
|
||||
outputId : output_id,
|
||||
inputs : [{
|
||||
action : 'Label',
|
||||
label : 'Label',
|
||||
type : 'text',
|
||||
value : '',
|
||||
ignore : '',
|
||||
help : 'This will provide a short name to describe the output - this must be unique across workflows.'
|
||||
value : ( output = this.node.getWorkflowOutput( output_id ) ) && output.label || '',
|
||||
help : 'This will provide a short name to describe the output - this must be unique across workflows.',
|
||||
onchange : function( new_value ) {
|
||||
self.workflow.attemptUpdateOutputLabel( self.node, output_id, new_value );
|
||||
}
|
||||
},{
|
||||
action : 'RenameDatasetAction',
|
||||
pja_arg : 'newname',
|
||||
@@ -267,21 +242,13 @@ define(['utils/utils', 'mvc/tool/tool-form-base'],
|
||||
};
|
||||
|
||||
// visit input nodes and enrich by name/value pairs from server data
|
||||
var self = this;
|
||||
function visit (head, head_list) {
|
||||
head_list = head_list || [];
|
||||
head_list.push(head);
|
||||
for (var i in head.inputs) {
|
||||
var input = head.inputs[i];
|
||||
var action = input.action;
|
||||
if ( action == "Label") {
|
||||
var workflowOutput = self.node.getWorkflowOutput(output_id);
|
||||
if ( workflowOutput ) {
|
||||
input.value = workflowOutput['label'] || '';
|
||||
} else{
|
||||
input.value = '';
|
||||
}
|
||||
} else if (action) {
|
||||
if (action) {
|
||||
// construct identifier as expected by backend
|
||||
input.name = 'pja__' + output_id + '__' + input.action;
|
||||
if (input.pja_arg) {
|
||||
|
||||
@@ -6,13 +6,10 @@
|
||||
"libs/underscore",
|
||||
"viz/trackster/util",
|
||||
"mvc/dataset/data",
|
||||
"mvc/tool/tool-form",
|
||||
"templates/tool_form.handlebars",
|
||||
"templates/tool_link.handlebars",
|
||||
"templates/panel_section.handlebars",
|
||||
"templates/tool_search.handlebars",
|
||||
"mvc/tool/tool-form"
|
||||
|
||||
], function(_, util, data, ToolForm, tool_form_template, tool_link_template, panel_section_template, tool_search_template) {
|
||||
], function(_, util, data, ToolForm) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Mixin for tracking model visibility.
|
||||
@@ -353,7 +350,6 @@ var ToolSearch = Backbone.Model.extend({
|
||||
defaults: {
|
||||
search_hint_string: "search tools",
|
||||
min_chars_for_search: 3,
|
||||
spinner_url: "",
|
||||
clear_btn_url: "",
|
||||
search_url: "",
|
||||
visible: true,
|
||||
@@ -496,7 +492,7 @@ var ToolPanel = Backbone.Model.extend({
|
||||
/**
|
||||
* View classes for Galaxy tools and tool panel.
|
||||
*
|
||||
* Views use precompiled Handlebars templates for rendering. Views update as needed
|
||||
* Views use the templates defined below for rendering. Views update as needed
|
||||
* based on (a) model/collection events and (b) user interactions; in this sense,
|
||||
* they are controllers are well and the HTML is the real view in the MVC architecture.
|
||||
*/
|
||||
@@ -523,7 +519,7 @@ var ToolLinkView = BaseView.extend({
|
||||
render: function() {
|
||||
// create element
|
||||
var $link = $('<div/>');
|
||||
$link.append(tool_link_template(this.model.toJSON()));
|
||||
$link.append(templates.tool_link(this.model.toJSON()));
|
||||
|
||||
// open upload dialog for upload tool
|
||||
if (this.model.id === 'upload1') {
|
||||
@@ -576,7 +572,7 @@ var ToolSectionView = BaseView.extend({
|
||||
|
||||
render: function() {
|
||||
// Build using template.
|
||||
this.$el.append( panel_section_template(this.model.toJSON()) );
|
||||
this.$el.append( templates.panel_section(this.model.toJSON()) );
|
||||
|
||||
// Add tools to section.
|
||||
var section_body = this.$el.find(".toolSectionBody");
|
||||
@@ -632,7 +628,7 @@ var ToolSearchView = Backbone.View.extend({
|
||||
},
|
||||
|
||||
render: function() {
|
||||
this.$el.append( tool_search_template(this.model.toJSON()) );
|
||||
this.$el.append( templates.tool_search(this.model.toJSON()) );
|
||||
if (!this.model.is_visible()) {
|
||||
this.$el.hide();
|
||||
}
|
||||
@@ -736,7 +732,7 @@ var ToolFormView = Backbone.View.extend({
|
||||
|
||||
render: function() {
|
||||
this.$el.children().remove();
|
||||
this.$el.append( tool_form_template(this.model.toJSON()) );
|
||||
this.$el.append( templates.tool_form(this.model.toJSON()) );
|
||||
}
|
||||
});
|
||||
|
||||
@@ -785,6 +781,72 @@ var IntegratedToolMenuAndView = Backbone.View.extend({
|
||||
}
|
||||
});
|
||||
|
||||
// TODO: move into relevant views
|
||||
var templates = {
|
||||
// the search bar at the top of the tool panel
|
||||
tool_search : _.template([
|
||||
'<input id="tool-search-query" class="search-query parent-width" name="query" ',
|
||||
'placeholder="<%- search_hint_string %>" autocomplete="off" type="text" />',
|
||||
'<a id="search-clear-btn" title="clear search (esc)"> </a>',
|
||||
//TODO: replace with icon
|
||||
'<span id="search-spinner" class="search-spinner fa fa-spinner fa-spin"></span>',
|
||||
].join('')),
|
||||
|
||||
// the category level container in the tool panel (e.g. 'Get Data', 'Text Manipulation')
|
||||
panel_section : _.template([
|
||||
'<div class="toolSectionTitle" id="title_<%- id %>">',
|
||||
'<a href="javascript:void(0)"><span><%- name %></span></a>',
|
||||
'</div>',
|
||||
'<div id="<%- id %>" class="toolSectionBody" style="display: none;">',
|
||||
'<div class="toolSectionBg"></div>',
|
||||
'<div>'
|
||||
].join('')),
|
||||
|
||||
// a single tool's link in the tool panel; will load the tool form in the center panel
|
||||
tool_link : _.template([
|
||||
'<span class="labels">',
|
||||
'<% _.each( labels, function( label ){ %>',
|
||||
'<span class="label label-default label-<%- label %>">',
|
||||
'<%- label %>',
|
||||
'</span>',
|
||||
'<% }); %>',
|
||||
'</span>',
|
||||
'<a class="<%- id %> tool-link" href="<%= link %>" target="<%- target %>" minsizehint="<%- min_width %>">',
|
||||
'<%- name %>',
|
||||
'</a>',
|
||||
' <%- description %>'
|
||||
].join('')),
|
||||
|
||||
// the tool form for entering tool parameters, viewing help and executing the tool
|
||||
// loaded when a tool link is clicked in the tool panel
|
||||
tool_form : _.template([
|
||||
'<div class="toolFormTitle"><%- tool.name %> (version <%- tool.version %>)</div>',
|
||||
'<div class="toolFormBody">',
|
||||
'<% _.each( tool.inputs, function( input ){ %>',
|
||||
'<div class="form-row">',
|
||||
'<label for="<%- input.name %>"><%- input.label %>:</label>',
|
||||
'<div class="form-row-input">',
|
||||
'<%= input.html %>',
|
||||
'</div>',
|
||||
'<div class="toolParamHelp" style="clear: both;">',
|
||||
'<%- input.help %>',
|
||||
'</div>',
|
||||
'<div style="clear: both;"></div>',
|
||||
'</div>',
|
||||
'<% }); %>',
|
||||
'</div>',
|
||||
'<div class="form-row form-actions">',
|
||||
'<input type="submit" class="btn btn-primary" name="runtool_btn" value="Execute" />',
|
||||
'</div>',
|
||||
'<div class="toolHelp">',
|
||||
'<div class="toolHelpBody"><% tool.help %></div>',
|
||||
'</div>',
|
||||
// TODO: we need scoping here because 'help' is the dom for the help menu in the masthead
|
||||
// which implies a leaky variable that I can't find
|
||||
].join(''), { variable: 'tool' }),
|
||||
};
|
||||
|
||||
|
||||
// Exports
|
||||
return {
|
||||
ToolParameter: ToolParameter,
|
||||
|
||||
@@ -14,7 +14,7 @@ var View = Backbone.View.extend({
|
||||
this.multiple = options.multiple || false;
|
||||
|
||||
// create message handler
|
||||
this.message = new Ui.Message({ cls: 'ui-margin-top' });
|
||||
this.message = new Ui.Message();
|
||||
|
||||
// create portlet
|
||||
this.portlet = new Portlet.View({ cls: 'ui-portlet-section' });
|
||||
|
||||
@@ -10,257 +10,141 @@ define(['utils/utils',
|
||||
'mvc/ui/ui-modal'],
|
||||
function( Utils, Select, Slider, Options, Drilldown, Buttons, Modal ) {
|
||||
|
||||
/** Image wrapper */
|
||||
var Image = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = Utils.merge(options, {
|
||||
url : '',
|
||||
cls : ''
|
||||
});
|
||||
this.setElement(this._template(this.options));
|
||||
},
|
||||
_template: function(options) {
|
||||
return '<img class="ui-image ' + options.cls + '" src="' + options.url + '"/>';
|
||||
}
|
||||
});
|
||||
|
||||
/** Label wrapper */
|
||||
var Label = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = Utils.merge(options, {
|
||||
title : '',
|
||||
cls : '',
|
||||
tagname : 'label'
|
||||
});
|
||||
this.setElement(this._template(this.options));
|
||||
tagName: 'label',
|
||||
initialize: function( options ) {
|
||||
this.model = options && options.model || new Backbone.Model( options );
|
||||
this.tagName = options.tagName || this.tagName;
|
||||
this.setElement( $( '<' + this.tagName + '/>' ) );
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
this.render();
|
||||
},
|
||||
title: function(new_title) {
|
||||
this.$el.html(new_title);
|
||||
title: function( new_title ) {
|
||||
this.model.set( 'title', new_title );
|
||||
},
|
||||
value: function() {
|
||||
return options.title;
|
||||
return this.model.get( 'title' );
|
||||
},
|
||||
_template: function(options) {
|
||||
return $( '<' + options.tagname + '/>' ).addClass( 'ui-label' ).addClass( options.cls ).html( options.title );
|
||||
}
|
||||
});
|
||||
|
||||
/** Displays an icon with title */
|
||||
var Icon = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = Utils.merge(options, {
|
||||
floating : 'right',
|
||||
icon : '',
|
||||
tooltip : '',
|
||||
placement : 'bottom',
|
||||
title : '',
|
||||
cls : ''
|
||||
});
|
||||
this.setElement(this._template(this.options));
|
||||
$(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
|
||||
},
|
||||
_template: function(options) {
|
||||
return '<div>' +
|
||||
'<span class="fa ' + options.icon + '" class="ui-icon"/> ' +
|
||||
options.title +
|
||||
'</div>';
|
||||
}
|
||||
});
|
||||
|
||||
/** Renders an anchor element */
|
||||
var Anchor = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = Utils.merge(options, {
|
||||
title : '',
|
||||
cls : ''
|
||||
});
|
||||
this.setElement(this._template(this.options));
|
||||
$(this.el).on('click', options.onclick);
|
||||
},
|
||||
_template: function(options) {
|
||||
return '<div><a href="javascript:void(0)" class="ui-anchor ' + options.cls + '">' + options.title + '</a></div>';
|
||||
render: function() {
|
||||
this.$el.removeClass()
|
||||
.addClass( 'ui-label' )
|
||||
.addClass( this.model.get( 'cls' ) )
|
||||
.html( this.model.get( 'title' ) );
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/** Displays messages used e.g. in the tool form */
|
||||
var Message = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = Utils.merge(options, {
|
||||
initialize: function( options ) {
|
||||
this.model = options && options.model || new Backbone.Model({
|
||||
message : null,
|
||||
status : 'info',
|
||||
cls : '',
|
||||
persistent : false
|
||||
});
|
||||
this.setElement('<div class="' + this.options.cls + '"/>');
|
||||
this.options.message && this.update(this.options);
|
||||
}).set( options );
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
this.render();
|
||||
},
|
||||
|
||||
// update
|
||||
update: function(options) {
|
||||
// get options
|
||||
this.options = Utils.merge(options, this.options);
|
||||
|
||||
// show message
|
||||
if (options.message != '') {
|
||||
this.$el.html(this._template(this.options));
|
||||
update: function( options ) {
|
||||
this.model.set( options );
|
||||
},
|
||||
render: function() {
|
||||
this.$el.removeClass().addClass( 'ui-message' ).addClass( this.model.get( 'cls' ) );
|
||||
var status = this.model.get( 'status' );
|
||||
if ( this.model.get( 'large' ) ) {
|
||||
this.$el.addClass((( status == 'success' && 'done' ) ||
|
||||
( status == 'danger' && 'error' ) ||
|
||||
status ) + 'messagelarge' );
|
||||
} else {
|
||||
this.$el.addClass( 'alert' ).addClass( 'alert-' + status );
|
||||
}
|
||||
if ( this.model.get( 'message' ) ) {
|
||||
this.$el.html( this.model.get( 'message' ) );
|
||||
this.$el.fadeIn();
|
||||
|
||||
// clear previous timeouts
|
||||
if (this.timeout) {
|
||||
window.clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
// set timeout if message is not persistent
|
||||
if (!options.persistent) {
|
||||
this.timeout && window.clearTimeout( this.timeout );
|
||||
if ( !this.model.get( 'persistent' ) ) {
|
||||
var self = this;
|
||||
this.timeout = window.setTimeout(function() {
|
||||
if (self.$el.is(':visible')) {
|
||||
self.$el.fadeOut();
|
||||
} else {
|
||||
self.$el.hide();
|
||||
}
|
||||
}, 3000);
|
||||
this.timeout = window.setTimeout( function() {
|
||||
self.$el.fadeOut();
|
||||
}, 3000 );
|
||||
}
|
||||
} else {
|
||||
this.$el.fadeOut();
|
||||
}
|
||||
},
|
||||
|
||||
// template
|
||||
_template: function(options) {
|
||||
var cls_status = 'ui-message alert alert-' + options.status;
|
||||
if (options.large) {
|
||||
cls_status = ( ( options.status == 'success' && 'done' ) ||
|
||||
( options.status == 'danger' && 'error' ) ||
|
||||
options.status ) + 'messagelarge';
|
||||
}
|
||||
return '<div class="' + cls_status + '" >' +
|
||||
options.message +
|
||||
'</div>';
|
||||
}
|
||||
});
|
||||
|
||||
/** Render a search box */
|
||||
var Searchbox = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = Utils.merge(options, {
|
||||
onclick : null,
|
||||
searchword : ''
|
||||
});
|
||||
this.setElement(this._template(this.options));
|
||||
var self = this;
|
||||
if (this.options.onclick) {
|
||||
this.$el.on('submit', function(e) {
|
||||
var search_field = self.$el.find('#search');
|
||||
self.options.onclick(search_field.val());
|
||||
});
|
||||
}
|
||||
},
|
||||
_template: function(options) {
|
||||
return '<div class="ui-search">' +
|
||||
'<form onsubmit="return false;">' +
|
||||
'<input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="' + options.searchword + '">' +
|
||||
'<button type="submit" class="btn search-btn">' +
|
||||
'<i class="fa fa-search"></i>' +
|
||||
'</button>' +
|
||||
'</form>' +
|
||||
'</div>';
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
/** Renders an input element used e.g. in the tool form */
|
||||
var Input = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
// configure options
|
||||
this.options = Utils.merge(options, {
|
||||
initialize: function( options ) {
|
||||
this.model = options && options.model || new Backbone.Model({
|
||||
type : 'text',
|
||||
placeholder : '',
|
||||
disabled : false,
|
||||
visible : true,
|
||||
cls : '',
|
||||
area : false
|
||||
});
|
||||
|
||||
// create new element
|
||||
this.setElement(this._template(this.options));
|
||||
|
||||
// set initial value
|
||||
if (this.options.value !== undefined) {
|
||||
this.value(this.options.value);
|
||||
}
|
||||
|
||||
// disable input field
|
||||
if (this.options.disabled) {
|
||||
this.$el.prop('disabled', true);
|
||||
}
|
||||
|
||||
// hide input field
|
||||
if (!this.options.visible) {
|
||||
this.$el.hide();
|
||||
}
|
||||
|
||||
// onchange event handler. fires on user activity.
|
||||
var self = this;
|
||||
this.$el.on('input', function() {
|
||||
if (self.options.onchange) {
|
||||
self.options.onchange(self.$el.val());
|
||||
}
|
||||
});
|
||||
}).set( options );
|
||||
this.tagName = this.model.get( 'area' ) ? 'textarea' : 'input';
|
||||
this.setElement( $( '<' + this.tagName + '/>' ) );
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
this.render();
|
||||
},
|
||||
|
||||
// value
|
||||
value : function (new_val) {
|
||||
if (new_val !== undefined) {
|
||||
this.$el.val( ( typeof new_val === 'string' && new_val ) || '' );
|
||||
}
|
||||
return this.$el.val();
|
||||
events: {
|
||||
'input': '_onchange'
|
||||
},
|
||||
|
||||
// template
|
||||
_template: function(options) {
|
||||
if (options.area) {
|
||||
return '<textarea id="' + options.id + '" class="ui-textarea ' + options.cls + '"></textarea>';
|
||||
} else {
|
||||
return '<input id="' + options.id + '" type="' + options.type + '" value="' + options.value + '" placeholder="' + options.placeholder + '" class="ui-input ' + options.cls + '">';
|
||||
}
|
||||
value: function( new_val ) {
|
||||
new_val !== undefined && this.model.set( 'value', typeof new_val === 'string' ? new_val : '' );
|
||||
return this.model.get( 'value' );
|
||||
},
|
||||
render: function() {
|
||||
this.$el.removeClass()
|
||||
.addClass( 'ui-' + this.tagName )
|
||||
.addClass( this.model.get( 'cls' ) )
|
||||
.attr( 'id', this.model.id )
|
||||
.attr( 'type', this.model.get( 'type' ) )
|
||||
.attr( 'placeholder', this.model.get( 'placeholder' ) )
|
||||
.val( this.model.get( 'value' ) );
|
||||
this.model.get( 'disabled' ) ? this.$el.attr( 'disabled', true ) : this.$el.removeAttr( 'disabled' );
|
||||
this.$el[ this.model.get( 'visible' ) ? 'show' : 'hide' ]();
|
||||
return this;
|
||||
},
|
||||
_onchange: function() {
|
||||
this.value( this.$el.val() );
|
||||
this.model.get( 'onchange' ) && this.model.get( 'onchange' )( this.model.get( 'value' ) );
|
||||
}
|
||||
});
|
||||
|
||||
/** Creates a hidden element input field used e.g. in the tool form */
|
||||
var Hidden = Backbone.View.extend({
|
||||
initialize : function(options) {
|
||||
this.options = options;
|
||||
this.setElement(this._template(this.options));
|
||||
if (this.options.value !== undefined) {
|
||||
this.value(this.options.value);
|
||||
}
|
||||
initialize: function( options ) {
|
||||
this.model = options && options.model || new Backbone.Model( options );
|
||||
this.setElement( $ ( '<div/>' ).append( this.$info = $( '<div/>' ) )
|
||||
.append( this.$hidden = $( '<div/>' ) ) );
|
||||
this.listenTo( this.model, 'change', this.render, this );
|
||||
this.render();
|
||||
},
|
||||
value : function (new_val) {
|
||||
if (new_val !== undefined) {
|
||||
this.$('hidden').val(new_val);
|
||||
}
|
||||
return this.$('hidden').val();
|
||||
value: function( new_val ) {
|
||||
new_val !== undefined && this.model.set( 'value', new_val );
|
||||
return this.model.get( 'value' );
|
||||
},
|
||||
_template: function(options) {
|
||||
var tmpl = '<div id="' + options.id + '" >';
|
||||
if (options.info) {
|
||||
tmpl += '<div>' + options.info + '</div>';
|
||||
}
|
||||
tmpl += '<hidden value="' + options.value + '"/>' +
|
||||
'</div>';
|
||||
return tmpl;
|
||||
render: function() {
|
||||
this.$el.attr( 'id', this.model.id );
|
||||
this.$hidden.val( this.model.get( 'value' ) );
|
||||
this.model.get( 'info' ) ? this.$info.show().html( this.model.get( 'info' ) ) : this.$info.hide();
|
||||
return this;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
Anchor : Anchor,
|
||||
Button : Buttons.ButtonDefault,
|
||||
ButtonIcon : Buttons.ButtonIcon,
|
||||
ButtonCheck : Buttons.ButtonCheck,
|
||||
ButtonMenu : Buttons.ButtonMenu,
|
||||
ButtonLink : Buttons.ButtonLink,
|
||||
Icon : Icon,
|
||||
Image : Image,
|
||||
Input : Input,
|
||||
Label : Label,
|
||||
Message : Message,
|
||||
@@ -268,7 +152,6 @@ define(['utils/utils',
|
||||
RadioButton : Options.RadioButton,
|
||||
Checkbox : Options.Checkbox,
|
||||
Radio : Options.Radio,
|
||||
Searchbox : Searchbox,
|
||||
Select : Select,
|
||||
Hidden : Hidden,
|
||||
Slider : Slider,
|
||||
|
||||
@@ -322,7 +322,7 @@ return Backbone.View.extend({
|
||||
'<td>' +
|
||||
'<div id="genome" class="upload-genome"/>' +
|
||||
'</td>' +
|
||||
'<td><div id="settings" class="upload-icon-button fa fa-gear"/></td>' +
|
||||
'<td><div id="settings" class="upload-settings upload-icon-button fa fa-gear"/></td>' +
|
||||
'<td>' +
|
||||
'<div id="info" class="upload-info">' +
|
||||
'<div class="progress">' +
|
||||
|
||||
@@ -1,93 +1,43 @@
|
||||
/** This renders the content of the settings popup, allowing users to specify flags i.e. for space-to-tab conversion **/
|
||||
define(['utils/utils'], function(Utils) {
|
||||
define( [ 'utils/utils' ], function( Utils ) {
|
||||
return Backbone.View.extend({
|
||||
// options
|
||||
options: {
|
||||
class_check : 'upload-icon-button fa fa-check-square-o',
|
||||
class_uncheck : 'upload-icon-button fa fa-square-o'
|
||||
class_check : 'fa-check-square-o',
|
||||
class_uncheck : 'fa-square-o',
|
||||
parameters : [{
|
||||
id : 'space_to_tab',
|
||||
title : 'Convert spaces to tabs',
|
||||
},{
|
||||
id : 'to_posix_lines',
|
||||
title : 'Use POSIX standard'
|
||||
}]
|
||||
},
|
||||
|
||||
// initialize
|
||||
initialize: function(app) {
|
||||
// link app
|
||||
this.app = app;
|
||||
|
||||
// link this
|
||||
initialize: function( options ) {
|
||||
var self = this;
|
||||
|
||||
// set template
|
||||
this.setElement(this._template());
|
||||
|
||||
// link model
|
||||
this.model = this.app.model;
|
||||
|
||||
// ui event: space-to-tab
|
||||
this.$('#upload-space-to-tab').on('click', function() {
|
||||
self._switchState('#upload-space-to-tab', 'space_to_tab');
|
||||
});
|
||||
|
||||
// ui event: to-posix-lines
|
||||
this.$('#upload-to-posix-lines').on('click', function() {
|
||||
self._switchState('#upload-to-posix-lines', 'to_posix_lines');
|
||||
});
|
||||
|
||||
// render
|
||||
this.render();
|
||||
this.model = options.model;
|
||||
this.setElement( $( '<div/>' ).addClass( 'upload-settings' ) );
|
||||
this.$el.append( $( '<div/>' ).addClass( 'upload-settings-cover' ) );
|
||||
this.$el.append( $( '<table/>' ).addClass( 'upload-settings-table ui-table-striped' ).append( '<tbody/>' ) );
|
||||
this.$cover = this.$( '.upload-settings-cover' );
|
||||
this.$table = this.$( '.upload-settings-table > tbody' );
|
||||
this.listenTo ( this.model, 'change', this.render, this );
|
||||
this.model.trigger( 'change' );
|
||||
},
|
||||
|
||||
// render
|
||||
render: function() {
|
||||
// render states
|
||||
this._renderState('#upload-space-to-tab', this.model.get('space_to_tab'));
|
||||
this._renderState('#upload-to-posix-lines', this.model.get('to_posix_lines'));
|
||||
|
||||
// disable options
|
||||
var $cover = this.$('#upload-settings-cover');
|
||||
if (!this.model.get('enabled')) {
|
||||
$cover.show();
|
||||
} else {
|
||||
$cover.hide();
|
||||
}
|
||||
},
|
||||
|
||||
// switch state
|
||||
_switchState: function (element_id, parameter_id) {
|
||||
if (this.model.get('enabled')) {
|
||||
var checked = !this.model.get(parameter_id);
|
||||
this.model.set(parameter_id, checked);
|
||||
this._renderState(element_id, checked);
|
||||
}
|
||||
},
|
||||
|
||||
// render state
|
||||
_renderState: function (element_id, checked) {
|
||||
var $it = this.$(element_id);
|
||||
$it.removeClass();
|
||||
if (checked) {
|
||||
$it.addClass(this.options.class_check);
|
||||
} else {
|
||||
$it.addClass(this.options.class_uncheck);
|
||||
}
|
||||
},
|
||||
|
||||
// load template
|
||||
_template: function() {
|
||||
return '<div class="upload-settings" style="position: relative;">' +
|
||||
'<div id="upload-settings-cover" class="upload-settings-cover"/>' +
|
||||
'<table class="ui-table-striped">' +
|
||||
'<tbody>' +
|
||||
'<tr>' +
|
||||
'<td><div id="upload-space-to-tab"/></td>' +
|
||||
'<td>Convert spaces to tabs</td>' +
|
||||
'</tr>' +
|
||||
'<tr>' +
|
||||
'<td><div id="upload-to-posix-lines"/></td>' +
|
||||
'<td>Use POSIX standard</td>' +
|
||||
'</tr>' +
|
||||
'</tbody>' +
|
||||
'</table>' +
|
||||
'</div>';
|
||||
var self = this;
|
||||
this.$table.empty();
|
||||
_.each( this.options.parameters, function( parameter ) {
|
||||
var $checkbox = $( '<div/>' ).addClass( 'upload-' + parameter.id + ' upload-icon-button fa' )
|
||||
.addClass( self.model.get( parameter.id ) && self.options.class_check || self.options.class_uncheck )
|
||||
.on( 'click', function() {
|
||||
self.model.get( 'enabled' ) && self.model.set( parameter.id, !self.model.get( parameter.id ) )
|
||||
});
|
||||
self.$table.append( $( '<tr/>' ).append( $( '<td/>' ).append( $checkbox ) )
|
||||
.append( $( '<td/>' ).append( parameter.title ) ) )
|
||||
});
|
||||
this.$cover[ this.model.get( 'enabled' ) && 'hide' || 'show' ]();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
@@ -4,6 +4,7 @@ define([
|
||||
'mvc/base-mvc',
|
||||
'utils/localization'
|
||||
], function( _, Backbone, baseMVC, _l ){
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'user';
|
||||
//==============================================================================
|
||||
|
||||
@@ -2,6 +2,7 @@ define([
|
||||
"mvc/base-mvc",
|
||||
"utils/localization"
|
||||
], function( baseMVC, _l ){
|
||||
'use strict';
|
||||
|
||||
var logNamespace = 'user';
|
||||
//==============================================================================
|
||||
@@ -27,7 +28,7 @@ var UserQuotaMeter = Backbone.View.extend( baseMVC.LoggableMixin ).extend(
|
||||
_.extend( this.options, options );
|
||||
|
||||
//this.bind( 'all', function( event, data ){ this.log( this + ' event:', event, data ); }, this );
|
||||
this.model.bind( 'change:quota_percent change:total_disk_usage', this.render, this );
|
||||
this.listenTo( this.model, 'change:quota_percent change:total_disk_usage', this.render );
|
||||
},
|
||||
|
||||
/** Re-load user model data from the api */
|
||||
|
||||
@@ -617,9 +617,7 @@ EditorFormView = Backbone.View.extend({
|
||||
|
||||
// Global state for the whole workflow
|
||||
reset: function() {
|
||||
if ( this.workflow ) {
|
||||
this.workflow.remove_all();
|
||||
}
|
||||
this.workflow && this.workflow.remove_all();
|
||||
this.workflow = Globals.workflow = new Workflow( this, $("#canvas-container") );
|
||||
},
|
||||
|
||||
@@ -795,6 +793,7 @@ EditorFormView = Backbone.View.extend({
|
||||
if (node.type == 'tool' && Utils.isJSON(text)) {
|
||||
var options = JSON.parse(text);
|
||||
options.node = node;
|
||||
options.workflow = this.workflow;
|
||||
options.datatypes = this.datatypes;
|
||||
formView = new ToolForm.View(options);
|
||||
} else {
|
||||
|
||||
@@ -8,7 +8,6 @@ window[ 'jQuery' ] = jQuery; // a weird form to prevent webpack from sub'ing 'wi
|
||||
window.$ = jQuery;
|
||||
window._ = _;
|
||||
window.Backbone = Backbone;
|
||||
window.Handlebars = Handlebars;
|
||||
// console.debug('globals loaded:', window.jQuery, window.Backbone, '...');
|
||||
|
||||
// these are galaxy globals not defined in the provider (although they could be - but why encourage that?)
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
define(['libs/handlebars.runtime'], function(Handlebars) {
|
||||
|
||||
return Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
|
||||
|
||||
return "<div class=\"toolSectionTitle\" id=\"title_"
|
||||
+ alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper)))
|
||||
+ "\">\n <a href=\"javascript:void(0)\"><span>"
|
||||
+ alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper)))
|
||||
+ "</span></a>\n</div>\n<div id=\""
|
||||
+ alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper)))
|
||||
+ "\" class=\"toolSectionBody\" style=\"display: none; \">\n <div class=\"toolSectionBg\"></div>\n<div>";
|
||||
},"useData":true})
|
||||
|
||||
});
|
||||
@@ -1,29 +0,0 @@
|
||||
define(['libs/handlebars.runtime'], function(Handlebars) {
|
||||
|
||||
return Handlebars.template({"1":function(depth0,helpers,partials,data) {
|
||||
var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
|
||||
|
||||
return " <div class=\"form-row\">\n <label for=\""
|
||||
+ alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper)))
|
||||
+ "\">"
|
||||
+ alias3(((helper = (helper = helpers.label || (depth0 != null ? depth0.label : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"label","hash":{},"data":data}) : helper)))
|
||||
+ ":</label>\n <div class=\"form-row-input\">\n "
|
||||
+ ((stack1 = ((helper = (helper = helpers.html || (depth0 != null ? depth0.html : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"html","hash":{},"data":data}) : helper))) != null ? stack1 : "")
|
||||
+ "\n </div>\n <div class=\"toolParamHelp\" style=\"clear: both;\">\n "
|
||||
+ alias3(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"help","hash":{},"data":data}) : helper)))
|
||||
+ "\n </div>\n <div style=\"clear: both;\"></div>\n </div>\n";
|
||||
},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
|
||||
|
||||
return "<div class=\"toolFormTitle\">"
|
||||
+ alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper)))
|
||||
+ " (version "
|
||||
+ alias3(((helper = (helper = helpers.version || (depth0 != null ? depth0.version : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"version","hash":{},"data":data}) : helper)))
|
||||
+ ")</div>\n <div class=\"toolFormBody\">\n"
|
||||
+ ((stack1 = helpers.each.call(depth0,(depth0 != null ? depth0.inputs : depth0),{"name":"each","hash":{},"fn":this.program(1, data, 0),"inverse":this.noop,"data":data})) != null ? stack1 : "")
|
||||
+ " </div>\n <div class=\"form-row form-actions\">\n <input type=\"submit\" class=\"btn btn-primary\" name=\"runtool_btn\" value=\"Execute\">\n</div>\n<div class=\"toolHelp\">\n <div class=\"toolHelpBody\">"
|
||||
+ alias3(((helper = (helper = helpers.help || (depth0 != null ? depth0.help : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"help","hash":{},"data":data}) : helper)))
|
||||
+ "</div>\n</div>";
|
||||
},"useData":true})
|
||||
|
||||
});
|
||||
@@ -1,31 +0,0 @@
|
||||
define(['libs/handlebars.runtime'], function(Handlebars) {
|
||||
|
||||
return Handlebars.template({"1":function(depth0,helpers,partials,data) {
|
||||
var alias1=this.lambda, alias2=this.escapeExpression;
|
||||
|
||||
return "<span class=\"label label-default label-"
|
||||
+ alias2(alias1(depth0, depth0))
|
||||
+ "\">"
|
||||
+ alias2(alias1(depth0, depth0))
|
||||
+ "</span> ";
|
||||
},"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
|
||||
|
||||
return "<span class=\"labels\">"
|
||||
+ ((stack1 = helpers.each.call(depth0,(depth0 != null ? depth0.labels : depth0),{"name":"each","hash":{},"fn":this.program(1, data, 0),"inverse":this.noop,"data":data})) != null ? stack1 : "")
|
||||
+ "</span>\n<a class=\""
|
||||
+ alias3(((helper = (helper = helpers.id || (depth0 != null ? depth0.id : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"id","hash":{},"data":data}) : helper)))
|
||||
+ " tool-link\" href=\""
|
||||
+ alias3(((helper = (helper = helpers.link || (depth0 != null ? depth0.link : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"link","hash":{},"data":data}) : helper)))
|
||||
+ "\" target=\""
|
||||
+ alias3(((helper = (helper = helpers.target || (depth0 != null ? depth0.target : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"target","hash":{},"data":data}) : helper)))
|
||||
+ "\" minsizehint=\""
|
||||
+ alias3(((helper = (helper = helpers.min_width || (depth0 != null ? depth0.min_width : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"min_width","hash":{},"data":data}) : helper)))
|
||||
+ "\">"
|
||||
+ alias3(((helper = (helper = helpers.name || (depth0 != null ? depth0.name : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"name","hash":{},"data":data}) : helper)))
|
||||
+ "</a>\n"
|
||||
+ alias3(((helper = (helper = helpers.description || (depth0 != null ? depth0.description : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"description","hash":{},"data":data}) : helper)))
|
||||
+ "\n";
|
||||
},"useData":true})
|
||||
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
define(['libs/handlebars.runtime'], function(Handlebars) {
|
||||
|
||||
return Handlebars.template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) {
|
||||
var helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression;
|
||||
|
||||
return "<input type=\"text\" name=\"query\" placeholder=\""
|
||||
+ alias3(((helper = (helper = helpers.search_hint_string || (depth0 != null ? depth0.search_hint_string : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"search_hint_string","hash":{},"data":data}) : helper)))
|
||||
+ "\" id=\"tool-search-query\" autocomplete=\"off\" class=\"search-query parent-width\" />\n<a id=\"search-clear-btn\" title=\"clear search (esc)\"> </a>\n<img src=\""
|
||||
+ alias3(((helper = (helper = helpers.spinner_url || (depth0 != null ? depth0.spinner_url : depth0)) != null ? helper : alias1),(typeof helper === alias2 ? helper.call(depth0,{"name":"spinner_url","hash":{},"data":data}) : helper)))
|
||||
+ "\" id=\"search-spinner\" class=\"search-spinner\"/>\n";
|
||||
},"useData":true})
|
||||
|
||||
});
|
||||
@@ -1,6 +0,0 @@
|
||||
<div class="toolSectionTitle" id="title_{{id}}">
|
||||
<a href="javascript:void(0)"><span>{{name}}</span></a>
|
||||
</div>
|
||||
<div id="{{id}}" class="toolSectionBody" style="display: none; ">
|
||||
<div class="toolSectionBg"></div>
|
||||
<div>
|
||||
@@ -1,21 +0,0 @@
|
||||
<div class="toolFormTitle">{{name}} (version {{version}})</div>
|
||||
<div class="toolFormBody">
|
||||
{{#each inputs}}
|
||||
<div class="form-row">
|
||||
<label for="{{name}}">{{label}}:</label>
|
||||
<div class="form-row-input">
|
||||
{{{html}}}
|
||||
</div>
|
||||
<div class="toolParamHelp" style="clear: both;">
|
||||
{{help}}
|
||||
</div>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
{{/each}}
|
||||
</div>
|
||||
<div class="form-row form-actions">
|
||||
<input type="submit" class="btn btn-primary" name="runtool_btn" value="Execute">
|
||||
</div>
|
||||
<div class="toolHelp">
|
||||
<div class="toolHelpBody">{{help}}</div>
|
||||
</div>
|
||||
@@ -1,3 +0,0 @@
|
||||
<span class="labels">{{#each labels}}<span class="label label-default label-{{this}}">{{this}}</span> {{/each}}</span>
|
||||
<a class="{{id}} tool-link" href="{{link}}" target="{{target}}" minsizehint="{{min_width}}">{{name}}</a>
|
||||
{{description}}
|
||||
@@ -1,3 +0,0 @@
|
||||
<input type="text" name="query" placeholder="{{search_hint_string}}" id="tool-search-query" autocomplete="off" class="search-query parent-width" />
|
||||
<a id="search-clear-btn" title="clear search (esc)"> </a>
|
||||
<img src="{{spinner_url}}" id="search-spinner" class="search-spinner"/>
|
||||
@@ -30,6 +30,7 @@
|
||||
@import "library.less";
|
||||
@import "toastr.less";
|
||||
@import "jstree.less";
|
||||
@import "tour.less";
|
||||
|
||||
// Mixins
|
||||
.unselectable {
|
||||
@@ -724,6 +725,8 @@ input[type="submit"], button {
|
||||
display: none;
|
||||
right: 6px;
|
||||
top: 9px;
|
||||
font-size: 1.4em;
|
||||
color: #888;
|
||||
}
|
||||
|
||||
#search-clear-btn {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
.popover-title{
|
||||
background-color: @base-color-1;
|
||||
color: @white;
|
||||
}
|
||||
@@ -64,7 +64,11 @@
|
||||
|
||||
.ui-message {
|
||||
padding: 2px 10px 2px 10px;
|
||||
margin: 0px;
|
||||
margin-top: @ui-margin-vertical-large;
|
||||
margin-bottom: 0px;
|
||||
float: left;
|
||||
width: 100%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.ui-modal {
|
||||
|
||||
@@ -227,6 +227,7 @@
|
||||
}
|
||||
|
||||
.upload-settings {
|
||||
position: relative;
|
||||
.upload-settings-cover {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
@@ -15,7 +15,6 @@ module.exports = function( grunt ){
|
||||
'traceKit': [ 'tracekit.js', 'tracekit.js' ],
|
||||
'ravenjs': [ 'dist/raven.js', 'raven.js' ],
|
||||
'underscore': [ 'underscore.js', 'underscore.js' ],
|
||||
'handlebars': [ 'handlebars.runtime.js', 'handlebars.runtime.js' ],
|
||||
'backbone': [ 'backbone.js', 'backbone.js' ],
|
||||
'requirejs': [ 'require.js', 'require.js' ],
|
||||
'd3': [ 'd3.js', 'd3.js' ],
|
||||
@@ -86,7 +85,7 @@ module.exports = function( grunt ){
|
||||
}
|
||||
}
|
||||
|
||||
grunt.loadNpmTasks( 'grunt-bower-install-simple');
|
||||
grunt.loadNpmTasks( 'grunt-bower-install-simple' );
|
||||
|
||||
grunt.registerTask( 'copy-libs', 'copy external libraries to src', copyLibs );
|
||||
grunt.registerTask( 'install-libs', 'fetch external libraries and copy to src',
|
||||
|
||||
@@ -17,7 +17,6 @@ module.exports = function( grunt ){
|
||||
'autocomplete_tagging',
|
||||
'embed_item',
|
||||
'iphone',
|
||||
'masthead',
|
||||
'library',
|
||||
'trackster',
|
||||
'circster',
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/**
|
||||
* Grunt task to compile templates.
|
||||
* @param {Object} grunt main grunt file
|
||||
* @return {Function} callback to build this task
|
||||
*/
|
||||
module.exports = function( grunt ){
|
||||
"use strict";
|
||||
|
||||
var app = grunt.config.get( 'app' ),
|
||||
paths = grunt.config.get( 'paths' );
|
||||
|
||||
grunt.config( 'handlebars', {
|
||||
'default' : {
|
||||
files: [{
|
||||
expand : true,
|
||||
cwd : paths.srcSymlink + '/templates',
|
||||
src : '**/*.handlebars',
|
||||
dest : paths.srcSymlink + '/templates/compiled',
|
||||
ext : '.js'
|
||||
}],
|
||||
options : {
|
||||
// namespace needs to be false to return a fn (instead of adding to a global namespace)
|
||||
namespace : false,
|
||||
// define truthy amd here - if string, this will be the modules require'd
|
||||
amd : 'libs/handlebars.runtime',
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
grunt.registerTask( 'templates', function(){
|
||||
// compile then compress
|
||||
grunt.task.run( 'handlebars' );
|
||||
grunt.config( 'uglify.target.files', [{
|
||||
expand : true,
|
||||
cwd : paths.srcSymlink + '/templates/compiled',
|
||||
src : '**/*.js',
|
||||
dest : paths.dist + '/templates/compiled'
|
||||
}]);
|
||||
grunt.task.run( 'uglify' );
|
||||
});
|
||||
|
||||
// -------------------------------------------------------------------------- watch & compile
|
||||
// grunt.config( 'watch', {
|
||||
// watch: {
|
||||
// // watch for changes in the src dir
|
||||
// files: [ paths.srcSymlink + '/**' ],
|
||||
// tasks: [ 'uglify' ],
|
||||
// options: {
|
||||
// spawn: false
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
grunt.loadNpmTasks( 'grunt-contrib-handlebars' );
|
||||
};
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* Grunt task to bundle apps using webpack (see also ../webpack.config.js).
|
||||
*/
|
||||
module.exports = function( grunt ){
|
||||
"use strict";
|
||||
|
||||
var path = require( 'path' );
|
||||
|
||||
// there is a taskrunner specifically for this - but it's not straightforward
|
||||
// and duplicates some of the config/code in webpack.config,
|
||||
// https://github.com/webpack/grunt-webpack
|
||||
// http://webpack.github.io/docs/usage-with-grunt.html
|
||||
|
||||
// so we'll use grunt-exec and call the webpack cli instead (until CLI and runner are unified a bit more?)
|
||||
|
||||
grunt.loadNpmTasks( 'grunt-exec' );
|
||||
|
||||
function webpackCLI(){
|
||||
var args = Array.prototype.slice.call( arguments );
|
||||
args.unshift( path.join( __dirname, '../node_modules/webpack/bin/webpack.js' ) );
|
||||
return args.join( ' ' );
|
||||
}
|
||||
grunt.registerTask( 'webpack', function(){
|
||||
grunt.log.writeln( 'bundling webpack apps for production...' );
|
||||
grunt.config( 'exec.webpack-production.command', webpackCLI( '-p' ) );
|
||||
grunt.task.run( 'exec:webpack-production' );
|
||||
});
|
||||
grunt.registerTask( 'webpack-dev', function(){
|
||||
grunt.log.writeln( 'bundling webpack apps for development...' );
|
||||
grunt.config( 'exec.webpack-dev.command', webpackCLI( '-d' ) );
|
||||
grunt.task.run( 'exec:webpack-dev' );
|
||||
});
|
||||
grunt.registerTask( 'webpack-watch', function(){
|
||||
grunt.log.writeln( 'bundling webpack apps for development and watching for changes...' );
|
||||
grunt.config( 'exec.webpack-watch.command', webpackCLI( '-d', '--watch' ) );
|
||||
grunt.task.run( 'exec:webpack-watch' );
|
||||
});
|
||||
};
|
||||
@@ -13,15 +13,11 @@
|
||||
"grunt-cli": "^0.1.13",
|
||||
"grunt-contrib-clean": "^0.6.0",
|
||||
"grunt-contrib-copy": "^0.5.0",
|
||||
"grunt-contrib-handlebars": "^0.10.2",
|
||||
"grunt-contrib-less": "^1.1.0",
|
||||
"grunt-contrib-uglify": "^0.8.0",
|
||||
"grunt-contrib-watch": "^0.6.1",
|
||||
"grunt-exec": "^0.4.6",
|
||||
"grunt-spritesmith": "^4.7.1",
|
||||
"grunt-webpack": "^1.0.8",
|
||||
"handlebars": "^4.0.4",
|
||||
"handlebars-loader": "^1.1.4",
|
||||
"i18n-webpack-plugin": "^0.2.7",
|
||||
"webpack": "^1.10.1",
|
||||
"webpack-dev-server": "^1.7.0"
|
||||
|
||||
@@ -23,7 +23,6 @@ var webpack = require( 'webpack' ),
|
||||
// mvc
|
||||
'libs/underscore',
|
||||
'libs/backbone',
|
||||
'libs/handlebars.runtime',
|
||||
// all pages get these
|
||||
'ui/autocom_tagging',
|
||||
'layout/modal',
|
||||
@@ -54,7 +53,6 @@ module.exports = {
|
||||
},
|
||||
module : {
|
||||
loaders : [
|
||||
{ test : /\.handlebars$/, loader : 'handlebars-loader' },
|
||||
],
|
||||
},
|
||||
resolveLoader : {
|
||||
@@ -74,7 +72,6 @@ module.exports = {
|
||||
'window.jQuery': 'jquery',
|
||||
_: "underscore",
|
||||
Backbone: 'libs/backbone',
|
||||
Handlebars: 'libs/handlebars.runtime'
|
||||
}),
|
||||
// new webpack.optimize.LimitChunkCountPlugin({ maxChunks: 1 })
|
||||
],
|
||||
|
||||
@@ -172,7 +172,7 @@ paste.app_factory = galaxy.web.buildapp:app_factory
|
||||
# from the Tool Shed will fail.
|
||||
#tool_dependency_dir = None
|
||||
|
||||
# The dependency resolves config file specifies an ordering and options for how
|
||||
# The dependency resolves config file specifies an ordering and options for how
|
||||
# Galaxy resolves tool dependencies (requirement tags in Tool XML). The default
|
||||
# ordering is to the use the tool shed for tools installed that way, use local
|
||||
# Galaxy packages, and then use conda if available.
|
||||
@@ -301,6 +301,19 @@ paste.app_factory = galaxy.web.buildapp:app_factory
|
||||
# Set to false to disable various checks Galaxy will do to ensure it
|
||||
# can run job scripts before attempting to execute or submit them.
|
||||
#check_job_script_integrity = True
|
||||
# Number of checks to execute if check_job_script_integrity is enabled.
|
||||
#check_job_script_integrity_count = 35
|
||||
# Time to sleep between checks if check_job_script_integrity is enabled (in seconds).
|
||||
#check_job_script_integrity_sleep = .25
|
||||
|
||||
|
||||
# Set the default shell used by jobs Galaxy-wide. This defaults to
|
||||
# sh and can be overidden at the destination level for
|
||||
# heterogenous clusters. conda job resolution requires bash or zsh
|
||||
# so if this is not switched to /bin/bash for instance - conda resolution
|
||||
# should be disabled. (16.01 will likely be the last release with a
|
||||
# default of /bin/sh instead of /bin/bash).
|
||||
#default_job_shell = /bin/sh
|
||||
|
||||
# Citation related caching. Tool citations information maybe fetched from
|
||||
# external sources such as http://dx.doi.org/ by Galaxy - the following
|
||||
@@ -662,6 +675,14 @@ nglims_config_file = tool-data/nglims.yaml
|
||||
# by setting the following option to True.
|
||||
#serve_xss_vulnerable_mimetypes = False
|
||||
|
||||
# Return a Access-Control-Allow-Origin response header that matches the Origin
|
||||
# header of the request if that Origin hostname matches one of the strings or
|
||||
# regular expressions listed here. This is a comma separated list of hostname
|
||||
# strings or regular expressions beginning and ending with /.
|
||||
# E.g. mysite.com,google.com,usegalaxy.org,/^[\w\.]*example\.com/
|
||||
# See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
|
||||
#allowed_origin_hostnames = None
|
||||
|
||||
# Set the following to True to use IPython nbconvert to build HTML from IPython
|
||||
# notebooks in Galaxy histories. This process may allow users to execute
|
||||
# arbitrary code or serve arbitrary HTML. If enabled, IPython must be
|
||||
@@ -878,8 +899,8 @@ use_interactive = True
|
||||
# Set the following to a number of threads greater than 1 to spawn
|
||||
# a Python task queue for dealing with large tool submissions (either
|
||||
# through the tool form or as part of an individual workflow step across
|
||||
# large collection). The size of a "large" tool request is controlled by
|
||||
# the second parameter below and defaults to 10. This affects workflow
|
||||
# large collection). The size of a "large" tool request is controlled by
|
||||
# the second parameter below and defaults to 10. This affects workflow
|
||||
# scheduling and web processes, not job handlers.
|
||||
#tool_submission_burst_threads = 1
|
||||
#tool_submission_burst_at = 10
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
name: Scratchbook - Introduction
|
||||
title_default: "Scratchbook Introduction"
|
||||
description: "An introduction on how to display multiple datasets and visualizations next to each other."
|
||||
steps:
|
||||
- content: "This short tour will walk you through <b>Galaxy's Scratchbook</b> feature"
|
||||
|
||||
- element: "#tool-panel-upload-button"
|
||||
intro: "Before using the Scratchbook, we will upload some tabular data."
|
||||
position: "right"
|
||||
postclick:
|
||||
- "#tool-panel-upload-button"
|
||||
|
||||
- element: "#btn-new"
|
||||
intro: "We will be using the paste feature to create a new dataset."
|
||||
position: "top"
|
||||
postclick:
|
||||
- "#btn-new"
|
||||
|
||||
- element: ".text-content:first"
|
||||
intro: "...and paste content into the text area field."
|
||||
position: "top"
|
||||
textinsert: |
|
||||
1 0.039 0.000
|
||||
2 0.455 0.000
|
||||
3 0.472 0.000
|
||||
4 0.030 0.000
|
||||
5 0.000 0.000
|
||||
6 0.000 0.000
|
||||
7 0.000 0.000
|
||||
8 0.000 0.000
|
||||
|
||||
- element: ".upload-settings:first"
|
||||
intro: "Now, we may further configure the upload content."
|
||||
position: "right"
|
||||
postclick:
|
||||
- ".upload-settings:first"
|
||||
|
||||
- element: ".upload-space_to_tab:first"
|
||||
intro: "...by specifying that all spaces in our table should be converted into tabs."
|
||||
position: "left"
|
||||
postclick:
|
||||
- ".upload-space_to_tab:first"
|
||||
|
||||
- element: "#btn-start"
|
||||
intro: "Upload the data into your Galaxy history."
|
||||
position: "top"
|
||||
postclick:
|
||||
- "#btn-start"
|
||||
|
||||
- element: "#btn-close"
|
||||
intro: "Hit the close button to close the upload dialog."
|
||||
position: "top"
|
||||
postclick:
|
||||
- "#btn-close"
|
||||
|
||||
- element: "#enable-scratchbook > .dropdown > .dropdown-toggle"
|
||||
intro: "Clicking this button will enable Galaxy's Scratchbook mode."
|
||||
position: "right"
|
||||
postclick:
|
||||
- "#enable-scratchbook > .dropdown > .dropdown-toggle"
|
||||
|
||||
- element: "#right"
|
||||
intro: "This is your history. It contains all datasets you are currently working with including our uploaded table."
|
||||
position: "left"
|
||||
|
||||
- element: ".fa-eye:first"
|
||||
intro: "Clicking the eye-icon usually displays a dataset in the center panel."
|
||||
position: "left"
|
||||
postclick:
|
||||
- ".fa-eye:first"
|
||||
|
||||
- element: "#frame-0"
|
||||
intro: "However while in Scratchbook mode, the dataset will be shown as resizable window."
|
||||
position: "right"
|
||||
|
||||
- title: "Done."
|
||||
intro: "You have created a Scratchbook view. Click on the background and select more datasets."
|
||||
File diff suppressed because one or more lines are too long
@@ -5,29 +5,13 @@ module.exports = function(grunt) {
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON( 'package.json' ),
|
||||
|
||||
handlebars: {
|
||||
// compile all hb templates into a single file in the build dir
|
||||
compile: {
|
||||
options: {
|
||||
namespace: 'scatterplot',
|
||||
processName : function( filepath ){
|
||||
return filepath.match( /\w*\.handlebars/ )[0].replace( '.handlebars', '' );
|
||||
}
|
||||
},
|
||||
files: {
|
||||
"build/compiled-templates.js" : "src/handlebars/*.handlebars"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
concat: {
|
||||
// concat the template file and any js files in the src dir into a single file in the build dir
|
||||
// concat any js files in the src dir into a single file in the build dir
|
||||
options: {
|
||||
separator: ';\n'
|
||||
},
|
||||
dist: {
|
||||
//NOTE: mvc references templates - templates must be cat'd first
|
||||
src : [ 'build/compiled-templates.js', 'src/**/*.js' ],
|
||||
src : [ 'src/**/*.js' ],
|
||||
dest: 'build/scatterplot-concat.js'
|
||||
}
|
||||
},
|
||||
@@ -47,17 +31,16 @@ module.exports = function(grunt) {
|
||||
|
||||
watch: {
|
||||
// watch for changes in the src dir
|
||||
files: [ 'src/**.js', 'src/handlebars/*.handlebars' ],
|
||||
files: [ 'src/**.js' ],
|
||||
tasks: [ 'default' ]
|
||||
}
|
||||
});
|
||||
|
||||
grunt.loadNpmTasks( 'grunt-contrib-handlebars' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-concat' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
|
||||
grunt.loadNpmTasks( 'grunt-contrib-watch' );
|
||||
|
||||
grunt.registerTask( 'default', [ 'handlebars', 'concat', 'uglify' ]);
|
||||
grunt.registerTask( 'default', [ 'concat', 'uglify' ]);
|
||||
// you can run grunt watch directly:
|
||||
// grunt watch
|
||||
};
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-cli": "~0.1.9",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-handlebars": "^0.9.3",
|
||||
"grunt-contrib-uglify": "~0.2.2",
|
||||
"grunt-contrib-watch": "~0.5.3"
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
<p class="help-text">
|
||||
Use the following controls to how the chart is displayed.
|
||||
The slide controls can be moved by the mouse or, if the 'handle' is in focus, your keyboard's arrow keys.
|
||||
Move the focus between controls by using the tab or shift+tab keys on your keyboard.
|
||||
Use the 'Draw' button to render (or re-render) the chart with the current settings.
|
||||
</p>
|
||||
|
||||
<div data-config-key="datapointSize" class="form-input numeric-slider-input">
|
||||
<label for="datapointSize">Size of data point: </label>
|
||||
<div class="slider-output">{{datapointSize}}</div>
|
||||
<div class="slider"></div>
|
||||
<p class="form-help help-text-small">
|
||||
Size of the graphic representation of each data point
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div data-config-key="width" class="form-input numeric-slider-input">
|
||||
<label for="width">Chart width: </label>
|
||||
<div class="slider-output">{{width}}</div>
|
||||
<div class="slider"></div>
|
||||
<p class="form-help help-text-small">
|
||||
(not including chart margins and axes)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div data-config-key="height" class="form-input numeric-slider-input">
|
||||
<label for="height">Chart height: </label>
|
||||
<div class="slider-output">{{height}}</div>
|
||||
<div class="slider"></div>
|
||||
<p class="form-help help-text-small">
|
||||
(not including chart margins and axes)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div data-config-key="X-axis-label"class="text-input form-input">
|
||||
<label for="X-axis-label">Re-label the X axis: </label>
|
||||
<input type="text" name="X-axis-label" id="X-axis-label" value="{{xLabel}}" />
|
||||
<p class="form-help help-text-small"></p>
|
||||
</div>
|
||||
|
||||
<div data-config-key="Y-axis-label" class="text-input form-input">
|
||||
<label for="Y-axis-label">Re-label the Y axis: </label>
|
||||
<input type="text" name="Y-axis-label" id="Y-axis-label" value="{{yLabel}}" />
|
||||
<p class="form-help help-text-small"></p>
|
||||
</div>
|
||||
|
||||
<button class="render-button btn btn-primary active">Draw</button>
|
||||
@@ -1,24 +0,0 @@
|
||||
<p class="help-text">
|
||||
Use the following control to change which columns are used by the chart. Click any cell
|
||||
from the last three rows of the table to select the column for the appropriate data.
|
||||
Use the 'Draw' button to render (or re-render) the chart with the current settings.
|
||||
</p>
|
||||
|
||||
<ul class="help-text" style="margin-left: 8px">
|
||||
<li><b>X Column</b>: which column values will be used for the x axis of the chart.</li>
|
||||
<li><b>Y Column</b>: which column values will be used for the y axis of the chart.</li>
|
||||
<li><b>ID Column</b>: an additional column value displayed when the user hovers over a data point.
|
||||
It may be useful to select unique or categorical identifiers here (such as gene ids).
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="column-selection">
|
||||
<pre class="peek">{{{ peek }}}</pre>
|
||||
</div>
|
||||
|
||||
<p class="help-text help-text-small">
|
||||
<b>Note</b>: If it can be determined from the dataset's filetype that a column is not numeric,
|
||||
that column choice may be disabled for either the x or y axis.
|
||||
</p>
|
||||
|
||||
<button class="render-button btn btn-primary active">Draw</button>
|
||||
@@ -1,42 +0,0 @@
|
||||
<div class="scatterplot-editor tabbable tabs-left">
|
||||
{{! tab buttons/headers using Bootstrap }}
|
||||
<ul class="nav nav-tabs">
|
||||
{{! start with the data controls as the displayed tab }}
|
||||
<li class="active">
|
||||
<a title="Use this tab to change which data are used"
|
||||
href="#data-control" data-toggle="tab">Data Controls</a>
|
||||
</li>
|
||||
<li>
|
||||
<a title="Use this tab to change how the chart is drawn"
|
||||
href="#chart-control" data-toggle="tab" >Chart Controls</a>
|
||||
</li>
|
||||
{{! chart starts as disabled since there's no info yet }}
|
||||
<li class="disabled">
|
||||
<a title="This tab will display the chart"
|
||||
href="#chart-display" data-toggle="tab">Chart</a>
|
||||
</li>
|
||||
{{! ... }}
|
||||
<li class="file-controls">
|
||||
<!-- <button class="copy-btn btn btn-default"
|
||||
title="Save this as a new visualization">Save to new</button>-->
|
||||
<button class="save-btn btn btn-default">Save</button>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
{{! data form, chart config form, chart all get their own tab }}
|
||||
<div class="tab-content">
|
||||
{{! ---------------------------- tab for data settings form }}
|
||||
<div id="data-control" class="scatterplot-config-control tab-pane active">
|
||||
{{! rendered separately }}
|
||||
</div>
|
||||
|
||||
{{! ---------------------------- tab for chart graphics control form }}
|
||||
<div id="chart-control" class="scatterplot-config-control tab-pane">
|
||||
{{! rendered separately }}
|
||||
</div>
|
||||
|
||||
{{! ---------------------------- tab for actual chart }}
|
||||
<div id="chart-display" class="scatterplot-display tab-pane"></div>
|
||||
|
||||
</div>{{! end .tab-content }}
|
||||
</div>{{! end .chart-control }}
|
||||
@@ -18,7 +18,7 @@ todo:
|
||||
Drag & Drop other splots onto current (redraw with new axis and differentiate the datasets)
|
||||
Remove 'chart' namessave
|
||||
Somehow link out from info box?
|
||||
|
||||
|
||||
Subclass on specific datatypes? (vcf, cuffdiff, etc.)
|
||||
What can be common/useful to other visualizations?
|
||||
|
||||
@@ -33,7 +33,7 @@ var ScatterplotConfigEditor = Backbone.View.extend({
|
||||
//TODO: !should be a view on a visualization model
|
||||
//logger : console,
|
||||
className : 'scatterplot-control-form',
|
||||
|
||||
|
||||
/** initialize requires a configuration Object containing a dataset Object */
|
||||
initialize : function( attributes ){
|
||||
if( !this.model ){
|
||||
@@ -139,7 +139,7 @@ var ScatterplotConfigEditor = Backbone.View.extend({
|
||||
$dataControl.find( '[title]' ).tooltip();
|
||||
return $dataControl;
|
||||
},
|
||||
|
||||
|
||||
/** tab content to control how the chart is rendered (data glyph size, chart size, etc.) */
|
||||
_render_chartControls : function( $where ){
|
||||
//TODO: as controls on actual chart
|
||||
@@ -147,7 +147,7 @@ var ScatterplotConfigEditor = Backbone.View.extend({
|
||||
var editor = this,
|
||||
config = this.model.get( 'config' ),
|
||||
$chartControls = $where.find( '#chart-control' );
|
||||
|
||||
|
||||
// ---- skeleton/form for controls
|
||||
$chartControls.html( ScatterplotConfigEditor.templates.chartControl( config ) );
|
||||
//console.debug( '$chartControl:', $chartControls );
|
||||
@@ -258,9 +258,130 @@ var ScatterplotConfigEditor = Backbone.View.extend({
|
||||
});
|
||||
|
||||
ScatterplotConfigEditor.templates = {
|
||||
mainLayout : scatterplot.editor,
|
||||
dataControl : scatterplot.datacontrol,
|
||||
chartControl : scatterplot.chartcontrol
|
||||
// tabbed, main layout for the editor (not used for scatterplot-display)
|
||||
mainLayout : _.template([
|
||||
'<div class="scatterplot-editor tabbable tabs-left">',
|
||||
// tab buttons/headers using Bootstrap
|
||||
'<ul class="nav nav-tabs">',
|
||||
// start with the data controls as the displayed tab
|
||||
'<li class="active">',
|
||||
'<a title="Use this tab to change which data are used"',
|
||||
'href="#data-control" data-toggle="tab">Data Controls</a>',
|
||||
'</li>',
|
||||
'<li>',
|
||||
'<a title="Use this tab to change how the chart is drawn"',
|
||||
'href="#chart-control" data-toggle="tab" >Chart Controls</a>',
|
||||
'</li>',
|
||||
// chart starts as disabled since there's no info yet
|
||||
'<li class="disabled">',
|
||||
'<a title="This tab will display the chart"',
|
||||
'href="#chart-display" data-toggle="tab">Chart</a>',
|
||||
'</li>',
|
||||
// button for saving the visualization config on the server
|
||||
'<li class="file-controls">',
|
||||
'<button class="save-btn btn btn-default">Save</button>',
|
||||
'</li>',
|
||||
'</ul>',
|
||||
|
||||
// data form, chart config form, chart all get their own tab
|
||||
'<div class="tab-content">',
|
||||
// tab for data settings form
|
||||
'<div id="data-control" class="scatterplot-config-control tab-pane active"></div>',
|
||||
|
||||
// tab for chart graphics control form
|
||||
'<div id="chart-control" class="scatterplot-config-control tab-pane"></div>',
|
||||
|
||||
// tab for actual chart
|
||||
'<div id="chart-display" class="scatterplot-display tab-pane"></div>',
|
||||
|
||||
'</div>',
|
||||
'</div>',
|
||||
].join('')),
|
||||
|
||||
// the controls for data selection (this is mostly done with column selector now)
|
||||
// TODO: this could be moved to the main template above
|
||||
// TODO: localize
|
||||
dataControl : _.template([
|
||||
'<p class="help-text">',
|
||||
'Use the following control to change which columns are used by the chart. Click any cell ',
|
||||
'from the last three rows of the table to select the column for the appropriate data. ',
|
||||
'Use the \'Draw\' button to render (or re-render) the chart with the current settings. ',
|
||||
'</p>',
|
||||
|
||||
'<ul class="help-text" style="margin-left: 8px">',
|
||||
'<li><b>X Column</b>: which column values will be used for the x axis of the chart.</li>',
|
||||
'<li><b>Y Column</b>: which column values will be used for the y axis of the chart.</li>',
|
||||
'<li><b>ID Column</b>: an additional column value displayed when the user hovers over a data point. ',
|
||||
'It may be useful to select unique or categorical identifiers here (such as gene ids).',
|
||||
'</li>',
|
||||
'</ul>',
|
||||
|
||||
'<div class="column-selection">',
|
||||
// the only dynamic thing
|
||||
'<pre class="peek"><%= peek %></pre>',
|
||||
'</div>',
|
||||
|
||||
'<p class="help-text help-text-small">',
|
||||
'<b>Note</b>: If it can be determined from the dataset\'s filetype that a column is not numeric, ',
|
||||
'that column choice may be disabled for either the x or y axis.',
|
||||
'</p>',
|
||||
|
||||
'<button class="render-button btn btn-primary active">Draw</button>',
|
||||
].join('')),
|
||||
|
||||
chartControl : _.template([
|
||||
'<p class="help-text">',
|
||||
'Use the following controls to how the chart is displayed. The slide controls can be moved ',
|
||||
'by the mouse or, if the \'handle\' is in focus, your keyboard\'s arrow keys. ',
|
||||
'Move the focus between controls by using the tab or shift+tab keys on your keyboard. ',
|
||||
'Use the \'Draw\' button to render (or re-render) the chart with the current settings. ',
|
||||
'</p>',
|
||||
|
||||
'<div data-config-key="datapointSize" class="form-input numeric-slider-input">',
|
||||
'<label for="datapointSize">Size of data point: </label>',
|
||||
'<div class="slider-output"><%- datapointSize %></div>',
|
||||
'<div class="slider"></div>',
|
||||
'<p class="form-help help-text-small">',
|
||||
'Size of the graphic representation of each data point',
|
||||
'</p>',
|
||||
'</div>',
|
||||
|
||||
'<div data-config-key="width" class="form-input numeric-slider-input">',
|
||||
'<label for="width">Chart width: </label>',
|
||||
'<div class="slider-output"><%- width %></div>',
|
||||
'<div class="slider"></div>',
|
||||
'<p class="form-help help-text-small">',
|
||||
'(not including chart margins and axes)',
|
||||
'</p>',
|
||||
'</div>',
|
||||
|
||||
'<div data-config-key="height" class="form-input numeric-slider-input">',
|
||||
'<label for="height">Chart height: </label>',
|
||||
'<div class="slider-output"><%- height %></div>',
|
||||
'<div class="slider"></div>',
|
||||
'<p class="form-help help-text-small">',
|
||||
'(not including chart margins and axes)',
|
||||
'</p>',
|
||||
'</div>',
|
||||
|
||||
'<div data-config-key="X-axis-label"class="text-input form-input">',
|
||||
'<label for="X-axis-label">Re-label the X axis: </label>',
|
||||
'<input type="text" name="X-axis-label" id="X-axis-label" value="<%- xLabel %>" />',
|
||||
'<p class="form-help help-text-small"></p>',
|
||||
'</div>',
|
||||
|
||||
'<div data-config-key="Y-axis-label" class="text-input form-input">',
|
||||
'<label for="Y-axis-label">Re-label the Y axis: </label>',
|
||||
'<input type="text" name="Y-axis-label" id="Y-axis-label" value="<%- yLabel %>" />',
|
||||
'<p class="form-help help-text-small"></p>',
|
||||
'</div>',
|
||||
|
||||
'<button class="render-button btn btn-primary active">Draw</button>',
|
||||
].join('')),
|
||||
|
||||
// mainLayout : scatterplot.editor,
|
||||
// dataControl : scatterplot.datacontrol,
|
||||
// chartControl : scatterplot.chartcontrol
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -30,7 +30,6 @@ ${h.js( 'libs/jquery/jquery',
|
||||
'libs/underscore',
|
||||
'libs/backbone/backbone',
|
||||
'libs/d3',
|
||||
'libs/handlebars.runtime',
|
||||
'ui/peek-column-selector',
|
||||
'ui/pagination',
|
||||
'mvc/visualization/visualization-model' )}
|
||||
|
||||
@@ -169,6 +169,7 @@ class Configuration( object ):
|
||||
self.job_queue_cleanup_interval = int( kwargs.get("job_queue_cleanup_interval", "5") )
|
||||
self.cluster_files_directory = os.path.abspath( kwargs.get( "cluster_files_directory", "database/pbs" ) )
|
||||
self.job_working_directory = resolve_path( kwargs.get( "job_working_directory", "database/job_working_directory" ), self.root )
|
||||
self.default_job_shell = kwargs.get( "default_job_shell", "/bin/sh" )
|
||||
self.cleanup_job = kwargs.get( "cleanup_job", "always" )
|
||||
self.container_image_cache_path = self.resolve_path( kwargs.get( "container_image_cache_path", "database/container_images" ) )
|
||||
self.outputs_to_working_directory = string_as_bool( kwargs.get( 'outputs_to_working_directory', False ) )
|
||||
@@ -262,6 +263,7 @@ class Configuration( object ):
|
||||
if kwargs.get('sanitize_whitelist_file', None) is not None:
|
||||
self.reload_sanitize_whitelist()
|
||||
self.serve_xss_vulnerable_mimetypes = string_as_bool( kwargs.get( 'serve_xss_vulnerable_mimetypes', False ) )
|
||||
self.allowed_origin_hostnames = self._parse_allowed_origin_hostnames( kwargs )
|
||||
self.trust_ipython_notebook_conversion = string_as_bool( kwargs.get( 'trust_ipython_notebook_conversion', False ) )
|
||||
self.enable_old_display_applications = string_as_bool( kwargs.get( "enable_old_display_applications", "True" ) )
|
||||
self.brand = kwargs.get( 'brand', None )
|
||||
@@ -671,6 +673,24 @@ class Configuration( object ):
|
||||
port = None
|
||||
return port
|
||||
|
||||
def _parse_allowed_origin_hostnames( self, kwargs ):
|
||||
"""
|
||||
Parse a CSV list of strings/regexp of hostnames that should be allowed
|
||||
to use CORS and will be sent the Access-Control-Allow-Origin header.
|
||||
"""
|
||||
allowed_origin_hostnames = listify( kwargs.get( 'allowed_origin_hostnames', None ) )
|
||||
if not allowed_origin_hostnames:
|
||||
return None
|
||||
|
||||
def parse( string ):
|
||||
# a string enclosed in fwd slashes will be parsed as a regexp: e.g. /<some val>/
|
||||
if string[0] == '/' and string[-1] == '/':
|
||||
string = string[1:-1]
|
||||
return re.compile( string, flags=( re.UNICODE | re.LOCALE ) )
|
||||
return string
|
||||
|
||||
return [ parse( v ) for v in allowed_origin_hostnames if v ]
|
||||
|
||||
|
||||
def get_database_engine_options( kwargs, model_prefix='' ):
|
||||
"""
|
||||
|
||||
@@ -81,6 +81,7 @@ class TabularData( data.Text ):
|
||||
# For now, default to the old behavior, ugly as it is. Remove this after adding 'matrix'.
|
||||
max_peek_size = 1000000 # 1 MB
|
||||
if os.stat( dataset.file_name ).st_size < max_peek_size:
|
||||
self._clean_and_set_mime_type( trans, dataset.get_mime() )
|
||||
return open( dataset.file_name )
|
||||
else:
|
||||
trans.response.set_content_type( "text/html" )
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
# packages with C extensions
|
||||
bx-python==0.7.3 --hash:sha256=0a0fd962edd0f9afdf5d7ccbdf46dc220a0cb652073a93411dd6f7f649f07d91 \
|
||||
--hash:sha256=46dc3042c7e475363830fa92d4a613ae10b58db7f114ff8193d2ee0bc3c4607e \
|
||||
--hash:sha256=b93a9378a5d0e29ea8a13e026c170f48bf1f8316a39c342b1eb54f557b4fb3c4 \
|
||||
--hash:sha256=d06c7bf0ae7f019521aeb5ffe4df48bb5fdd4d75d7ad00e0059b997c4f13ca3a \
|
||||
--hash:sha256=05d0ab8fd13319d5ef9edb246dc6805640ea7574bb885a0b8607474271ac5793 \
|
||||
--hash:sha256=5a026869227a6464eba23835765a36ffc2910f7af51b81f672a97c0d005e04a3 \
|
||||
--hash:sha256=85be43a6b94f0c841d9954f820133db35067854504c1de87dd0089bb06eca18d \
|
||||
--hash:sha256=d085824eb33c54d333b99dca29b49890457a8263f431b54b17ae3052be191d2b \
|
||||
--hash:sha256=41bcf85b9be9f61ba7c7bae48c5a5ae3251868a1b25f02b6eb93b29bcabfd00c \
|
||||
--hash:sha256=c9b71aee26ee85fbcbb3060109d79531bfa8991f4924bdcfed63d909a5937290
|
||||
MarkupSafe==0.23 --hash:sha256=3a79d9650b7e79943be51a045c7c39a77ebbe9a337e8af51a5575e39332dce87 \
|
||||
--hash:sha256=e0a4155493d1cfa72e985dbe1660a44d64a173282801563956e061b24371266a \
|
||||
--hash:sha256=147013ed157f1423a0d0047043c6bbccbef31a52d82e2a10dfc3c6de9392765c \
|
||||
--hash:sha256=d25d14cb01284aed33690b85bfde8de206ffcfdc52351588bcf17480839bef6f \
|
||||
--hash:sha256=29958f81958e0dd9f5dd36d52f2ac549d875dde3559b783578118c9005693852 \
|
||||
--hash:sha256=287a1c6b0d2a08cb76be6e584bf119649405f015598cf8b78d4a592cc80700a0 \
|
||||
--hash:sha256=973cadf7b9907f9c81d9b898817d6a485b37325176befec2389fa2ced4c61a51 \
|
||||
--hash:sha256=a365fd3468c86741aec5901f4b07990aaa0b458fb79e9f3557378a63e6d627e9 \
|
||||
--hash:sha256=ba7af558b18ba9c05bb0d36f22a5ea65ee11ba44a6cf8a2950f2f80c08260e11 \
|
||||
--hash:sha256=51bf7f077938c64dd00de6732996ccee8ceba2206c69acfb07f66430ca76372f
|
||||
PyYAML==3.11 --hash:sha256=2912c1fb56c316461d003a8b8f1f41e1ed8387b2e47a4523f8a4eec8aa85e241 \
|
||||
--hash:sha256=f4437443dc014c04ceee8cc94d4165f01ba23643991fd2c6b919f26cf9997474 \
|
||||
--hash:sha256=b62cde962d41377c175831fa3fd6ac41585d2e2111ca4c45a6ee80a832457e92 \
|
||||
--hash:sha256=aad37be9d524ba2dba9a3114b620b2800b40e67e455c9741a5cb81a6a0e882f6 \
|
||||
--hash:sha256=03e0f4ac96599c1d687b080f1610ab0469e8785bb48cfdf860f2076a08ea6406 \
|
||||
--hash:sha256=7dc97b5b1b920f6bbe0e47cfa6ff112f6eede35924a63354f80d672354f25160 \
|
||||
--hash:sha256=ceb5dccec2045d4a864c6e808b397b10830476c44bdc64b80c18bf29e481ba07 \
|
||||
--hash:sha256=9b184a4a7d3d383b39cb73429d3798370facaee4263465b575f243c7ede3f9c3 \
|
||||
--hash:sha256=f90314e2ed46ea2da980aff88b91c3cc8ce93edd4658011dd462a8f28399533b \
|
||||
--hash:sha256=80936dca10b611cd54ca52939aac938d59653830a6a6265bef5d11896de8e249
|
||||
SQLAlchemy==1.0.8 --hash:sha256=3c357f36c141205cea2b5ec4c4e9885602452fea06428d6c20596c66c9a43243 \
|
||||
--hash:sha256=17fad7f37f902dbec37ca2777af3021f9a4ed31079d64f7f888e7b29517240a3 \
|
||||
--hash:sha256=e177904a384b9bc68914afb32a6ed2cc73ed7787444e3e1fdf85e3b9cfe5f847 \
|
||||
--hash:sha256=91ed10baf56b6e29665f2b9fcb0c690afc6cc2c2e8e19c7f92b58092a4002e14 \
|
||||
--hash:sha256=f5d6156d1d7865cd23b76ddad3f53ec07a3009a2cd8082a829cd1f24b366db5c \
|
||||
--hash:sha256=3c3f3baf07f868c1c3f86d63dc2efa4455e95d76745f1af561f1ccf0fd9e8c81 \
|
||||
--hash:sha256=a9fb8061aa767ca2ad22983a11e074ac231f44a56709721c60cc1992f2a92350 \
|
||||
--hash:sha256=884b522d2d067cffd103f4e1a5342c678803cd6903da24a3f757b57b00eb188b \
|
||||
--hash:sha256=d5dde66c1603853aebbfbbd74d79c60678f7d98c17abce4be4ebbb697dfd7265 \
|
||||
--hash:sha256=42346d5e91c5e0a5a975352d8af3cfd8b2dad602dd07ec41b6b848ac5205cf5b
|
||||
# Mercurial >= 3.5 changed the bundle format, which breaks hg push of TS repositories
|
||||
mercurial==3.4.2 --hash:sha256=7851864b03929c09e07670bf8ab7d59f3529650c935a70d09fb6ce7f6a84e2a5 \
|
||||
--hash:sha256=c23b02b4c32edc2d0799221a9d35abd916fb8a1acd1c07d64c16a235ef677b9e \
|
||||
--hash:sha256=ca72ddfaea681a070b62edcb8e41d58bd24a2b04f73e66658565d189a76f3819 \
|
||||
--hash:sha256=fdad4496f3d7f3e7eced771fa46e21c074989f8437ddf3e0ff6c0eee964e4c29 \
|
||||
--hash:sha256=964a10ec1114dbee3696134bafed676f66038759b73de8593f92616f0e53f371 \
|
||||
--hash:sha256=c6ca6fbe56a8919dfc521e80ab781ab565760d87f4a6170e788d67eb6d69d30f \
|
||||
--hash:sha256=69540318fa9f7a3a0428647003d4f1fa8865d29648e73999b921cae039145ce9 \
|
||||
--hash:sha256=b3de0ee851cf8750f53102437c9a04c7217a8c6f7411030ab3bb5534885f3315 \
|
||||
--hash:sha256=46f67af52c7b1aed68b67daa33c26eafc0fb1d371954d3266fce739446cfcb1d \
|
||||
--hash:sha256=000afb932f0ae45c365cbc0457044e8800811fdad7eee9332b6403b83423ab0a
|
||||
numpy==1.9.2 --hash:sha256=931ce6fd1180a10d58a925b614775706c05de35bca5805e705e1da17e1326862 \
|
||||
--hash:sha256=2340c4b72fdab79ac0fc04bb6629b26eeb93d10f4945b6b1f07d9be8663cab84 \
|
||||
--hash:sha256=83fe34ff67653a639c57cfd04a0d48dda5913250fd95c8466af1d8416b58af59 \
|
||||
--hash:sha256=aeb182d95ddb2dfd81683907be193cfc11c4d0ba744faf457013499fa14a131e \
|
||||
--hash:sha256=d6f1eec7ae250892a2b142af406e43760042badae8e2f168136eace5dd9f05c3 \
|
||||
--hash:sha256=0b0883cac08e3c0999159ba7f34c9b94d26d7d1a2be4017b792145d722646fb7 \
|
||||
--hash:sha256=a124d11b1bec5c517d60ad9414564b5af0828421112d2a00771d22715eab1c3c \
|
||||
--hash:sha256=fabc2f76266de7396e2752baabf287cdd0cc2ed23c1f36ca3c3e8b094e86b87c \
|
||||
--hash:sha256=f83a667d3a38643b3bf6361904cd6c4f2a18d1420c2204c7f269cd36b730c404 \
|
||||
--hash:sha256=dab9bd8c867403340b370ea383c8eda3dc984dd5efc91904a5695e00b1762fc9
|
||||
pycrypto==2.6.1 --hash:sha256=44c20785a1057b8d5e190d6a1847f7c62a8180b9b27a3aca7c3ec920bfb8e7b7 \
|
||||
--hash:sha256=785ba61251cda6e574e0affc4412c346ef615455b81287fe0d6a2e1c5aed5172 \
|
||||
--hash:sha256=5ec40d95520a665843915763c8cbbf40457330bd7ebf2a55ffea1b10a519d12b \
|
||||
--hash:sha256=2cb43f0b293a18e6d5818287150994cf6083b1a9cdff65c19d1150a34aa813bc \
|
||||
--hash:sha256=d48e46f4ccd5c21f3e01bbdbd8e7a86443fc7abdf3f93829c3d04ed684ec22c5 \
|
||||
--hash:sha256=30312bd39f45c91f287f3e6e54c40988d30b1be9a9f332585e3cc00ee5f91554 \
|
||||
--hash:sha256=d129d6d3441efecf2bc7e6b36cb35e99642248d72dbf59b992e6940b9359dabc \
|
||||
--hash:sha256=8884b92835a1c0c763099981d19c990fdc3ae2b7011eb93b1f96e34a346b2d2f \
|
||||
--hash:sha256=7e7e9abc0ae522ae86772d98b7144e0d2ef7791d124936f283680f84fe8cce6c \
|
||||
--hash:sha256=61d3b42eaf89108b8a24c3736fb770f768efb89b1efaf0825efb5c316f0bffdc
|
||||
|
||||
# Install python_lzo if you want to support indexed access to lzo-compressed
|
||||
# locally cached maf files via bx-python
|
||||
#python_lzo==1.8 --hash:sha256=638b38bc1d83561a9807365676f5b2ba6f18491753a673e6a9c5913bd542fe1a \
|
||||
# --hash:sha256=cda3d6c27e69a9d04eb96db6b4b96fbe7facdd11dc2b9a82fe3c65b84b40fe44 \
|
||||
# --hash:sha256=7ededfdb65b4eb282a7cc1600c6f5b4f483b39a70b3460c2f4651ee8fc431f77 \
|
||||
# --hash:sha256=86a61008a8ab5f8ca973bd7e7b1d031c89637257dcf7215bff1913f17d3c596f \
|
||||
# --hash:sha256=1d6af33e40383dba0c3ee26eee3e501e805fe42537dd0096788190bbc8fd7aae \
|
||||
# --hash:sha256=6d08ad35322a5969dfd8ef5af7ff4cdf625d6a7bfa8e915b77f5935f58e1c7b1 \
|
||||
# --hash:sha256=99b7e0c186c5b84d80de6e7b70359b6fc456c02bd2b31fc598140fbc6618d651 \
|
||||
# --hash:sha256=be967c38c4e33f66823d10fb5efca42a0a23269459ce41239c173ccc114b603e \
|
||||
# --hash:sha256=a34d7431e30c6d61c22b92d51224ea34d68be51aa42ec95a053b7f19be3fef0d \
|
||||
# --hash:sha256=be76281c1c7f24d44e3415787d2a05688f6bbda2dc9bba92155ae3ca0d6716e7
|
||||
|
||||
# pure Python packages
|
||||
Paste==2.0.2 --hash:sha256=4e7bb2d8cbdc47ab46e4af0cb61d2af91fccc620a08415d9c4da9e499f0455fd
|
||||
PasteDeploy==1.5.2 --hash:sha256=3922127d3acc6e274a800978b9293c874b3ef4ac2eb8bf485e2c85b22d1f260a
|
||||
docutils==0.12 --hash:sha256=732dfc2d706ea390c264bc69110d3d6c7c3a520628a052ccc5998466f95d5c29
|
||||
wchartype==0.1 --hash:sha256=2932471fe3a4e5cac4539c1b49bbc2bbd24ec3f00532c7f27c80b7756fdc177d
|
||||
repoze.lru==0.6 --hash:sha256=731cc0b0a184c9fd270a4f29d9635099bb0398823e9a1a39bf4f488d1ead57b3
|
||||
Routes==2.2 --hash:sha256=1d61dc9f1bbd86504de221568743133fbdfeb70f11cee4222cef72aa108e834c
|
||||
WebOb==1.4.1 --hash:sha256=dc3c45ac0b56a3c65f47f1da6c23760dfe0139e8a84caaf1cfc9276b3e10875a
|
||||
WebHelpers==1.3 --hash:sha256=8969ec3fb851872096067a805d512c3bed1952e6fc66f1ef1d1c6a7470937688
|
||||
Mako==1.0.2 --hash:sha256=d3f372cbc2e7de080b5f7056d160f3ac8279353a2ea8f1ef8fd5b0cf0a6a3b17
|
||||
pytz==2015.4 --hash:sha256=3bec70eef120ad0bf9143e59bbf36715ec1232fb0550ae2b8aa6c107aacfa6f2
|
||||
Babel==2.0 --hash:sha256=aa725635ef189f77b6b0579efe1e91602d7cf63a31f6dd719a88ee53642bb5ab
|
||||
Beaker==1.7.0 --hash:sha256=334427853ac291e4ecd1e03addb48e231681ab9b6c2bc793c0f0fb98024b70b1
|
||||
|
||||
# Cheetah and dependencies
|
||||
Cheetah==2.4.4 --hash:sha256=24cf67789b7a9f1e0a55cba266b6aad16e97aaf25810fd6f2f7e7b36005c1161 \
|
||||
--hash:sha256=30c6dd32c066f483462cebc7fc37feb454d6a3d35e8b599da17624b2541761ab \
|
||||
--hash:sha256=fcbff7d96509419cbcefa231d6fee4aca98d2f04f8339848c19da3e82aebcf27 \
|
||||
--hash:sha256=5c758550b8170b01e016b75ec05dbd2c32b56513d6e1ef9177c5290f4e166ad2 \
|
||||
--hash:sha256=6aaeef7f742df6a23c4132bb33000196053b661a150fdd98311f25f09d3730c1 \
|
||||
--hash:sha256=469e7ddc2f4a9b147b2b5c258fc9f97cee9842790c1849b941bae165b390da92 \
|
||||
--hash:sha256=75f05eda3b16c621b5b570f9c5b317f6ea94b01296b9e1ef2583560d153578bd \
|
||||
--hash:sha256=6da983e9d189a3c389e98506871ff836a83df1792dba5e4a684d27d948402d7a \
|
||||
--hash:sha256=55b0c2696eb321415a9eca86303e3c359dee550d7f6fc719bc960f23422d2290 \
|
||||
--hash:sha256=2caf567b6cdd54f806ce12d98302e380d4bbbed8990663f9bce52d69358fc488
|
||||
Markdown==2.6.3 --hash:sha256=59417f5eb3dace08309d81e48fc903217d12d66677f367674b22c317b0f04284
|
||||
|
||||
# BioBlend and dependencies
|
||||
bioblend==0.6.1 --hash:sha256=f5eea1f6c31264ef7bfab8c70deac2b9229a10e5c56508a6542f5643ad9e2a5b
|
||||
boto==2.38.0 --hash:sha256=1760584368da0c3861dbed448dcb439334ce831044262a5ca5188167f8bba585
|
||||
requests==2.8.1 --hash:sha256=70e285122c97b1d104824482cb929246b2b8a2b9858897c4fab3acec83f1e03c
|
||||
requests-toolbelt==0.4.0 --hash:sha256=94694e32845b84ed2186fdf56219b949582ebd08dc3abc55c0549958f2029643
|
||||
|
||||
# kombu and dependencies
|
||||
kombu==3.0.30 --hash:sha256=562010f0deb1f04e3abd154b0ef5e246d606b54cb2c5f29e8c4651b354d0b082 \
|
||||
--hash:sha256=5baff23a2b2d78eecb7c97700ea359ab80744c719e311fb446513d7b72ddbc96
|
||||
amqp==1.4.8 --hash:sha256=c7874d845c9bdffbf754ce84f105a1b8c7a6cffb61f362ac67591536ba8c0c1a \
|
||||
--hash:sha256=caada1c29d5e73e13ed8706442ee0fbb1440de9b6fca4df12fc8ff59dd61f6f6
|
||||
anyjson==0.3.3 --hash:sha256=2c84f23be20e3c465151a55917b8e38a04c579394057e232c16fb5ca0c6ae108
|
||||
|
||||
# sqlalchemy-migrate and dependencies
|
||||
sqlalchemy-migrate==0.10.0 --hash:sha256=2aaa4e7070c8447d564f1c173937c2c5a45f889eb31a0fc80add5fc175c45a5e
|
||||
decorator==4.0.2 --hash:sha256=d8c3f7e18efba558084648d6dd6c6b0850e6f5c08c392975ae196c4b4eb7be2a
|
||||
Tempita==0.5.3dev --hash:sha256=df0c6513e565b213733b3f8bf7bcca75998f166042692e1712e3fe36568db234
|
||||
sqlparse==0.1.16 --hash:sha256=221d383f1236f9c05aadd2c4edf4274144279ad06821d7d9bf5a70751157f75d
|
||||
pbr==1.8.0 --hash:sha256=355a0c2ba71120dce1c522387e494c60eb4f44fa9d03067cb9816187e6e803e9
|
||||
# six is also a Pulsar client dep
|
||||
six==1.9.0 --hash:sha256=cf806ab65d5e16561df30c2cea2fb2cf3e6aa82e48f22036dff177e20f61e188
|
||||
Parsley==1.3 --hash:sha256=32fd648334146e4005dae41d559d32edfff9f3d5f503f8b5d233dbfe3a15a28b
|
||||
nose==1.3.7 --hash:sha256=f36054c5786e84ff6b131f3249a3cce82787f1a930ab053287c0edaa9f840d0f
|
||||
SVGFig==1.1.6 --hash:sha256=300cf4b37b4773498d4ea96c703cdb5f09215978b02828dadb786fb248e0b54b
|
||||
|
||||
# Fabric and dependencies
|
||||
Fabric==1.10.2 --hash:sha256=8fe1eb0b0f271e2d41445e7da4470548d3bdf882aab1c1f143505c599996793b
|
||||
paramiko==1.15.2 --hash:sha256=c92b168c8db94a9e1362f3fc27bc21e8c20794885bf2f7d303b5ad717c044ebc
|
||||
ecdsa==0.13 --hash:sha256=89f149066e4a1e419892cef830fd0db85c227d5d427f7075422ace83429e2d26
|
||||
# pycrypto, but it is a direct Galaxy dependency as well
|
||||
|
||||
# Can't use Whoosh latest due to a bug but need to backport a bugfix from a
|
||||
# newer release.
|
||||
#
|
||||
# https://bitbucket.org/mchaput/whoosh/pull-requests/50/fix-lru-thread-safety/diff
|
||||
Whoosh==2.4.1+gx1 --hash:sha256=98897e796c048810d71f7f4fc174914869f1b3b77f44e5a19a5e649b078d5e0e \
|
||||
--hash:sha256=5ec3c22e782c86e981fab62a24ac9feea09e42c43b763a6493c78b82a3b6e3fd
|
||||
|
||||
# Flexible BAM index naming
|
||||
pysam==0.8.3+gx1 --hash:sha256=020aa9101579ac1e82a194fdb08f49f517c634911409e9a2cda4d0a1c72a8c7c \
|
||||
--hash:sha256=1a3d86849b9bd962979b65aaa9af236030dcc1db40296c88d2aa436a0c9df79b \
|
||||
--hash:sha256=0fc55fb252eb0e7914679e9e22672fdc6a1e09804cbcc62769f004ebbed9b4c1 \
|
||||
--hash:sha256=dde8f5037661d7be42e2c3f50c01566dcaedbf2f88133a3bb50c6ae3f75e6e13 \
|
||||
--hash:sha256=7809fd926a071519c0a2b220346e45c094577877e5b2adba2903e7b52490c736 \
|
||||
--hash:sha256=021070ed70a89e19eee6a989933d69d0bdb076c02342e2987bb5fab43f63ad17 \
|
||||
--hash:sha256=374ea868bf64daa4665e8743db1be2e88712953a923020225f57a589b790537c \
|
||||
--hash:sha256=9884b6904face1977649847261e7c984120adaa169a0d62e07820a44c71e18c5 \
|
||||
--hash:sha256=873b81951e9d572b53ab4c7a0d3ef915f7d0e1db5f75603d8861cf1d3810491e \
|
||||
--hash:sha256=37d0ba3880b5a517f354281159f6751f6f9f1c1074ea48bf5f4c424e6ec488dd \
|
||||
--hash:sha256=db99cb20cb5e07998b2acfd29e34c367ef408a184a7b3150586212175a0719bf \
|
||||
--hash:sha256=a1fcb2a6459b799bff7a046e190452b151c5985dea404eaee82bd645b1bfe34d \
|
||||
--hash:sha256=306e4d900dfb582cf87bc21904e2193ef81db76173e976b74152c95ddd93bdc6 \
|
||||
--hash:sha256=2341438d636b8e3cb51b219aab1cc909142d3af176042d12b128d4177682b1ab \
|
||||
--hash:sha256=0f33df9eba7b079b7489ac3dd908a6e44b0e98d094e633b29035d33bfc990b9e \
|
||||
--hash:sha256=faa8aae3f8f105c5c823a7d570dd3caba31ece69b8f3325106435b9f1fcb68d2 \
|
||||
--hash:sha256=2db995758d666c51fecf11cbee1afda357477e01077aacf68ae0c00304c7bc51 \
|
||||
--hash:sha256=2de7a2098f64672d0396ac727633285f3562f804e7845e105ee19da544d7da8a
|
||||
@@ -1,170 +1,69 @@
|
||||
# packages with C extensions
|
||||
bx-python==0.7.3 --hash:sha256=0a0fd962edd0f9afdf5d7ccbdf46dc220a0cb652073a93411dd6f7f649f07d91 \
|
||||
--hash:sha256=46dc3042c7e475363830fa92d4a613ae10b58db7f114ff8193d2ee0bc3c4607e \
|
||||
--hash:sha256=b93a9378a5d0e29ea8a13e026c170f48bf1f8316a39c342b1eb54f557b4fb3c4 \
|
||||
--hash:sha256=d06c7bf0ae7f019521aeb5ffe4df48bb5fdd4d75d7ad00e0059b997c4f13ca3a \
|
||||
--hash:sha256=05d0ab8fd13319d5ef9edb246dc6805640ea7574bb885a0b8607474271ac5793 \
|
||||
--hash:sha256=5a026869227a6464eba23835765a36ffc2910f7af51b81f672a97c0d005e04a3 \
|
||||
--hash:sha256=85be43a6b94f0c841d9954f820133db35067854504c1de87dd0089bb06eca18d \
|
||||
--hash:sha256=d085824eb33c54d333b99dca29b49890457a8263f431b54b17ae3052be191d2b \
|
||||
--hash:sha256=41bcf85b9be9f61ba7c7bae48c5a5ae3251868a1b25f02b6eb93b29bcabfd00c \
|
||||
--hash:sha256=c9b71aee26ee85fbcbb3060109d79531bfa8991f4924bdcfed63d909a5937290
|
||||
MarkupSafe==0.23 --hash:sha256=3a79d9650b7e79943be51a045c7c39a77ebbe9a337e8af51a5575e39332dce87 \
|
||||
--hash:sha256=e0a4155493d1cfa72e985dbe1660a44d64a173282801563956e061b24371266a \
|
||||
--hash:sha256=147013ed157f1423a0d0047043c6bbccbef31a52d82e2a10dfc3c6de9392765c \
|
||||
--hash:sha256=d25d14cb01284aed33690b85bfde8de206ffcfdc52351588bcf17480839bef6f \
|
||||
--hash:sha256=29958f81958e0dd9f5dd36d52f2ac549d875dde3559b783578118c9005693852 \
|
||||
--hash:sha256=287a1c6b0d2a08cb76be6e584bf119649405f015598cf8b78d4a592cc80700a0 \
|
||||
--hash:sha256=973cadf7b9907f9c81d9b898817d6a485b37325176befec2389fa2ced4c61a51 \
|
||||
--hash:sha256=a365fd3468c86741aec5901f4b07990aaa0b458fb79e9f3557378a63e6d627e9 \
|
||||
--hash:sha256=ba7af558b18ba9c05bb0d36f22a5ea65ee11ba44a6cf8a2950f2f80c08260e11 \
|
||||
--hash:sha256=51bf7f077938c64dd00de6732996ccee8ceba2206c69acfb07f66430ca76372f
|
||||
PyYAML==3.11 --hash:sha256=2912c1fb56c316461d003a8b8f1f41e1ed8387b2e47a4523f8a4eec8aa85e241 \
|
||||
--hash:sha256=f4437443dc014c04ceee8cc94d4165f01ba23643991fd2c6b919f26cf9997474 \
|
||||
--hash:sha256=b62cde962d41377c175831fa3fd6ac41585d2e2111ca4c45a6ee80a832457e92 \
|
||||
--hash:sha256=aad37be9d524ba2dba9a3114b620b2800b40e67e455c9741a5cb81a6a0e882f6 \
|
||||
--hash:sha256=03e0f4ac96599c1d687b080f1610ab0469e8785bb48cfdf860f2076a08ea6406 \
|
||||
--hash:sha256=7dc97b5b1b920f6bbe0e47cfa6ff112f6eede35924a63354f80d672354f25160 \
|
||||
--hash:sha256=ceb5dccec2045d4a864c6e808b397b10830476c44bdc64b80c18bf29e481ba07 \
|
||||
--hash:sha256=9b184a4a7d3d383b39cb73429d3798370facaee4263465b575f243c7ede3f9c3 \
|
||||
--hash:sha256=f90314e2ed46ea2da980aff88b91c3cc8ce93edd4658011dd462a8f28399533b \
|
||||
--hash:sha256=80936dca10b611cd54ca52939aac938d59653830a6a6265bef5d11896de8e249
|
||||
SQLAlchemy==1.0.8 --hash:sha256=3c357f36c141205cea2b5ec4c4e9885602452fea06428d6c20596c66c9a43243 \
|
||||
--hash:sha256=17fad7f37f902dbec37ca2777af3021f9a4ed31079d64f7f888e7b29517240a3 \
|
||||
--hash:sha256=e177904a384b9bc68914afb32a6ed2cc73ed7787444e3e1fdf85e3b9cfe5f847 \
|
||||
--hash:sha256=91ed10baf56b6e29665f2b9fcb0c690afc6cc2c2e8e19c7f92b58092a4002e14 \
|
||||
--hash:sha256=f5d6156d1d7865cd23b76ddad3f53ec07a3009a2cd8082a829cd1f24b366db5c \
|
||||
--hash:sha256=3c3f3baf07f868c1c3f86d63dc2efa4455e95d76745f1af561f1ccf0fd9e8c81 \
|
||||
--hash:sha256=a9fb8061aa767ca2ad22983a11e074ac231f44a56709721c60cc1992f2a92350 \
|
||||
--hash:sha256=884b522d2d067cffd103f4e1a5342c678803cd6903da24a3f757b57b00eb188b \
|
||||
--hash:sha256=d5dde66c1603853aebbfbbd74d79c60678f7d98c17abce4be4ebbb697dfd7265 \
|
||||
--hash:sha256=42346d5e91c5e0a5a975352d8af3cfd8b2dad602dd07ec41b6b848ac5205cf5b
|
||||
bx-python==0.7.3
|
||||
MarkupSafe==0.23
|
||||
PyYAML==3.11
|
||||
SQLAlchemy==1.0.8
|
||||
# Mercurial >= 3.5 changed the bundle format, which breaks hg push of TS repositories
|
||||
mercurial==3.4.2 --hash:sha256=7851864b03929c09e07670bf8ab7d59f3529650c935a70d09fb6ce7f6a84e2a5 \
|
||||
--hash:sha256=c23b02b4c32edc2d0799221a9d35abd916fb8a1acd1c07d64c16a235ef677b9e \
|
||||
--hash:sha256=ca72ddfaea681a070b62edcb8e41d58bd24a2b04f73e66658565d189a76f3819 \
|
||||
--hash:sha256=fdad4496f3d7f3e7eced771fa46e21c074989f8437ddf3e0ff6c0eee964e4c29 \
|
||||
--hash:sha256=964a10ec1114dbee3696134bafed676f66038759b73de8593f92616f0e53f371 \
|
||||
--hash:sha256=c6ca6fbe56a8919dfc521e80ab781ab565760d87f4a6170e788d67eb6d69d30f \
|
||||
--hash:sha256=69540318fa9f7a3a0428647003d4f1fa8865d29648e73999b921cae039145ce9 \
|
||||
--hash:sha256=b3de0ee851cf8750f53102437c9a04c7217a8c6f7411030ab3bb5534885f3315 \
|
||||
--hash:sha256=46f67af52c7b1aed68b67daa33c26eafc0fb1d371954d3266fce739446cfcb1d \
|
||||
--hash:sha256=000afb932f0ae45c365cbc0457044e8800811fdad7eee9332b6403b83423ab0a
|
||||
numpy==1.9.2 --hash:sha256=931ce6fd1180a10d58a925b614775706c05de35bca5805e705e1da17e1326862 \
|
||||
--hash:sha256=2340c4b72fdab79ac0fc04bb6629b26eeb93d10f4945b6b1f07d9be8663cab84 \
|
||||
--hash:sha256=83fe34ff67653a639c57cfd04a0d48dda5913250fd95c8466af1d8416b58af59 \
|
||||
--hash:sha256=aeb182d95ddb2dfd81683907be193cfc11c4d0ba744faf457013499fa14a131e \
|
||||
--hash:sha256=d6f1eec7ae250892a2b142af406e43760042badae8e2f168136eace5dd9f05c3 \
|
||||
--hash:sha256=0b0883cac08e3c0999159ba7f34c9b94d26d7d1a2be4017b792145d722646fb7 \
|
||||
--hash:sha256=a124d11b1bec5c517d60ad9414564b5af0828421112d2a00771d22715eab1c3c \
|
||||
--hash:sha256=fabc2f76266de7396e2752baabf287cdd0cc2ed23c1f36ca3c3e8b094e86b87c \
|
||||
--hash:sha256=f83a667d3a38643b3bf6361904cd6c4f2a18d1420c2204c7f269cd36b730c404 \
|
||||
--hash:sha256=dab9bd8c867403340b370ea383c8eda3dc984dd5efc91904a5695e00b1762fc9
|
||||
pycrypto==2.6.1 --hash:sha256=44c20785a1057b8d5e190d6a1847f7c62a8180b9b27a3aca7c3ec920bfb8e7b7 \
|
||||
--hash:sha256=785ba61251cda6e574e0affc4412c346ef615455b81287fe0d6a2e1c5aed5172 \
|
||||
--hash:sha256=5ec40d95520a665843915763c8cbbf40457330bd7ebf2a55ffea1b10a519d12b \
|
||||
--hash:sha256=2cb43f0b293a18e6d5818287150994cf6083b1a9cdff65c19d1150a34aa813bc \
|
||||
--hash:sha256=d48e46f4ccd5c21f3e01bbdbd8e7a86443fc7abdf3f93829c3d04ed684ec22c5 \
|
||||
--hash:sha256=30312bd39f45c91f287f3e6e54c40988d30b1be9a9f332585e3cc00ee5f91554 \
|
||||
--hash:sha256=d129d6d3441efecf2bc7e6b36cb35e99642248d72dbf59b992e6940b9359dabc \
|
||||
--hash:sha256=8884b92835a1c0c763099981d19c990fdc3ae2b7011eb93b1f96e34a346b2d2f \
|
||||
--hash:sha256=7e7e9abc0ae522ae86772d98b7144e0d2ef7791d124936f283680f84fe8cce6c \
|
||||
--hash:sha256=61d3b42eaf89108b8a24c3736fb770f768efb89b1efaf0825efb5c316f0bffdc
|
||||
mercurial==3.4.2
|
||||
numpy==1.9.2
|
||||
pycrypto==2.6.1
|
||||
|
||||
# Install python_lzo if you want to support indexed access to lzo-compressed
|
||||
# locally cached maf files via bx-python
|
||||
#python_lzo==1.8 --hash:sha256=638b38bc1d83561a9807365676f5b2ba6f18491753a673e6a9c5913bd542fe1a \
|
||||
# --hash:sha256=cda3d6c27e69a9d04eb96db6b4b96fbe7facdd11dc2b9a82fe3c65b84b40fe44 \
|
||||
# --hash:sha256=7ededfdb65b4eb282a7cc1600c6f5b4f483b39a70b3460c2f4651ee8fc431f77 \
|
||||
# --hash:sha256=86a61008a8ab5f8ca973bd7e7b1d031c89637257dcf7215bff1913f17d3c596f \
|
||||
# --hash:sha256=1d6af33e40383dba0c3ee26eee3e501e805fe42537dd0096788190bbc8fd7aae \
|
||||
# --hash:sha256=6d08ad35322a5969dfd8ef5af7ff4cdf625d6a7bfa8e915b77f5935f58e1c7b1 \
|
||||
# --hash:sha256=99b7e0c186c5b84d80de6e7b70359b6fc456c02bd2b31fc598140fbc6618d651 \
|
||||
# --hash:sha256=be967c38c4e33f66823d10fb5efca42a0a23269459ce41239c173ccc114b603e \
|
||||
# --hash:sha256=a34d7431e30c6d61c22b92d51224ea34d68be51aa42ec95a053b7f19be3fef0d \
|
||||
# --hash:sha256=be76281c1c7f24d44e3415787d2a05688f6bbda2dc9bba92155ae3ca0d6716e7
|
||||
#python_lzo==1.8
|
||||
|
||||
# pure Python packages
|
||||
Paste==2.0.2 --hash:sha256=4e7bb2d8cbdc47ab46e4af0cb61d2af91fccc620a08415d9c4da9e499f0455fd
|
||||
PasteDeploy==1.5.2 --hash:sha256=3922127d3acc6e274a800978b9293c874b3ef4ac2eb8bf485e2c85b22d1f260a
|
||||
docutils==0.12 --hash:sha256=732dfc2d706ea390c264bc69110d3d6c7c3a520628a052ccc5998466f95d5c29
|
||||
wchartype==0.1 --hash:sha256=2932471fe3a4e5cac4539c1b49bbc2bbd24ec3f00532c7f27c80b7756fdc177d
|
||||
repoze.lru==0.6 --hash:sha256=731cc0b0a184c9fd270a4f29d9635099bb0398823e9a1a39bf4f488d1ead57b3
|
||||
Routes==2.2 --hash:sha256=1d61dc9f1bbd86504de221568743133fbdfeb70f11cee4222cef72aa108e834c
|
||||
WebOb==1.4.1 --hash:sha256=dc3c45ac0b56a3c65f47f1da6c23760dfe0139e8a84caaf1cfc9276b3e10875a
|
||||
WebHelpers==1.3 --hash:sha256=8969ec3fb851872096067a805d512c3bed1952e6fc66f1ef1d1c6a7470937688
|
||||
Mako==1.0.2 --hash:sha256=d3f372cbc2e7de080b5f7056d160f3ac8279353a2ea8f1ef8fd5b0cf0a6a3b17
|
||||
pytz==2015.4 --hash:sha256=3bec70eef120ad0bf9143e59bbf36715ec1232fb0550ae2b8aa6c107aacfa6f2
|
||||
Babel==2.0 --hash:sha256=aa725635ef189f77b6b0579efe1e91602d7cf63a31f6dd719a88ee53642bb5ab
|
||||
Beaker==1.7.0 --hash:sha256=334427853ac291e4ecd1e03addb48e231681ab9b6c2bc793c0f0fb98024b70b1
|
||||
Paste==2.0.2
|
||||
PasteDeploy==1.5.2
|
||||
docutils==0.12
|
||||
wchartype==0.1
|
||||
repoze.lru==0.6
|
||||
Routes==2.2
|
||||
WebOb==1.4.1
|
||||
WebHelpers==1.3
|
||||
Mako==1.0.2
|
||||
pytz==2015.4
|
||||
Babel==2.0
|
||||
Beaker==1.7.0
|
||||
|
||||
# Cheetah and dependencies
|
||||
Cheetah==2.4.4 --hash:sha256=24cf67789b7a9f1e0a55cba266b6aad16e97aaf25810fd6f2f7e7b36005c1161 \
|
||||
--hash:sha256=30c6dd32c066f483462cebc7fc37feb454d6a3d35e8b599da17624b2541761ab \
|
||||
--hash:sha256=fcbff7d96509419cbcefa231d6fee4aca98d2f04f8339848c19da3e82aebcf27 \
|
||||
--hash:sha256=5c758550b8170b01e016b75ec05dbd2c32b56513d6e1ef9177c5290f4e166ad2 \
|
||||
--hash:sha256=6aaeef7f742df6a23c4132bb33000196053b661a150fdd98311f25f09d3730c1 \
|
||||
--hash:sha256=469e7ddc2f4a9b147b2b5c258fc9f97cee9842790c1849b941bae165b390da92 \
|
||||
--hash:sha256=75f05eda3b16c621b5b570f9c5b317f6ea94b01296b9e1ef2583560d153578bd \
|
||||
--hash:sha256=6da983e9d189a3c389e98506871ff836a83df1792dba5e4a684d27d948402d7a \
|
||||
--hash:sha256=55b0c2696eb321415a9eca86303e3c359dee550d7f6fc719bc960f23422d2290 \
|
||||
--hash:sha256=2caf567b6cdd54f806ce12d98302e380d4bbbed8990663f9bce52d69358fc488
|
||||
Markdown==2.6.3 --hash:sha256=59417f5eb3dace08309d81e48fc903217d12d66677f367674b22c317b0f04284
|
||||
Cheetah==2.4.4
|
||||
Markdown==2.6.3
|
||||
|
||||
# BioBlend and dependencies
|
||||
bioblend==0.6.1 --hash:sha256=f5eea1f6c31264ef7bfab8c70deac2b9229a10e5c56508a6542f5643ad9e2a5b
|
||||
boto==2.38.0 --hash:sha256=1760584368da0c3861dbed448dcb439334ce831044262a5ca5188167f8bba585
|
||||
requests==2.8.1 --hash:sha256=70e285122c97b1d104824482cb929246b2b8a2b9858897c4fab3acec83f1e03c
|
||||
requests-toolbelt==0.4.0 --hash:sha256=94694e32845b84ed2186fdf56219b949582ebd08dc3abc55c0549958f2029643
|
||||
bioblend==0.6.1
|
||||
boto==2.38.0
|
||||
requests==2.8.1
|
||||
requests-toolbelt==0.4.0
|
||||
|
||||
# kombu and dependencies
|
||||
kombu==3.0.30 --hash:sha256=562010f0deb1f04e3abd154b0ef5e246d606b54cb2c5f29e8c4651b354d0b082 \
|
||||
--hash:sha256=5baff23a2b2d78eecb7c97700ea359ab80744c719e311fb446513d7b72ddbc96
|
||||
amqp==1.4.8 --hash:sha256=c7874d845c9bdffbf754ce84f105a1b8c7a6cffb61f362ac67591536ba8c0c1a \
|
||||
--hash:sha256=caada1c29d5e73e13ed8706442ee0fbb1440de9b6fca4df12fc8ff59dd61f6f6
|
||||
anyjson==0.3.3 --hash:sha256=2c84f23be20e3c465151a55917b8e38a04c579394057e232c16fb5ca0c6ae108
|
||||
kombu==3.0.30
|
||||
amqp==1.4.8
|
||||
anyjson==0.3.3
|
||||
|
||||
# sqlalchemy-migrate and dependencies
|
||||
sqlalchemy-migrate==0.10.0 --hash:sha256=2aaa4e7070c8447d564f1c173937c2c5a45f889eb31a0fc80add5fc175c45a5e
|
||||
decorator==4.0.2 --hash:sha256=d8c3f7e18efba558084648d6dd6c6b0850e6f5c08c392975ae196c4b4eb7be2a
|
||||
Tempita==0.5.3dev --hash:sha256=df0c6513e565b213733b3f8bf7bcca75998f166042692e1712e3fe36568db234
|
||||
sqlparse==0.1.16 --hash:sha256=221d383f1236f9c05aadd2c4edf4274144279ad06821d7d9bf5a70751157f75d
|
||||
pbr==1.8.0 --hash:sha256=355a0c2ba71120dce1c522387e494c60eb4f44fa9d03067cb9816187e6e803e9
|
||||
sqlalchemy-migrate==0.10.0
|
||||
decorator==4.0.2
|
||||
Tempita==0.5.3dev
|
||||
sqlparse==0.1.16
|
||||
pbr==1.8.0
|
||||
# six is also a Pulsar client dep
|
||||
six==1.9.0 --hash:sha256=cf806ab65d5e16561df30c2cea2fb2cf3e6aa82e48f22036dff177e20f61e188
|
||||
Parsley==1.3 --hash:sha256=32fd648334146e4005dae41d559d32edfff9f3d5f503f8b5d233dbfe3a15a28b
|
||||
nose==1.3.7 --hash:sha256=f36054c5786e84ff6b131f3249a3cce82787f1a930ab053287c0edaa9f840d0f
|
||||
SVGFig==1.1.6 --hash:sha256=300cf4b37b4773498d4ea96c703cdb5f09215978b02828dadb786fb248e0b54b
|
||||
six==1.9.0
|
||||
Parsley==1.3
|
||||
nose==1.3.7
|
||||
SVGFig==1.1.6
|
||||
|
||||
# Fabric and dependencies
|
||||
Fabric==1.10.2 --hash:sha256=8fe1eb0b0f271e2d41445e7da4470548d3bdf882aab1c1f143505c599996793b
|
||||
paramiko==1.15.2 --hash:sha256=c92b168c8db94a9e1362f3fc27bc21e8c20794885bf2f7d303b5ad717c044ebc
|
||||
ecdsa==0.13 --hash:sha256=89f149066e4a1e419892cef830fd0db85c227d5d427f7075422ace83429e2d26
|
||||
Fabric==1.10.2
|
||||
paramiko==1.15.2
|
||||
ecdsa==0.13
|
||||
# pycrypto, but it is a direct Galaxy dependency as well
|
||||
|
||||
# Can't use Whoosh latest due to a bug but need to backport a bugfix from a
|
||||
# newer release.
|
||||
#
|
||||
# https://bitbucket.org/mchaput/whoosh/pull-requests/50/fix-lru-thread-safety/diff
|
||||
Whoosh==2.4.1+gx1 --hash:sha256=98897e796c048810d71f7f4fc174914869f1b3b77f44e5a19a5e649b078d5e0e \
|
||||
--hash:sha256=5ec3c22e782c86e981fab62a24ac9feea09e42c43b763a6493c78b82a3b6e3fd
|
||||
Whoosh==2.4.1+gx1
|
||||
|
||||
# Flexible BAM index naming
|
||||
pysam==0.8.3+gx1 --hash:sha256=020aa9101579ac1e82a194fdb08f49f517c634911409e9a2cda4d0a1c72a8c7c \
|
||||
--hash:sha256=1a3d86849b9bd962979b65aaa9af236030dcc1db40296c88d2aa436a0c9df79b \
|
||||
--hash:sha256=0fc55fb252eb0e7914679e9e22672fdc6a1e09804cbcc62769f004ebbed9b4c1 \
|
||||
--hash:sha256=dde8f5037661d7be42e2c3f50c01566dcaedbf2f88133a3bb50c6ae3f75e6e13 \
|
||||
--hash:sha256=7809fd926a071519c0a2b220346e45c094577877e5b2adba2903e7b52490c736 \
|
||||
--hash:sha256=021070ed70a89e19eee6a989933d69d0bdb076c02342e2987bb5fab43f63ad17 \
|
||||
--hash:sha256=374ea868bf64daa4665e8743db1be2e88712953a923020225f57a589b790537c \
|
||||
--hash:sha256=9884b6904face1977649847261e7c984120adaa169a0d62e07820a44c71e18c5 \
|
||||
--hash:sha256=873b81951e9d572b53ab4c7a0d3ef915f7d0e1db5f75603d8861cf1d3810491e \
|
||||
--hash:sha256=37d0ba3880b5a517f354281159f6751f6f9f1c1074ea48bf5f4c424e6ec488dd \
|
||||
--hash:sha256=db99cb20cb5e07998b2acfd29e34c367ef408a184a7b3150586212175a0719bf \
|
||||
--hash:sha256=a1fcb2a6459b799bff7a046e190452b151c5985dea404eaee82bd645b1bfe34d \
|
||||
--hash:sha256=306e4d900dfb582cf87bc21904e2193ef81db76173e976b74152c95ddd93bdc6 \
|
||||
--hash:sha256=2341438d636b8e3cb51b219aab1cc909142d3af176042d12b128d4177682b1ab \
|
||||
--hash:sha256=0f33df9eba7b079b7489ac3dd908a6e44b0e98d094e633b29035d33bfc990b9e \
|
||||
--hash:sha256=faa8aae3f8f105c5c823a7d570dd3caba31ece69b8f3325106435b9f1fcb68d2 \
|
||||
--hash:sha256=2db995758d666c51fecf11cbee1afda357477e01077aacf68ae0c00304c7bc51 \
|
||||
--hash:sha256=2de7a2098f64672d0396ac727633285f3562f804e7845e105ee19da544d7da8a
|
||||
pysam==0.8.3+gx1
|
||||
|
||||
@@ -43,6 +43,9 @@ log = logging.getLogger( __name__ )
|
||||
# and should eventually become API'd
|
||||
TOOL_PROVIDED_JOB_METADATA_FILE = 'galaxy.json'
|
||||
|
||||
# Override with config.default_job_shell.
|
||||
DEFAULT_JOB_SHELL = '/bin/sh'
|
||||
|
||||
|
||||
class JobDestination( Bunch ):
|
||||
"""
|
||||
@@ -55,6 +58,7 @@ class JobDestination( Bunch ):
|
||||
self['runner'] = None
|
||||
self['legacy'] = False
|
||||
self['converted'] = False
|
||||
self['shell'] = None
|
||||
self['env'] = []
|
||||
self['resubmit'] = []
|
||||
# dict is appropriate (rather than a bunch) since keys may not be valid as attributes
|
||||
@@ -785,6 +789,10 @@ class JobWrapper( object ):
|
||||
def get_parallelism(self):
|
||||
return self.tool.parallelism
|
||||
|
||||
@property
|
||||
def shell(self):
|
||||
return self.job_destination.shell or getattr(self.app.config, 'default_job_shell', DEFAULT_JOB_SHELL)
|
||||
|
||||
@property
|
||||
def commands_in_new_shell(self):
|
||||
return self.app.config.commands_in_new_shell
|
||||
|
||||
@@ -1,16 +1,19 @@
|
||||
from os import getcwd
|
||||
from os import chmod
|
||||
from os.path import join
|
||||
from os.path import abspath
|
||||
|
||||
from galaxy import util
|
||||
from galaxy.jobs.runners.util.job_script import (
|
||||
INTEGRITY_INJECTION,
|
||||
write_script,
|
||||
check_script_integrity,
|
||||
)
|
||||
|
||||
from logging import getLogger
|
||||
log = getLogger( __name__ )
|
||||
|
||||
CAPTURE_RETURN_CODE = "return_code=$?"
|
||||
YIELD_CAPTURED_CODE = 'sh -c "exit $return_code"'
|
||||
DEFAULT_SHELL = "/bin/sh"
|
||||
|
||||
|
||||
def build_command(
|
||||
@@ -19,7 +22,7 @@ def build_command(
|
||||
container=None,
|
||||
include_metadata=False,
|
||||
include_work_dir_outputs=True,
|
||||
remote_command_params={}
|
||||
remote_command_params={},
|
||||
):
|
||||
"""
|
||||
Compose the sequence of commands necessary to execute a job. This will
|
||||
@@ -30,6 +33,7 @@ def build_command(
|
||||
- command line taken from job wrapper
|
||||
- commands to set metadata (if include_metadata is True)
|
||||
"""
|
||||
shell = job_wrapper.shell
|
||||
base_command_line = job_wrapper.get_command_line()
|
||||
# job_id = job_wrapper.job_id
|
||||
# log.debug( 'Tool evaluation for job (%s) produced command-line: %s' % ( job_id, base_command_line ) )
|
||||
@@ -52,7 +56,7 @@ def build_command(
|
||||
__handle_dependency_resolution(commands_builder, job_wrapper, remote_command_params)
|
||||
|
||||
if container or job_wrapper.commands_in_new_shell:
|
||||
externalized_commands = __externalize_commands(job_wrapper, commands_builder, remote_command_params)
|
||||
externalized_commands = __externalize_commands(job_wrapper, shell, commands_builder, remote_command_params)
|
||||
if container:
|
||||
# Stop now and build command before handling metadata and copying
|
||||
# working directory files back. These should always happen outside
|
||||
@@ -76,17 +80,18 @@ def build_command(
|
||||
return commands_builder.build()
|
||||
|
||||
|
||||
def __externalize_commands(job_wrapper, commands_builder, remote_command_params, script_name="tool_script.sh"):
|
||||
def __externalize_commands(job_wrapper, shell, commands_builder, remote_command_params, script_name="tool_script.sh"):
|
||||
local_container_script = join( job_wrapper.working_directory, script_name )
|
||||
tool_commands = commands_builder.build()
|
||||
with open( local_container_script, "w" ) as f:
|
||||
script_contents = u"#!%s\n%s" % (DEFAULT_SHELL, tool_commands)
|
||||
f.write(script_contents.encode(util.DEFAULT_ENCODING))
|
||||
chmod( local_container_script, 0755 )
|
||||
|
||||
config = job_wrapper.app.config
|
||||
integrity_injection = ""
|
||||
if check_script_integrity(config):
|
||||
integrity_injection = INTEGRITY_INJECTION
|
||||
script_contents = u"#!%s\n%s%s" % (shell, integrity_injection, tool_commands)
|
||||
write_script(local_container_script, script_contents, config)
|
||||
commands = local_container_script
|
||||
if 'working_directory' in remote_command_params:
|
||||
commands = "%s %s" % (DEFAULT_SHELL, join(remote_command_params['working_directory'], script_name))
|
||||
commands = "%s %s" % (shell, join(remote_command_params['working_directory'], script_name))
|
||||
log.info("Built script [%s] for tool command[%s]" % (local_container_script, tool_commands))
|
||||
return commands
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ from galaxy.util import in_directory
|
||||
from galaxy.util import ParamsWithSpecs
|
||||
from galaxy.util import ExecutionTimer
|
||||
from galaxy.util.bunch import Bunch
|
||||
from galaxy.jobs.runners.util.job_script import write_script
|
||||
from galaxy.jobs.runners.util.job_script import job_script
|
||||
from galaxy.jobs.runners.util.env import env_to_statement
|
||||
|
||||
@@ -166,7 +167,7 @@ class BaseJobRunner( object ):
|
||||
job_wrapper.runner_command_line = self.build_command_line(
|
||||
job_wrapper,
|
||||
include_metadata=include_metadata,
|
||||
include_work_dir_outputs=include_work_dir_outputs
|
||||
include_work_dir_outputs=include_work_dir_outputs,
|
||||
)
|
||||
except:
|
||||
log.exception("(%s) Failure preparing job" % job_id)
|
||||
@@ -297,6 +298,7 @@ class BaseJobRunner( object ):
|
||||
env_setup_commands=env_setup_commands,
|
||||
working_directory=os.path.abspath( job_wrapper.working_directory ),
|
||||
command=command_line,
|
||||
shell=job_wrapper.shell,
|
||||
)
|
||||
# Additional logging to enable if debugging from_work_dir handling, metadata
|
||||
# commands, etc... (or just peak in the job script.)
|
||||
@@ -306,41 +308,7 @@ class BaseJobRunner( object ):
|
||||
return job_script(**options)
|
||||
|
||||
def write_executable_script( self, path, contents, mode=0o755 ):
|
||||
with open( path, 'w' ) as f:
|
||||
if isinstance(contents, unicode):
|
||||
contents = contents.encode("UTF-8")
|
||||
f.write( contents )
|
||||
os.chmod( path, mode )
|
||||
self._handle_script_integrity( path )
|
||||
|
||||
def _handle_script_integrity( self, path ):
|
||||
if not getattr( self.app.config, "check_job_script_integrity", True ):
|
||||
return
|
||||
|
||||
script_integrity_verified = False
|
||||
for i in range(10):
|
||||
try:
|
||||
proc = subprocess.Popen( [path], shell=True, env={"ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ": "1"} )
|
||||
proc.wait()
|
||||
if proc.returncode == 42:
|
||||
script_integrity_verified = True
|
||||
break
|
||||
|
||||
# Else we will sync and wait to see if the script becomes
|
||||
# executable.
|
||||
try:
|
||||
# sync file system to avoid "Text file busy" problems.
|
||||
# These have occurred both in Docker containers and on EC2 clusters
|
||||
# under high load.
|
||||
subprocess.check_call(["/bin/sync"])
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep( .25 )
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not script_integrity_verified:
|
||||
raise Exception("Failed to write job script, could not verify job script integrity.")
|
||||
write_script( path, contents, self.app.config, mode=mode )
|
||||
|
||||
def _complete_terminal_job( self, ajs, **kwargs ):
|
||||
if ajs.job_wrapper.get_state() != model.Job.states.DELETED:
|
||||
|
||||
@@ -1,12 +1,6 @@
|
||||
#!/bin/sh
|
||||
|
||||
# The following block can be used by the job creation system
|
||||
# to ensure this script is runnable before running it directly
|
||||
# or submitting it to a cluster manager.
|
||||
if [ -n "$ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ" ]; then
|
||||
exit 42
|
||||
fi
|
||||
#!$shell
|
||||
|
||||
$integrity_injection
|
||||
$headers
|
||||
$slots_statement
|
||||
export GALAXY_SLOTS
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
import os
|
||||
from string import Template
|
||||
import subprocess
|
||||
import time
|
||||
from pkg_resources import resource_string
|
||||
|
||||
from six import text_type
|
||||
from galaxy.util import unicodify
|
||||
|
||||
DEFAULT_SHELL = '/bin/sh'
|
||||
|
||||
DEFAULT_JOB_FILE_TEMPLATE = Template(
|
||||
resource_string(__name__, 'DEFAULT_JOB_FILE_TEMPLATE.sh').decode('UTF-8')
|
||||
)
|
||||
@@ -13,6 +20,19 @@ SLOTS_STATEMENT_SINGLE = """
|
||||
GALAXY_SLOTS="1"
|
||||
"""
|
||||
|
||||
INTEGRITY_INJECTION = """
|
||||
# The following block can be used by the job system
|
||||
# to ensure this script is runnable before actually attempting
|
||||
# to run it.
|
||||
if [ -n "$ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ" ]; then
|
||||
exit 42
|
||||
fi
|
||||
"""
|
||||
|
||||
INTEGRITY_SYNC_COMMAND = "/bin/sync"
|
||||
DEFAULT_INTEGRITY_CHECK = True
|
||||
DEFAULT_INTEGRITY_COUNT = 35
|
||||
DEFAULT_INTEGRITY_SLEEP = .25
|
||||
REQUIRED_TEMPLATE_PARAMS = ['working_directory', 'command', 'exit_code_path']
|
||||
OPTIONAL_TEMPLATE_PARAMS = {
|
||||
'galaxy_lib': None,
|
||||
@@ -22,6 +42,8 @@ OPTIONAL_TEMPLATE_PARAMS = {
|
||||
'slots_statement': SLOTS_STATEMENT_CLUSTER_DEFAULT,
|
||||
'instrument_pre_commands': '',
|
||||
'instrument_post_commands': '',
|
||||
'integrity_injection': INTEGRITY_INJECTION,
|
||||
'shell': DEFAULT_SHELL,
|
||||
}
|
||||
|
||||
|
||||
@@ -67,3 +89,56 @@ def job_script(template=DEFAULT_JOB_FILE_TEMPLATE, **kwds):
|
||||
if not isinstance(template, Template):
|
||||
template = Template(template)
|
||||
return template.safe_substitute(template_params)
|
||||
|
||||
|
||||
def check_script_integrity(config):
|
||||
return getattr(config, "check_job_script_integrity", DEFAULT_INTEGRITY_CHECK)
|
||||
|
||||
|
||||
def write_script(path, contents, config, mode=0o755):
|
||||
with open(path, 'w') as f:
|
||||
if isinstance(contents, text_type):
|
||||
contents = contents.encode("UTF-8")
|
||||
f.write(contents)
|
||||
os.chmod(path, mode)
|
||||
_handle_script_integrity(path, config)
|
||||
|
||||
|
||||
def _handle_script_integrity(path, config):
|
||||
if not check_script_integrity(config):
|
||||
return
|
||||
|
||||
script_integrity_verified = False
|
||||
count = getattr(config, "check_job_script_integrity_count", DEFAULT_INTEGRITY_COUNT)
|
||||
sleep_amt = getattr(config, "check_job_script_integrity_sleep", DEFAULT_INTEGRITY_SLEEP)
|
||||
for i in range(count):
|
||||
try:
|
||||
proc = subprocess.Popen([path], shell=True, env={"ABC_TEST_JOB_SCRIPT_INTEGRITY_XYZ": "1"})
|
||||
proc.wait()
|
||||
if proc.returncode == 42:
|
||||
script_integrity_verified = True
|
||||
break
|
||||
|
||||
# Else we will sync and wait to see if the script becomes
|
||||
# executable.
|
||||
try:
|
||||
# sync file system to avoid "Text file busy" problems.
|
||||
# These have occurred both in Docker containers and on EC2 clusters
|
||||
# under high load.
|
||||
subprocess.check_call(INTEGRITY_SYNC_COMMAND)
|
||||
except Exception:
|
||||
pass
|
||||
time.sleep(sleep_amt)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not script_integrity_verified:
|
||||
raise Exception("Failed to write job script, could not verify job script integrity.")
|
||||
|
||||
|
||||
__all__ = [
|
||||
'check_script_integrity',
|
||||
'job_script',
|
||||
'write_script',
|
||||
'INTEGRITY_INJECTION',
|
||||
]
|
||||
|
||||
@@ -1398,7 +1398,6 @@ class History( object, Dictifiable, UsesAnnotations, HasName ):
|
||||
assert db_session is not None
|
||||
query = db_session.query( content_class ).filter( content_class.table.c.history_id == self.id )
|
||||
query = query.order_by( content_class.table.c.hid.asc() )
|
||||
python_filter = None
|
||||
deleted = galaxy.util.string_as_bool_or_none( kwds.get( 'deleted', None ) )
|
||||
if deleted is not None:
|
||||
query = query.filter( content_class.deleted == deleted )
|
||||
@@ -1411,11 +1410,8 @@ class History( object, Dictifiable, UsesAnnotations, HasName ):
|
||||
if len(ids) < max_in_filter_length:
|
||||
query = query.filter( content_class.id.in_(ids) )
|
||||
else:
|
||||
python_filter = lambda content: content.id in ids
|
||||
if python_filter:
|
||||
return ifilter(python_filter, query)
|
||||
else:
|
||||
return query
|
||||
query = ifilter(lambda content: content.id in ids, query)
|
||||
return query
|
||||
|
||||
def __collection_contents_iter( self, **kwds ):
|
||||
return self.__filter_contents( HistoryDatasetCollectionAssociation, **kwds )
|
||||
@@ -3561,6 +3557,28 @@ class Workflow( object, Dictifiable ):
|
||||
"""
|
||||
return self.top_level_workflow.stored_workflow
|
||||
|
||||
def copy(self):
|
||||
""" Copy a workflow (without user information) for a new
|
||||
StoredWorkflow object.
|
||||
"""
|
||||
copied_workflow = Workflow()
|
||||
copied_workflow.name = self.name
|
||||
copied_workflow.has_cycles = self.has_cycles
|
||||
copied_workflow.has_errors = self.has_errors
|
||||
|
||||
# Map old step ids to new steps
|
||||
step_mapping = {}
|
||||
copied_steps = []
|
||||
for step in self.steps:
|
||||
copied_step = WorkflowStep()
|
||||
copied_steps.append(copied_step)
|
||||
step_mapping[step.id] = copied_step
|
||||
|
||||
for old_step, new_step in zip(self.steps, copied_steps):
|
||||
old_step.copy_to(new_step, step_mapping)
|
||||
copied_workflow.steps = copied_steps
|
||||
return copied_workflow
|
||||
|
||||
def log_str(self):
|
||||
extra = ""
|
||||
if self.stored_workflow:
|
||||
@@ -3579,8 +3597,9 @@ class WorkflowStep( object ):
|
||||
self.position = None
|
||||
self.input_connections = []
|
||||
self.config = None
|
||||
self.label = None
|
||||
self.uuid = uuid4()
|
||||
self.worklfow_outputs = []
|
||||
self.workflow_outputs = []
|
||||
self._input_connections_by_name = None
|
||||
|
||||
@property
|
||||
@@ -3630,6 +3649,34 @@ class WorkflowStep( object ):
|
||||
break
|
||||
return target_output
|
||||
|
||||
def copy_to(self, copied_step, step_mapping):
|
||||
copied_step.order_index = self.order_index
|
||||
copied_step.type = self.type
|
||||
copied_step.tool_id = self.tool_id
|
||||
copied_step.tool_inputs = self.tool_inputs
|
||||
copied_step.tool_errors = self.tool_errors
|
||||
copied_step.position = self.position
|
||||
copied_step.config = self.config
|
||||
copied_step.label = self.label
|
||||
copied_step.input_connections = copy_list(self.input_connections)
|
||||
|
||||
subworkflow_step_mapping = {}
|
||||
subworkflow = self.subworkflow
|
||||
if subworkflow:
|
||||
copied_subworkflow = subworkflow.copy()
|
||||
copied_step.subworkflow = copied_subworkflow
|
||||
for subworkflow_step, copied_subworkflow_step in zip(subworkflow.steps, copied_subworkflow.steps):
|
||||
subworkflow_step_mapping[subworkflow_step.id] = copied_subworkflow_step
|
||||
|
||||
for old_conn, new_conn in zip(self.input_connections, copied_step.input_connections):
|
||||
# new_conn.input_step = new_
|
||||
new_conn.input_step = step_mapping[old_conn.input_step_id]
|
||||
new_conn.output_step = step_mapping[old_conn.output_step_id]
|
||||
if old_conn.input_subworkflow_step_id:
|
||||
new_conn.input_subworkflow_step = subworkflow_step_mapping[old_conn.input_subworkflow_step_id]
|
||||
|
||||
copied_step.workflow_outputs = copy_list(self.workflow_outputs, copied_step)
|
||||
|
||||
def log_str(self):
|
||||
return "WorkflowStep[index=%d,type=%s]" % (self.order_index, self.type)
|
||||
|
||||
@@ -3657,6 +3704,13 @@ class WorkflowStepConnection( object ):
|
||||
return (self.output_name == WorkflowStepConnection.NON_DATA_CONNECTION and
|
||||
self.input_name == WorkflowStepConnection.NON_DATA_CONNECTION)
|
||||
|
||||
def copy(self):
|
||||
# TODO: handle subworkflow ids...
|
||||
copied_connection = WorkflowStepConnection()
|
||||
copied_connection.output_name = self.output_name
|
||||
copied_connection.input_name = self.input_name
|
||||
return copied_connection
|
||||
|
||||
|
||||
class WorkflowOutput(object):
|
||||
|
||||
@@ -3669,6 +3723,12 @@ class WorkflowOutput(object):
|
||||
else:
|
||||
self.uuid = UUID(str(uuid))
|
||||
|
||||
def copy(self, copied_step):
|
||||
copied_output = WorkflowOutput(copied_step)
|
||||
copied_output.output_name = self.output_name
|
||||
copied_output.label = self.label
|
||||
return copied_output
|
||||
|
||||
|
||||
class StoredWorkflowUserShareAssociation( object ):
|
||||
|
||||
@@ -5021,3 +5081,10 @@ class APIKeys( object ):
|
||||
self.id = id
|
||||
self.user_id = user_id
|
||||
self.key = key
|
||||
|
||||
|
||||
def copy_list(lst, *args, **kwds):
|
||||
if lst is None:
|
||||
return lst
|
||||
else:
|
||||
return list(map(lambda el: el.copy(*args, **kwds), lst))
|
||||
|
||||
@@ -232,7 +232,8 @@ def total_size(o, handlers={}, verbose=False):
|
||||
|
||||
Recipe from: https://code.activestate.com/recipes/577504-compute-memory-footprint-of-an-object-and-its-cont/
|
||||
"""
|
||||
dict_handler = lambda d: chain.from_iterable(d.items())
|
||||
def dict_handler(d):
|
||||
return chain.from_iterable(d.items())
|
||||
all_handlers = { tuple: iter,
|
||||
list: iter,
|
||||
deque: iter,
|
||||
|
||||
@@ -2154,6 +2154,9 @@ class Tool( object, Dictifiable ):
|
||||
def jsonify(v):
|
||||
if isinstance(v, UnvalidatedValue):
|
||||
v = v.value
|
||||
while isinstance( v, UnvalidatedValue ):
|
||||
v = v.value
|
||||
return v
|
||||
|
||||
# check if value is numeric
|
||||
isnumber = False
|
||||
|
||||
@@ -350,7 +350,7 @@ def create_paramfile( trans, uploaded_datasets ):
|
||||
return json_file_path
|
||||
|
||||
|
||||
def create_job( trans, params, tool, json_file_path, data_list, folder=None, history=None ):
|
||||
def create_job( trans, params, tool, json_file_path, data_list, folder=None, history=None, job_params=None ):
|
||||
"""
|
||||
Create the upload job.
|
||||
"""
|
||||
@@ -395,7 +395,10 @@ def create_job( trans, params, tool, json_file_path, data_list, folder=None, his
|
||||
# open( dataset.file_name, "w" ).close()
|
||||
job.object_store_id = object_store_id
|
||||
job.set_state( job.states.NEW )
|
||||
job.set_handler(tool.get_job_handler(None))
|
||||
job.set_handler( tool.get_job_handler( None ) )
|
||||
if job_params:
|
||||
for name, value in job_params.iteritems():
|
||||
job.add_parameter( name, value )
|
||||
trans.sa_session.add( job )
|
||||
trans.sa_session.flush()
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user