diff --git a/.ci/pep8_sources.txt b/.ci/flake8_blacklist.txt similarity index 95% rename from .ci/pep8_sources.txt rename to .ci/flake8_blacklist.txt index 1f2171fa9190..23695ec079cf 100644 --- a/.ci/pep8_sources.txt +++ b/.ci/flake8_blacklist.txt @@ -1,4 +1,7 @@ +.venv/ contrib/ +client/ +database/ doc/patch.py doc/source/conf.py lib/galaxy/model/migrate/versions/ diff --git a/.ci/flake8_wrapper.sh b/.ci/flake8_wrapper.sh index 80fe6c4c3300..4f725cd4845d 100755 --- a/.ci/flake8_wrapper.sh +++ b/.ci/flake8_wrapper.sh @@ -2,7 +2,7 @@ set -e -flake8 --exclude database/,.venv/,`paste -sd, .ci/pep8_sources.txt` . +flake8 --exclude `paste -sd, .ci/flake8_blacklist.txt` . # Look for obviously broken stuff lots more places. flake8 --select=E901,E902,F821,F822,F823,F831 --exclude lib/galaxy/util/pastescript/serve.py,lib/pkg_resources.py lib/ test/{api,unit} diff --git a/client/GruntFile.js b/client/GruntFile.js index acc9fd98f1d4..469e9849755d 100644 --- a/client/GruntFile.js +++ b/client/GruntFile.js @@ -22,5 +22,6 @@ module.exports = function(grunt) { // see the sub directory grunt-tasks/ for individual task definitions grunt.loadTasks( 'grunt-tasks' ); - grunt.registerTask( 'default', [ 'uglify' ] ); + // note: 'handlebars' *not* 'templates' since handlebars doesn't call uglify + grunt.registerTask( 'default', [ 'handlebars', 'uglify' ] ); }; diff --git a/client/README.md b/client/README.md index 8aa828dbeb2f..b3db1286f0a6 100644 --- a/client/README.md +++ b/client/README.md @@ -33,6 +33,19 @@ This will: 2. generate source maps and place them in static/maps +Templates +========= + +You can change and recompile the templates by using: + + grunt templates + +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 + + Changing Styles/CSS =================== diff --git a/client/bower.json b/client/bower.json index 161347ce6808..184a811d9d98 100644 --- a/client/bower.json +++ b/client/bower.json @@ -30,7 +30,7 @@ "jstree": "~3.0.9", "jquery-ui": "git://github.com/jquery/jquery-ui.git#~1.11.2", "threedubmedia.jquery.event": "*", - "handlebars": "~2.0.0", + "handlebars": "~3.0.0", "jquery-migrate": "~1.2.1", "requirejs": "~2.1.17" }, diff --git a/client/galaxy/scripts/libs/handlebars.runtime.js b/client/galaxy/scripts/libs/handlebars.runtime.js index 932fb7aea017..22638261eabc 100644 --- a/client/galaxy/scripts/libs/handlebars.runtime.js +++ b/client/galaxy/scripts/libs/handlebars.runtime.js @@ -1,6 +1,6 @@ /*! - handlebars v2.0.0 + handlebars v3.0.3 Copyright (C) 2011-2014 by Yehuda Katz @@ -24,637 +24,858 @@ THE SOFTWARE. @license */ -/* exported Handlebars */ -(function (root, factory) { - if (typeof define === 'function' && define.amd) { - define([], factory); - } else if (typeof exports === 'object') { - module.exports = factory(); - } else { - root.Handlebars = root.Handlebars || factory(); - } -}(this, function () { -// handlebars/safe-string.js -var __module3__ = (function() { - "use strict"; - var __exports__; - // Build out our basic SafeString type - function SafeString(string) { - this.string = string; - } - - SafeString.prototype.toString = function() { - return "" + this.string; - }; - - __exports__ = SafeString; - return __exports__; -})(); - -// handlebars/utils.js -var __module2__ = (function(__dependency1__) { - "use strict"; - var __exports__ = {}; - /*jshint -W004 */ - var SafeString = __dependency1__; - - var escape = { - "&": "&", - "<": "<", - ">": ">", - '"': """, - "'": "'", - "`": "`" - }; - - var badChars = /[&<>"'`]/g; - var 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; - } - - __exports__.extend = extend;var toString = Object.prototype.toString; - __exports__.toString = toString; - // Sourced from lodash - // https://github.com/bestiejs/lodash/blob/master/LICENSE.txt - var isFunction = function(value) { - return typeof value === 'function'; - }; - // fallback for older versions of Chrome and Safari - /* istanbul ignore next */ - if (isFunction(/x/)) { - isFunction = function(value) { - return typeof value === 'function' && toString.call(value) === '[object Function]'; - }; - } - var isFunction; - __exports__.isFunction = isFunction; - /* istanbul ignore next */ - var isArray = Array.isArray || function(value) { - return (value && typeof value === 'object') ? toString.call(value) === '[object Array]' : false; - }; - __exports__.isArray = isArray; - - function escapeExpression(string) { - // don't escape SafeStrings, since they're already safe - if (string instanceof SafeString) { - return string.toString(); - } 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); - } - - __exports__.escapeExpression = escapeExpression;function isEmpty(value) { - if (!value && value !== 0) { - return true; - } else if (isArray(value) && value.length === 0) { - return true; - } else { - return false; - } - } - - __exports__.isEmpty = isEmpty;function appendContextPath(contextPath, id) { - return (contextPath ? contextPath + '.' : '') + id; - } - - __exports__.appendContextPath = appendContextPath; - return __exports__; -})(__module3__); - -// handlebars/exception.js -var __module4__ = (function() { - "use strict"; - var __exports__; - - var errorProps = ['description', 'fileName', 'lineNumber', 'message', 'name', 'number', 'stack']; - - function Exception(message, node) { - var line; - if (node && node.firstLine) { - line = node.firstLine; - - message += ' - ' + line + ':' + node.firstColumn; - } - - 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 (line) { - this.lineNumber = line; - this.column = node.firstColumn; - } - } - - Exception.prototype = new Error(); - - __exports__ = Exception; - return __exports__; -})(); - -// handlebars/base.js -var __module1__ = (function(__dependency1__, __dependency2__) { - "use strict"; - var __exports__ = {}; - var Utils = __dependency1__; - var Exception = __dependency2__; - - var VERSION = "2.0.0"; - __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); - } - - __exports__.HandlebarsEnvironment = HandlebarsEnvironment;HandlebarsEnvironment.prototype = { - constructor: HandlebarsEnvironment, - - logger: logger, - log: log, - - registerHelper: function(name, fn) { - if (toString.call(name) === objectType) { - if (fn) { throw new Exception('Arg not supported with multiple helpers'); } - Utils.extend(this.helpers, name); - } else { - this.helpers[name] = fn; - } - }, - unregisterHelper: function(name) { - delete this.helpers[name]; - }, - - registerPartial: function(name, partial) { - if (toString.call(name) === objectType) { - Utils.extend(this.partials, name); - } else { - this.partials[name] = partial; - } - }, - unregisterPartial: function(name) { - delete this.partials[name]; - } - }; - - function registerDefaultHelpers(instance) { - instance.registerHelper('helperMissing', function(/* [args, ]options */) { - 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 Exception("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 Exception('Must pass iterator to #each'); - } - - var fn = options.fn, inverse = options.inverse; - var i = 0, ret = "", data; - - var contextPath; - 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); - } - - if(context && typeof context === 'object') { - if (isArray(context)) { - for(var j = context.length; i= 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; + +/***/ } +/******/ ]) +}); +; \ No newline at end of file diff --git a/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js b/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js index 269650b427b6..e4137a1db9f3 100644 --- a/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js +++ b/client/galaxy/scripts/mvc/collection/list-of-pairs-collection-creator.js @@ -568,7 +568,8 @@ var PairedCollectionCreator = Backbone.View.extend( baseMVC.LoggableMixin ).exte */ createList : function( name ){ var creator = this, - url = '/api/histories/' + this.historyId + '/contents/dataset_collections'; + root = ( window.Galaxy && Galaxy.options.root )? Galaxy.options.root : '/', + url = root + 'api/histories/' + this.historyId + '/contents/dataset_collections'; //TODO: use ListPairedCollection.create() var ajaxData = { diff --git a/client/galaxy/scripts/mvc/history/history-panel.js b/client/galaxy/scripts/mvc/history/history-panel.js index 2222a0924f26..933dd5751862 100644 --- a/client/galaxy/scripts/mvc/history/history-panel.js +++ b/client/galaxy/scripts/mvc/history/history-panel.js @@ -143,17 +143,21 @@ var HistoryPanel = _super.extend( */ _setUpListeners : function(){ _super.prototype._setUpListeners.call( this ); - - this.on( 'error', function( model, xhr, options, msg, details ){ - this.errorHandler( model, xhr, options, msg, details ); - }); - - this.on( 'loading-done', function(){ - //TODO:?? if( this.collection.length ){ - if( !this.views.length ){ - this.trigger( 'empty-history', this ); + this.on({ + error : function( model, xhr, options, msg, details ){ + this.errorHandler( model, xhr, options, msg, details ); + }, + 'loading-done' : function(){ + //TODO:?? if( this.collection.length ){ + if( !this.views.length ){ + this.trigger( 'empty-history', this ); + } + }, + 'views:ready view:attached view:removed' : function( view ){ + this._renderSelectButton(); } }); + // this.on( 'all', function(){ console.debug( arguments ); }); }, // ------------------------------------------------------------------------ loading history/hda models @@ -304,20 +308,34 @@ var HistoryPanel = _super.extend( /** In this override, add a btn to toggle the selectors */ _buildNewRender : function(){ var $newRender = _super.prototype._buildNewRender.call( this ); - //if( this.views.length && this.multiselectActions().length ){ - if( this.multiselectActions().length ){ - $newRender.find( '.controls .actions' ).prepend( this._renderSelectButton() ); - } + this._renderSelectButton( $newRender ); return $newRender; }, /** button for starting select mode */ _renderSelectButton : function( $where ){ + $where = $where || this.$el; + // do not render selector option if no actions + if( !this.multiselectActions().length ){ + return null; + } + // do not render (and remove even) if nothing to select + if( !this.views.length ){ + this.hideSelectors(); + $where.find( '.controls .actions .show-selectors-btn' ).remove(); + return null; + } + // don't bother rendering if there's one already + var $existing = $where.find( '.controls .actions .show-selectors-btn' ); + if( $existing.size() ){ + return $existing; + } + return faIconButton({ title : _l( 'Operations on multiple datasets' ), classes : 'show-selectors-btn', faIcon : 'fa-check-square-o' - }); + }).prependTo( $where.find( '.controls .actions' ) ); }, // ------------------------------------------------------------------------ sub-views @@ -398,9 +416,9 @@ var HistoryPanel = _super.extend( if( store ){ this.storage.set( 'show_deleted', show ); } - this.trigger( 'show-hidden', show ); //TODO:?? to events on storage('change:show_deleted') this.renderItems(); + this.trigger( 'show-deleted', show ); return this.showDeleted; }, @@ -416,9 +434,9 @@ var HistoryPanel = _super.extend( if( store ){ this.storage.set( 'show_hidden', show ); } - this.trigger( 'show-hidden', show ); //TODO:?? to events on storage('change:show_deleted') this.renderItems(); + this.trigger( 'show-hidden', show ); return this.showHidden; }, diff --git a/client/galaxy/scripts/mvc/list/list-panel.js b/client/galaxy/scripts/mvc/list/list-panel.js index 6741b11d3e05..d57e82efcfd2 100644 --- a/client/galaxy/scripts/mvc/list/list-panel.js +++ b/client/galaxy/scripts/mvc/list/list-panel.js @@ -371,6 +371,7 @@ var ListPanel = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend( } else { panel._renderEmptyMessage( $whereTo ).show(); } + panel.trigger( 'views:ready', panel.views ); return panel.views; }, diff --git a/client/galaxy/scripts/mvc/tools.js b/client/galaxy/scripts/mvc/tools.js index abd017b075b4..3c25706adc74 100644 --- a/client/galaxy/scripts/mvc/tools.js +++ b/client/galaxy/scripts/mvc/tools.js @@ -262,7 +262,7 @@ var Tool = Backbone.Model.extend({ // Run job and resolve run_deferred to tool outputs. $.when(ss_deferred.go()).then(function(result) { - run_deferred.resolve(new data.DatasetCollection().reset(result)); + run_deferred.resolve(new data.DatasetCollection(result)); }); return run_deferred; } diff --git a/client/galaxy/scripts/mvc/ui/ui-slider.js b/client/galaxy/scripts/mvc/ui/ui-slider.js index 96e9217228f1..d2fb4ac45630 100644 --- a/client/galaxy/scripts/mvc/ui/ui-slider.js +++ b/client/galaxy/scripts/mvc/ui/ui-slider.js @@ -68,9 +68,9 @@ var View = Backbone.View.extend({ this.$text.on('keydown', function (e) { var v = e.which; pressed[v] = true; - if (!(v == 8 || v == 9 || v == 13 || v == 37 || v == 39 || (v >= 48 && v <= 57) - || (v == 190 && $(this).val().indexOf('.') == -1 && self.options.precise) - || (v == 189 && $(this).val().indexOf('-') == -1) + if (!(v == 8 || v == 9 || v == 13 || v == 37 || v == 39 || (v >= 48 && v <= 57) || (v >= 96 && v <= 105) + || ((v == 190 || v == 110) && $(this).val().indexOf('.') == -1 && self.options.precise) + || ((v == 189 || v == 109) && $(this).val().indexOf('-') == -1) || pressed[91] || pressed[17])) { event.preventDefault(); } diff --git a/client/galaxy/scripts/reports_webapp/run_stats.js b/client/galaxy/scripts/reports_webapp/run_stats.js new file mode 100644 index 000000000000..27929b391fb7 --- /dev/null +++ b/client/galaxy/scripts/reports_webapp/run_stats.js @@ -0,0 +1,602 @@ +function days_in_month(month,year) { + return new Date(year, month, 0).getDate(); +} + +function date_by_subtracting_days(date, days) { + return new Date( + date.getFullYear(), + date.getMonth(), + date.getDate() - days, + date.getHours(), + date.getMinutes(), + date.getSeconds(), + date.getMilliseconds() + ); +} + +function date_by_subtracting_hours(date, hours) { + return new Date( + date.getFullYear(), + date.getMonth(), + date.getDate(), + date.getHours() - hours, + date.getMinutes(), + date.getSeconds(), + date.getMilliseconds() + ); +} + +function get_utc_time_hours() { + var date = new Date(); + return new Date( + date.getUTCFullYear(), + date.getUTCMonth(), + date.getUTCDate(), + date.getUTCHours(), + 0, 0 + ); +} + +function refresh() { + window.location.reload(true); +} +setTimeout(refresh, 900000); //15 minutes = 900000 ms + +function create_chart( inp_data, name, time, title ) { + require( ["d3"], function (e) { + var data = inp_data; + var margin = {top: 60, right: 30, bottom: 50, left: 60}; + var chart_zoom = 1.75; + + var hours_array = [] + var now = get_utc_time_hours() + for(var i = 0; i < 24; i++) { + hours_array.push(date_by_subtracting_hours(now, i)); + } + + var days_array = [] + var now = get_utc_time_hours() + for(var i = 0; i < 30; i++) { + days_array.push(date_by_subtracting_days(now, i)); + } + + function click() { + var classes = d3.select(this).attr("class"); + classes = classes.split(" "); + d3.selectAll("." + classes[0]).filter("." + classes[1]) + .transition() + .duration(750) + .attr("height", chart_height) + .attr("width", chart_width); + + d3.select(this) + .transition() + .duration(750) + .attr("height", chart_height*chart_zoom) + .attr("width", chart_width*chart_zoom); + } + + var height = 150; + if(d3.max(data) != 0) { + var zoom = height / d3.max(data); + } else { + var zoom = 1.0; + } + var chart_height = height + margin.top + margin.bottom; + $(".charts").css("height", chart_height * (chart_zoom)); + + var width = 300; + var barWidth = 0; + if(time == "hours") { + barWidth = width / 24; + } else if(time == "days") { + barWidth = width / 30; + } + var chart_width = width + margin.left + margin.right; + + var chart = d3.select("#" + name) + .attr("width", chart_width) + .attr("height", chart_width) + .attr("preserveAspectRatio", "xMidYMin") + .attr("viewBox", "0 0 " + chart_width + " " + chart_height) + .on("click", click); + + var bar = chart.selectAll("g") + .data(data) + .enter().append("g") + .attr("transform", function(d, i) { + curr_margin = +margin.left; + curr_margin += +(i * barWidth); + return "translate(" + curr_margin + "," + margin.top + ")"; + }) + .on("mouseenter", function(d) { + var i = 1; + var size = d; + + while( size >= 10) { + size = size / 10; + i++; + } + + var wdth = (i * 4) + 10; + d3.select(d3.event.path[1]).select(".tool_tip") + .select("text") + .attr("transform", "translate( " + (margin.left - 5) + ", " + ((height - (d * zoom)) + +margin.top + 10) + " )" ) + .attr("visibility", "visible") + .text(d); + + d3.select(d3.event.path[1]).select(".tool_tip") + .attr("width", wdth + "px") + .attr("height", "15px") + .select("rect") + .attr("transform", "translate( " + ((+margin.left) - wdth) + ", " + ((height - (d * zoom)) + +margin.top) + " )" ) + .attr("width", wdth + "px") + .attr("height", "15px") + .attr("fill","#ebd9b2"); + }) + .on("mouseleave", function(d) { + d3.select(d3.event.path[1]).select(".tool_tip") + .select("text") + .attr("visibility", "hidden"); + + d3.select(d3.event.path[1]).select(".tool_tip") + .select("rect") + .attr("width", "0") + .attr("height", "0") + .attr("fill","") + .text(d); + }); + + chart.append("g") + .append("text") + .attr("class", "title") + .attr("text-anchor", "end") + .attr("transform", function(e) { + return "translate( " + width + ",15 )"; + }) + .text(title); + + chart.append("g") + .attr("class", "axis") + .append("path") + .attr("class", "x") + .attr("d", function(d) { + var m_x = margin.left; + var m_y = +margin.top + height; + var l_x = m_x + width; + var l_y = m_y; + + return "M" + m_x + " " + m_y + " L " + l_x + " " + l_y; + }); + + var y = d3.scale.linear() + .range([height, 0]); + + var yAxis = d3.svg.axis() + .scale(y) + .orient("left") + .tickFormat( function(d) { return d3.round( d*d3.max(data), 0 ) }); + + chart.append("g") + .attr("class", "y axis") + .attr("id", ("y_" + name)) + .attr("text-anchor", "end") + .attr("transform", "translate( " + margin.left + "," + margin.top + ")") + .call(yAxis) + .select(".domain"); + + chart.append("g") + .append("text") + .attr("class", "ax_title") + .attr("transform", function(e) { + var axis = d3.select("#y_" + name).node() + var left_pad = +margin.left - axis.getBoundingClientRect().width - 5; + var top_pad = +margin.top + (axis.getBoundingClientRect().height/2) - 30 + var trans = "translate(" + left_pad + "," + top_pad + ")rotate(-90)"; + + return trans; + }) + .text("Number of Jobs"); + + bar.append("rect") + .attr("y", function(d) { return height - (d * zoom); }) + .attr("height", function(d) { return (d * zoom); }) + .attr("width", barWidth - 1); + + // Append x axis + if(time == "hours") { + // Append hour lines + bar.append("line") + .attr("x1", 0) + .attr("y1", 0) + .attr("x2", 0) + .attr("y2", 3) + .attr("stroke", "black") + .attr("stroke-width", 1) + .attr("transform", function(d, i) { + return "translate( " + (barWidth/2) + ", " + height + ")" + }); + + // Append hour numbers + bar.append("text") + .attr("fill", "rgb(0,0,0)") + .attr("transform", "translate( 10, " + (height + 10) + " )") + .text(function(d, i) { + var time = "0000" + + if( hours_array[i].getHours() < 10 ) { + time = "0" + String(hours_array[i].getHours()); + } else { + time = hours_array[i].getHours(); + } + + return time; + }); + + // Append day lines + var curr_day = ""; + var first = false; + bar.append("line") + .attr("x1", 0) + .attr("y1", 0) + .attr("x2", 0) + .attr("y2", function(d, i) { + var _y2 = 0; + + if(hours_array[i].getDate() != curr_day) { + if(!first) { + _y2 = 27; + first = true; + } else { + _y2 = 20; + } + + curr_day = hours_array[i].getDate(); + } + + return _y2; + }) + .attr("stroke", "black") + .attr("stroke-width", 1) + .attr("transform", function(d, i) { + return "translate( 0, " + height + ")"; + }); + + // Append day numbers + curr_day = ""; + curr_day_text = ""; + first = false; + bar.append("text") + .attr("fill", "rgb(0,0,0)") + .text(function(d, i) { + var time = ""; + var locale = "en-us"; + + if(hours_array[i].getDate() != curr_day_text) { + time = String(hours_array[i].toLocaleString(locale, { month: "long" })); + time += " " + String(hours_array[i].getDate()) + + curr_day_text = hours_array[i].getDate(); + } + + return time; + }) + .attr("transform", function(d, i) { + var text_height = height; + var this_width = d3.select(this).node().getBBox().width; + + if(hours_array[i].getDate() != curr_day) { + if(!first) { + text_height += 25; + first = true; + } else { + text_height += 18; + } + + curr_day = hours_array[i].getDate(); + } + + return "translate( " + (this_width + 2) + ", " + (text_height) + " )" + }); + } else if(time == "days") { + // Append day lines + bar.append("line") + .attr("x1", 0) + .attr("y1", 0) + .attr("x2", 0) + .attr("y2", 3) + .attr("stroke", "black") + .attr("stroke-width", 1) + .attr("transform", function(d, i) { + return "translate( " + (barWidth/2) + ", " + height + ")" + }); + + // Append day numbers + bar.append("text") + .attr("fill", "rgb(0,0,0)") + .attr("transform", "translate( 9, " + (height + 10) + " )") + .text(function(d, i) { + var time = "0000" + + if( days_array[i].getDate() < 10 ) { + time = "0" + String(days_array[i].getDate()); + } else { + time = days_array[i].getDate(); + } + + return time; + }); + + // Append month lines + var curr_month = ""; + var first = false; + bar.append("line") + .attr("x1", 0) + .attr("y1", 0) + .attr("x2", 0) + .attr("y2", function(d, i) { + var _y2 = 0; + + if(days_array[i].getMonth() != curr_month) { + if(!first) { + _y2 = 27; + first = true; + } else { + _y2 = 20; + } + + curr_month = days_array[i].getMonth(); + } + + return _y2; + }) + .attr("stroke", "black") + .attr("stroke-width", 1) + .attr("transform", function(d, i) { + return "translate( 0, " + height + ")"; + }); + + // Append month numbers + curr_month = ""; + curr_month_text = ""; + first = false; + bar.append("text") + .attr("fill", "rgb(0,0,0)") + .text(function(d, i) { + var time = ""; + var locale = "en-us"; + + if(days_array[i].getMonth() != curr_month_text) { + time = String(days_array[i].toLocaleString(locale, { month: "long" })); + time += " " + String(days_array[i].getFullYear()) + + curr_month_text = days_array[i].getMonth(); + } + + return time; + }) + .attr("transform", function(d, i) { + var text_height = height; + var this_width = d3.select(this).node().getBBox().width; + + if(days_array[i].getMonth() != curr_month) { + if(!first) { + text_height += 25; + first = true; + } else { + text_height += 18; + } + + curr_month = days_array[i].getMonth(); + } + + return "translate( " + (this_width + 2) + ", " + (text_height) + " )" + }); + } + + chart.append("g") + .attr("class", "tool_tip") + .append("rect"); + chart.select(".tool_tip") + .append("text"); + + if(name == "jc_dy_chart" || name == "jc_hr_chart") { + d3.select("#" + name) + .attr("height", chart_height * chart_zoom) + .attr("width", chart_width * chart_zoom) + } + }); +} + +//============================================================================================================ + +function create_histogram( inp_data, name, title ) { + require( ["d3"], function (e) { + //inp_data is an array of numbers that are the amount of minutes per run + var data = inp_data; + var chart_zoom = 1.75; + // Formatters for counts and times (converting numbers to Dates). + function click(d) { + var classes = d3.select(this).attr("class") + classes = classes.split(" "); + d3.selectAll("." + classes[0]).filter("." + classes[1]) + .transition() + .duration(750) + .attr("height", chart_height) + .attr("width", chart_width); + + d3.select(this) + .transition() + .duration(750) + .attr("height", chart_height*chart_zoom) + .attr("width", chart_width*chart_zoom); + + } + + var formatMinutes = function(d) { + hours = Math.floor( d / 60 ) + minutes = Math.floor(d - (hours * 60)) + + if(hours < 10) { + hours = "0" + hours + } + if(minutes < 10) { + minutes = "0" + minutes + } + + return hours + ":" + minutes; + }; + + var margin = {top: 60, right: 30, bottom: 50, left: 60}; + var height = 150; + var chart_height = height + margin.top + margin.bottom; + + var width = 300; + var chart_width = width + margin.left + margin.right; + + var lengths = [] + + var x = d3.scale.linear() + .domain([0, d3.max(data)]) + .range([0, width]); + + // Generate a histogram using twenty uniformly-spaced bins. + var data = d3.layout.histogram() + .bins(x.ticks(20))(data); + + for(var i = 0; i < data.length; i ++) { + lengths.push(data[i].length) + } + + if(d3.max(data) != 0) { + var zoom = height / d3.max(lengths); + } else { + var zoom = 1.0; + } + + var y = d3.scale.linear() + .domain([0, d3.max(data, function(d) { return d.y; })]) + .range([height, 0]); + + var chart = d3.select("#" + name) + .attr("viewBox", "0 0 " + chart_width + " " + chart_height) + .attr("width", chart_width) + .attr("height", chart_height) + .attr("preserveAspectRatio", "xMidYMin") + .on("click", click); + + chart.append("g") + .append("text") + .attr("class", "title") + .attr("transform", function(e) { + return "translate( " + width + ",15 )"; + }) + .text(title); + + var bar = chart.selectAll(".bar") + .data(data) + .enter().append("g") + .attr("class", "bar") + .attr("transform", function(d) { return "translate(" + (+x(d.x) + +margin.left) + "," + (+y(d.y) + +margin.top) + ")"; }) + .on("mouseenter", function(d) { + i = 0; + size = d.length; + + while( size >= 1) { + size = size / 10; + i++; + } + var wdth = (i * 4) + 10; + d3.select(d3.event.path[1]).select(".tool_tip") + .select("text") + .attr("transform", "translate( " + (margin.left - 5) + ", " + (height - (d.length * zoom) + +margin.top + 10) + " )" ) + .attr("visibility", "visible") + .text(d.length); + + d3.select(d3.event.path[1]).select(".tool_tip") + .attr("width", wdth + "px") + .attr("height", "15px") + .select("rect") + .attr("transform", "translate( " + ((+margin.left) - wdth) + ", " + (height - (d.length * zoom) + +margin.top) + " )") + .attr("width", wdth + "px") + .attr("height", "15px") + .attr("fill","#ebd9b2"); + }) + .on("mouseleave", function(d) { + d3.select(d3.event.path[1]).select(".tool_tip") + .select("text") + .attr("visibility", "hidden"); + + d3.select(d3.event.path[1]).select(".tool_tip") + .select("rect") + .attr("width", "0") + .attr("height", "0") + .attr("fill","") + }); + + var bar_x; + if(data[0] == undefined) { + bar_x = 1; + } else { + bar_x = x(data[0].dx); + } + + bar.append("rect") + .attr("x", 1) + .attr("width", bar_x - 1) + .attr("height", function(d) { return height - y(d.y); }); + + var xAxis = d3.svg.axis() + .scale(x) + .orient("bottom") + .tickFormat(formatMinutes); + + chart.append("g") + .attr("class", "x axis") + .attr("id", "x_" + name) + .attr("transform", "translate( " + margin.left + "," + (+height + +margin.top) + ")") + .call(xAxis); + + chart.append("g") + .append("text") + .attr("class", "ax_title") + .attr("transform", function(e) { + var axis = d3.select("#x_" + name).node() + var left_pad = +margin.left + (axis.getBoundingClientRect().width/2) + 30; + var top_pad = +margin.top + height + axis.getBoundingClientRect().height + 10 + var trans = "translate(" + left_pad + "," + top_pad + ")"; + + return trans; + }) + .text("ETA - hrs:mins"); + + var yAxis = d3.svg.axis() + .scale(y) + .orient("left"); + + chart.append("g") + .attr("class", "y axis") + .attr("id", ("y_" + name)) + .attr("transform", "translate( " + margin.left + "," + margin.top + ")") + .call(yAxis); + + chart.append("g") + .append("text") + .attr("class", "ax_title") + .attr("transform", function(e) { + var axis = d3.select("#y_" + name).node() + var left_pad = +margin.left - axis.getBoundingClientRect().width - 5; + var top_pad = +margin.top + (axis.getBoundingClientRect().height/2) - 30 + var trans = "translate(" + left_pad + "," + top_pad + ")rotate(-90)"; + + return trans; + }) + .text("Number of Jobs"); + + chart.append("g") + .attr("class", "tool_tip") + .append("rect"); + chart.select(".tool_tip") + .append("text"); + }); +} diff --git a/client/galaxy/scripts/templates/compile_templates.py b/client/galaxy/scripts/templates/compile_templates.py deleted file mode 100755 index fffe0f5250e1..000000000000 --- a/client/galaxy/scripts/templates/compile_templates.py +++ /dev/null @@ -1,238 +0,0 @@ -#!/usr/bin/env python - -# Script requires handlebars compiler be installed; use node package manager -# to install handlebars. - -"""%prog [options] [ specific .handlebars or .html template file to compile ] - Compiles handlebars templates into javascript for better load times and performance. - - Handlebars compilation errors will print to stderr. - NOTE!: you will need node.js, npm, and handlebars (installed from npm) in order to compile templates - See http://handlebarsjs.com/precompilation.html for more info. - - Should be called from the $GLX_ROOT/static/scripts/templates directory. - Compiled templates will be written to the compiled/ directory. - - If the --multi-ext option is passed a file extension string, the script will: - * search for *. in the current directory, - * extract each ' -""" -# ------------------------------------------------------------------------------ - -TODO = """ -remove intermediate, handlebars step of multi->handlebars->compiled/.js (if handlebars does stdin) -""" - -import sys - -from glob import glob -from subprocess import call -import os -from optparse import OptionParser -import re - -import logging as log -log.basicConfig( - # level=log.DEBUG, - name=__name__ -) - -COMPILED_DIR = 'compiled' -COMPILED_EXT = '.js' -COMPILE_CMD_STR = "handlebars %s -f %s" -COMPILE_MINIMIZE_SWITCH = ' -m' - -TEMPLATE_TAG = 'script' -TEMPLATE_TYPE = 'text/template' -HELPER_TYPE = 'text/javascript' - -# both of these are off by default for backward compat -DEFAULT_MINIMIZATION = False -DEFAULT_MULTI_EXT = None # '.html' - - -# ------------------------------------------------------------------------------ -def parse_html_tag_attrs( string ): - attrs = {} - for match in re.finditer( r'(?P\w+?)=[\'|\"](?P.*?)[\'|\"]', string, re.DOTALL | re.MULTILINE ): - match = match.groupdict() - key = match[ 'key' ] - val = match[ 'val' ] - attrs[ key ] = val - return attrs - - -def split_on_html_tag( string, tag ): - tag_pattern = r'<%s\s*(?P.*?)>(?P.*?)' % ( tag, tag ) - log.debug( tag_pattern ) - tag_pattern = re.compile( tag_pattern, re.MULTILINE | re.DOTALL ) - - found_list = re.findall( tag_pattern, string ) - for attrs, body in found_list: - yield ( parse_html_tag_attrs( attrs ), body ) - - -def filter_on_tag_type( generator, type_attr_to_match ): - for attrs, body in generator: - log.debug( 'attrs: %s', str( attrs ) ) - if( ( 'type' in attrs ) - and ( attrs[ 'type' ] == type_attr_to_match ) ): - yield attrs, body - - -# ------------------------------------------------------------------------------ -def break_multi_template( multi_template_filename ): - """parse the multi template, writing each template into a new handlebars tmpl and returning their names""" - template_filenames = [] - - # parse the multi template - print "\nBreaking multi-template file %s into individual templates and helpers:" % ( multi_template_filename ) - with open( multi_template_filename, 'r' ) as multi_template_file: - multi_template_file_text = multi_template_file.read() - - # write a template file for each template (name based on id in tag) - tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG ) - for attrs, template_text in filter_on_tag_type( tag_generator, TEMPLATE_TYPE ): - if( 'id' not in attrs ): - log.warning( 'Template has no "id". attrs: %s' % ( str( attrs ) ) ) - continue - - template_id = attrs[ 'id' ] - template_text = template_text.strip() - handlebar_template_filename = template_id + '.handlebars' - with open( handlebar_template_filename, 'w' ) as handlebar_template_file: - handlebar_template_file.write( template_text ) - - log.debug( "%s\n%s\n", template_id, template_text ) - template_filenames.append( handlebar_template_filename ) - - # write all helpers to a single 'helper-' prefixed js file in the compilation dir - helper_fns = [] - # same tag, different type - tag_generator = split_on_html_tag( multi_template_file_text, TEMPLATE_TAG ) - for attrs, helper_text in filter_on_tag_type( tag_generator, HELPER_TYPE ): - helper_text = helper_text.strip() - print '(helper):', ( attrs[ 'id' ] if 'id' in attrs else '(No id)' ) - - helper_fns.append( helper_text ) - - if helper_fns: - # prefix original filename (in compiled dir) and write all helper funcs to that file - helper_filename = 'helpers-' + os.path.splitext( multi_template_filename )[0] + '.js' - helper_filename = os.path.join( COMPILED_DIR, helper_filename ) - with open( helper_filename, 'w' ) as helper_file: - helper_file.write( '\n'.join( helper_fns ) ) - print '(helper functions written to %s)' % helper_filename - - print '\n'.join( template_filenames ) - return template_filenames - - -# ------------------------------------------------------------------------------ -def compile_template( template_filename, minimize=False ): - """compile the given template file (optionally minimizing the js) using subprocess. - - Use the basename of the template file for the outputed js. - """ - template_basename = os.path.splitext( os.path.split( template_filename )[1] )[0] - compiled_filename = os.path.join( COMPILED_DIR, template_basename + COMPILED_EXT ) - - command_string = COMPILE_CMD_STR % ( template_filename, compiled_filename ) - if minimize: - command_string += COMPILE_MINIMIZE_SWITCH - print command_string - return call( command_string, shell=True ) - - -# ------------------------------------------------------------------------------ -def main( options, args ): - """Break multi template files into single templates, compile all single templates. - - If args, compile that as a list of specific handlebars and/or multi template files. - """ - print "(Call this script with the '-h' option for more help)" - - handlebars_templates = [] - # If specific scripts specified on command line, just compile them, - if len( args ) >= 1: - handlebars_templates = filter( lambda( x ): x.endswith( '.handlebars' ), args ) - - # otherwise compile all in the current dir - else: - handlebars_templates = glob( '*.handlebars' ) - - # if desired, break up any passed-in or found multi template files - # adding the names of the new single templates to those needing compilation - multi_template_template_filenames = [] - if options.multi_ext: - multi_templates = [] - if len( args ) >= 1: - multi_templates = filter( lambda( x ): x.endswith( options.multi_ext ), args ) - else: - multi_templates = glob( '*' + options.multi_ext ) - - for multi_template_filename in multi_templates: - multi_template_template_filenames.extend( break_multi_template( multi_template_filename ) ) - - # unique filenames only (Q&D) - handlebars_templates = list( set( handlebars_templates + multi_template_template_filenames ) ) - - # compile the templates - print "\nCompiling templates:" - filenames_w_possible_errors = [] - for handlebars_template in handlebars_templates: - shell_ret = compile_template( handlebars_template, options.minimize ) - if shell_ret: - filenames_w_possible_errors.append( handlebars_template ) - - # report any possible errors - if filenames_w_possible_errors: - print "\nThere may have been errors on the following files:" - print ',\n'.join( filenames_w_possible_errors ) - print "\nCall this script with the '-h' for more help" - - # delete multi template intermediate files - if options.remove_intermediate: - print "\nCleaning up intermediate multi-template template files:" - for filename in multi_template_template_filenames: - try: - print 'removing', filename - os.remove( filename ) - except Exception, exc: - print exc - - -# ------------------------------------------------------------------------------ -if __name__ == '__main__': - optparser = OptionParser( usage=__doc__ ) - optparser.add_option( '-m', '--minimize', dest='minimize', action='store_true', default=DEFAULT_MINIMIZATION, - help=( 'minimize compiled template scripts via handlebars ' - + '(defaults to %s)' % DEFAULT_MINIMIZATION ) ) - optparser.add_option( '--multi-ext', dest='multi_ext', metavar="FILE_EXTENSION", default=DEFAULT_MULTI_EXT, - help=( 'indicates that files ending with the given string contain multiple ' - + 'templates and the script should break those into individual ' - + 'handlebars templates (defaults to "%s")' ) % DEFAULT_MULTI_EXT ) - optparser.add_option( '--no-remove', action='store_false', dest='remove_intermediate', default=True, - help=( 'remove intermediate *.handlebars files when using multiple template' - + 'files (defaults to "True")' ) ) - - ( options, args ) = optparser.parse_args() - sys.exit( main( options, args ) ) diff --git a/client/galaxy/scripts/templates/compiled/panel_section.js b/client/galaxy/scripts/templates/compiled/panel_section.js index b29a893c683a..af2ecea14a6a 100644 --- a/client/galaxy/scripts/templates/compiled/panel_section.js +++ b/client/galaxy/scripts/templates/compiled/panel_section.js @@ -1,6 +1,7 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['panel_section'] = template({"compiler":[6,">= 2.0.0-beta.1"],"main":function(depth0,helpers,partials,data) { +this["Handlebars"] = this["Handlebars"] || {}; +this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {}; + +this["Handlebars"]["templates"]["panel_section"] = 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 "
= 2.0.0-beta.1"],"main":f + "\n
\n
\n
\n
"; -},"useData":true}); -})(); \ No newline at end of file +},"useData":true}); \ No newline at end of file diff --git a/client/galaxy/scripts/templates/compiled/tool_form.js b/client/galaxy/scripts/templates/compiled/tool_form.js index 66411909f721..e4e4768ed4b7 100644 --- a/client/galaxy/scripts/templates/compiled/tool_form.js +++ b/client/galaxy/scripts/templates/compiled/tool_form.js @@ -1,6 +1,7 @@ -(function() { - var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {}; -templates['tool_form'] = template({"1":function(depth0,helpers,partials,data) { +this["Handlebars"] = this["Handlebars"] || {}; +this["Handlebars"]["templates"] = this["Handlebars"]["templates"] || {}; + +this["Handlebars"]["templates"]["tool_form"] = Handlebars.template({"1":function(depth0,helpers,partials,data) { var stack1, helper, alias1=helpers.helperMissing, alias2="function", alias3=this.escapeExpression; return "
\n