galaxy-commits
Threads by month
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
October 2012
- 1 participants
- 194 discussions
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/4bdb9214efd6/
changeset: 4bdb9214efd6
user: jgoecks
date: 2012-10-02 04:53:21
summary: Fix some UI framework issues.
affected #: 3 files
diff -r 55e7d7008efee2c5622f2505612265a9593ae992 -r 4bdb9214efd6ec510f2cc6e00224a467d36ba721 static/scripts/libs/underscore.js
--- a/static/scripts/libs/underscore.js
+++ b/static/scripts/libs/underscore.js
@@ -1,7 +1,10 @@
-// Underscore.js 1.4.0
-// http://underscorejs.org
+// Underscore.js 1.3.1
// (c) 2009-2012 Jeremy Ashkenas, DocumentCloud Inc.
-// Underscore may be freely distributed under the MIT license.
+// Underscore is freely distributable under the MIT license.
+// Portions of Underscore are inspired or borrowed from Prototype,
+// Oliver Steele's Functional, and John Resig's Micro-Templating.
+// For all details and documentation:
+// http://documentcloud.github.com/underscore
(function() {
@@ -21,9 +24,7 @@
var ArrayProto = Array.prototype, ObjProto = Object.prototype, FuncProto = Function.prototype;
// Create quick reference variables for speed access to core prototypes.
- var push = ArrayProto.push,
- slice = ArrayProto.slice,
- concat = ArrayProto.concat,
+ var slice = ArrayProto.slice,
unshift = ArrayProto.unshift,
toString = ObjProto.toString,
hasOwnProperty = ObjProto.hasOwnProperty;
@@ -45,11 +46,7 @@
nativeBind = FuncProto.bind;
// Create a safe reference to the Underscore object for use below.
- var _ = function(obj) {
- if (obj instanceof _) return obj;
- if (!(this instanceof _)) return new _(obj);
- this._wrapped = obj;
- };
+ var _ = function(obj) { return new wrapper(obj); };
// Export the Underscore object for **Node.js**, with
// backwards-compatibility for the old `require()` API. If we're in
@@ -65,7 +62,7 @@
}
// Current version.
- _.VERSION = '1.4.0';
+ _.VERSION = '1.3.1';
// Collection Functions
// --------------------
@@ -74,11 +71,12 @@
// Handles objects with the built-in `forEach`, arrays, and raw objects.
// Delegates to **ECMAScript 5**'s native `forEach` if available.
var each = _.each = _.forEach = function(obj, iterator, context) {
+ if (obj == null) return;
if (nativeForEach && obj.forEach === nativeForEach) {
obj.forEach(iterator, context);
} else if (obj.length === +obj.length) {
for (var i = 0, l = obj.length; i < l; i++) {
- if (iterator.call(context, obj[i], i, obj) === breaker) return;
+ if (i in obj && iterator.call(context, obj[i], i, obj) === breaker) return;
}
} else {
for (var key in obj) {
@@ -93,10 +91,12 @@
// Delegates to **ECMAScript 5**'s native `map` if available.
_.map = _.collect = function(obj, iterator, context) {
var results = [];
+ if (obj == null) return results;
if (nativeMap && obj.map === nativeMap) return obj.map(iterator, context);
each(obj, function(value, index, list) {
results[results.length] = iterator.call(context, value, index, list);
});
+ if (obj.length === +obj.length) results.length = obj.length;
return results;
};
@@ -104,6 +104,7 @@
// or `foldl`. Delegates to **ECMAScript 5**'s native `reduce` if available.
_.reduce = _.foldl = _.inject = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
+ if (obj == null) obj = [];
if (nativeReduce && obj.reduce === nativeReduce) {
if (context) iterator = _.bind(iterator, context);
return initial ? obj.reduce(iterator, memo) : obj.reduce(iterator);
@@ -124,26 +125,14 @@
// Delegates to **ECMAScript 5**'s native `reduceRight` if available.
_.reduceRight = _.foldr = function(obj, iterator, memo, context) {
var initial = arguments.length > 2;
+ if (obj == null) obj = [];
if (nativeReduceRight && obj.reduceRight === nativeReduceRight) {
if (context) iterator = _.bind(iterator, context);
- return arguments.length > 2 ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
+ return initial ? obj.reduceRight(iterator, memo) : obj.reduceRight(iterator);
}
- var length = obj.length;
- if (length !== +length) {
- var keys = _.keys(obj);
- length = keys.length;
- }
- each(obj, function(value, index, list) {
- index = keys ? keys[--length] : --length;
- if (!initial) {
- memo = obj[index];
- initial = true;
- } else {
- memo = iterator.call(context, memo, obj[index], index, list);
- }
- });
- if (!initial) throw new TypeError('Reduce of empty array with no initial value');
- return memo;
+ var reversed = _.toArray(obj).reverse();
+ if (context && !initial) iterator = _.bind(iterator, context);
+ return initial ? _.reduce(reversed, iterator, memo, context) : _.reduce(reversed, iterator);
};
// Return the first value which passes a truth test. Aliased as `detect`.
@@ -163,6 +152,7 @@
// Aliased as `select`.
_.filter = _.select = function(obj, iterator, context) {
var results = [];
+ if (obj == null) return results;
if (nativeFilter && obj.filter === nativeFilter) return obj.filter(iterator, context);
each(obj, function(value, index, list) {
if (iterator.call(context, value, index, list)) results[results.length] = value;
@@ -173,6 +163,7 @@
// Return all the elements for which a truth test fails.
_.reject = function(obj, iterator, context) {
var results = [];
+ if (obj == null) return results;
each(obj, function(value, index, list) {
if (!iterator.call(context, value, index, list)) results[results.length] = value;
});
@@ -183,13 +174,13 @@
// Delegates to **ECMAScript 5**'s native `every` if available.
// Aliased as `all`.
_.every = _.all = function(obj, iterator, context) {
- iterator || (iterator = _.identity);
var result = true;
+ if (obj == null) return result;
if (nativeEvery && obj.every === nativeEvery) return obj.every(iterator, context);
each(obj, function(value, index, list) {
if (!(result = result && iterator.call(context, value, index, list))) return breaker;
});
- return !!result;
+ return result;
};
// Determine if at least one element in the object matches a truth test.
@@ -198,6 +189,7 @@
var any = _.some = _.any = function(obj, iterator, context) {
iterator || (iterator = _.identity);
var result = false;
+ if (obj == null) return result;
if (nativeSome && obj.some === nativeSome) return obj.some(iterator, context);
each(obj, function(value, index, list) {
if (result || (result = iterator.call(context, value, index, list))) return breaker;
@@ -205,10 +197,11 @@
return !!result;
};
- // Determine if the array or object contains a given value (using `===`).
- // Aliased as `include`.
- _.contains = _.include = function(obj, target) {
+ // Determine if a given value is included in the array or object using `===`.
+ // Aliased as `contains`.
+ _.include = _.contains = function(obj, target) {
var found = false;
+ if (obj == null) return found;
if (nativeIndexOf && obj.indexOf === nativeIndexOf) return obj.indexOf(target) != -1;
found = any(obj, function(value) {
return value === target;
@@ -220,7 +213,7 @@
_.invoke = function(obj, method) {
var args = slice.call(arguments, 2);
return _.map(obj, function(value) {
- return (_.isFunction(method) ? method : value[method]).apply(value, args);
+ return (_.isFunction(method) ? method || value : value[method]).apply(value, args);
});
};
@@ -229,25 +222,9 @@
return _.map(obj, function(value){ return value[key]; });
};
- // Convenience version of a common use case of `filter`: selecting only objects
- // with specific `key:value` pairs.
- _.where = function(obj, attrs) {
- if (_.isEmpty(attrs)) return [];
- return _.filter(obj, function(value) {
- for (var key in attrs) {
- if (attrs[key] !== value[key]) return false;
- }
- return true;
- });
- };
-
// Return the maximum element or (element-based computation).
- // Can't optimize arrays of integers longer than 65,535 elements.
- // See: https://bugs.webkit.org/show_bug.cgi?id=80797
_.max = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.max.apply(Math, obj);
- }
+ if (!iterator && _.isArray(obj)) return Math.max.apply(Math, obj);
if (!iterator && _.isEmpty(obj)) return -Infinity;
var result = {computed : -Infinity};
each(obj, function(value, index, list) {
@@ -259,9 +236,7 @@
// Return the minimum element (or element-based computation).
_.min = function(obj, iterator, context) {
- if (!iterator && _.isArray(obj) && obj[0] === +obj[0] && obj.length < 65535) {
- return Math.min.apply(Math, obj);
- }
+ if (!iterator && _.isArray(obj)) return Math.min.apply(Math, obj);
if (!iterator && _.isEmpty(obj)) return Infinity;
var result = {computed : Infinity};
each(obj, function(value, index, list) {
@@ -273,107 +248,81 @@
// Shuffle an array.
_.shuffle = function(obj) {
- var rand;
- var index = 0;
- var shuffled = [];
- each(obj, function(value) {
- rand = _.random(index++);
- shuffled[index - 1] = shuffled[rand];
- shuffled[rand] = value;
+ var shuffled = [], rand;
+ each(obj, function(value, index, list) {
+ if (index == 0) {
+ shuffled[0] = value;
+ } else {
+ rand = Math.floor(Math.random() * (index + 1));
+ shuffled[index] = shuffled[rand];
+ shuffled[rand] = value;
+ }
});
return shuffled;
};
- // An internal function to generate lookup iterators.
- var lookupIterator = function(value) {
- return _.isFunction(value) ? value : function(obj){ return obj[value]; };
- };
-
// Sort the object's values by a criterion produced by an iterator.
- _.sortBy = function(obj, value, context) {
- var iterator = lookupIterator(value);
+ _.sortBy = function(obj, iterator, context) {
return _.pluck(_.map(obj, function(value, index, list) {
return {
value : value,
- index : index,
criteria : iterator.call(context, value, index, list)
};
}).sort(function(left, right) {
- var a = left.criteria;
- var b = right.criteria;
- if (a !== b) {
- if (a > b || a === void 0) return 1;
- if (a < b || b === void 0) return -1;
- }
- return left.index < right.index ? -1 : 1;
+ var a = left.criteria, b = right.criteria;
+ return a < b ? -1 : a > b ? 1 : 0;
}), 'value');
};
- // An internal function used for aggregate "group by" operations.
- var group = function(obj, value, context, behavior) {
+ // Groups the object's values by a criterion. Pass either a string attribute
+ // to group by, or a function that returns the criterion.
+ _.groupBy = function(obj, val) {
var result = {};
- var iterator = lookupIterator(value);
+ var iterator = _.isFunction(val) ? val : function(obj) { return obj[val]; };
each(obj, function(value, index) {
- var key = iterator.call(context, value, index, obj);
- behavior(result, key, value);
+ var key = iterator(value, index);
+ (result[key] || (result[key] = [])).push(value);
});
return result;
};
- // Groups the object's values by a criterion. Pass either a string attribute
- // to group by, or a function that returns the criterion.
- _.groupBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key, value) {
- (_.has(result, key) ? result[key] : (result[key] = [])).push(value);
- });
- };
-
- // Counts instances of an object that group by a certain criterion. Pass
- // either a string attribute to count by, or a function that returns the
- // criterion.
- _.countBy = function(obj, value, context) {
- return group(obj, value, context, function(result, key, value) {
- if (!_.has(result, key)) result[key] = 0;
- result[key]++;
- });
- };
-
- // Use a comparator function to figure out the smallest index at which
- // an object should be inserted so as to maintain order. Uses binary search.
- _.sortedIndex = function(array, obj, iterator, context) {
- iterator = iterator == null ? _.identity : lookupIterator(iterator);
- var value = iterator.call(context, obj);
+ // Use a comparator function to figure out at what index an object should
+ // be inserted so as to maintain order. Uses binary search.
+ _.sortedIndex = function(array, obj, iterator) {
+ iterator || (iterator = _.identity);
var low = 0, high = array.length;
while (low < high) {
- var mid = (low + high) >>> 1;
- iterator.call(context, array[mid]) < value ? low = mid + 1 : high = mid;
+ var mid = (low + high) >> 1;
+ iterator(array[mid]) < iterator(obj) ? low = mid + 1 : high = mid;
}
return low;
};
// Safely convert anything iterable into a real, live array.
- _.toArray = function(obj) {
- if (!obj) return [];
- if (obj.length === +obj.length) return slice.call(obj);
- return _.values(obj);
+ _.toArray = function(iterable) {
+ if (!iterable) return [];
+ if (iterable.toArray) return iterable.toArray();
+ if (_.isArray(iterable)) return slice.call(iterable);
+ if (_.isArguments(iterable)) return slice.call(iterable);
+ return _.values(iterable);
};
// Return the number of elements in an object.
_.size = function(obj) {
- return (obj.length === +obj.length) ? obj.length : _.keys(obj).length;
+ return _.toArray(obj).length;
};
// Array Functions
// ---------------
// Get the first element of an array. Passing **n** will return the first N
- // values in the array. Aliased as `head` and `take`. The **guard** check
- // allows it to work with `_.map`.
- _.first = _.head = _.take = function(array, n, guard) {
+ // values in the array. Aliased as `head`. The **guard** check allows it to work
+ // with `_.map`.
+ _.first = _.head = function(array, n, guard) {
return (n != null) && !guard ? slice.call(array, 0, n) : array[0];
};
- // Returns everything but the last entry of the array. Especially useful on
+ // Returns everything but the last entry of the array. Especcialy useful on
// the arguments object. Passing **n** will return all the values in
// the array, excluding the last N. The **guard** check allows it to work with
// `_.map`.
@@ -391,12 +340,12 @@
}
};
- // Returns everything but the first entry of the array. Aliased as `tail` and `drop`.
- // Especially useful on the arguments object. Passing an **n** will return
- // the rest N values in the array. The **guard**
+ // Returns everything but the first entry of the array. Aliased as `tail`.
+ // Especially useful on the arguments object. Passing an **index** will return
+ // the rest of the values in the array from that index onward. The **guard**
// check allows it to work with `_.map`.
- _.rest = _.tail = _.drop = function(array, n, guard) {
- return slice.call(array, (n == null) || guard ? 1 : n);
+ _.rest = _.tail = function(array, index, guard) {
+ return slice.call(array, (index == null) || guard ? 1 : index);
};
// Trim out all falsy values from an array.
@@ -404,21 +353,13 @@
return _.filter(array, function(value){ return !!value; });
};
- // Internal implementation of a recursive `flatten` function.
- var flatten = function(input, shallow, output) {
- each(input, function(value) {
- if (_.isArray(value)) {
- shallow ? push.apply(output, value) : flatten(value, shallow, output);
- } else {
- output.push(value);
- }
- });
- return output;
- };
-
// Return a completely flattened version of an array.
_.flatten = function(array, shallow) {
- return flatten(array, shallow, []);
+ return _.reduce(array, function(memo, value) {
+ if (_.isArray(value)) return memo.concat(shallow ? value : _.flatten(value));
+ memo[memo.length] = value;
+ return memo;
+ }, []);
};
// Return a version of the array that does not contain the specified value(s).
@@ -429,28 +370,28 @@
// Produce a duplicate-free version of the array. If the array has already
// been sorted, you have the option of using a faster algorithm.
// Aliased as `unique`.
- _.uniq = _.unique = function(array, isSorted, iterator, context) {
- var initial = iterator ? _.map(array, iterator, context) : array;
- var results = [];
- var seen = [];
- each(initial, function(value, index) {
- if (isSorted ? (!index || seen[seen.length - 1] !== value) : !_.contains(seen, value)) {
- seen.push(value);
- results.push(array[index]);
+ _.uniq = _.unique = function(array, isSorted, iterator) {
+ var initial = iterator ? _.map(array, iterator) : array;
+ var result = [];
+ _.reduce(initial, function(memo, el, i) {
+ if (0 == i || (isSorted === true ? _.last(memo) != el : !_.include(memo, el))) {
+ memo[memo.length] = el;
+ result[result.length] = array[i];
}
- });
- return results;
+ return memo;
+ }, []);
+ return result;
};
// Produce an array that contains the union: each distinct element from all of
// the passed-in arrays.
_.union = function() {
- return _.uniq(concat.apply(ArrayProto, arguments));
+ return _.uniq(_.flatten(arguments, true));
};
// Produce an array that contains every item shared between all the
- // passed-in arrays.
- _.intersection = function(array) {
+ // passed-in arrays. (Aliased as "intersect" for back-compat.)
+ _.intersection = _.intersect = function(array) {
var rest = slice.call(arguments, 1);
return _.filter(_.uniq(array), function(item) {
return _.every(rest, function(other) {
@@ -462,8 +403,8 @@
// Take the difference between one array and a number of other arrays.
// Only the elements present in just the first array will remain.
_.difference = function(array) {
- var rest = concat.apply(ArrayProto, slice.call(arguments, 1));
- return _.filter(array, function(value){ return !_.contains(rest, value); });
+ var rest = _.flatten(slice.call(arguments, 1));
+ return _.filter(array, function(value){ return !_.include(rest, value); });
};
// Zip together multiple lists into a single array -- elements that share
@@ -472,27 +413,10 @@
var args = slice.call(arguments);
var length = _.max(_.pluck(args, 'length'));
var results = new Array(length);
- for (var i = 0; i < length; i++) {
- results[i] = _.pluck(args, "" + i);
- }
+ for (var i = 0; i < length; i++) results[i] = _.pluck(args, "" + i);
return results;
};
- // Converts lists into objects. Pass either a single array of `[key, value]`
- // pairs, or two parallel arrays of the same length -- one of keys, and one of
- // the corresponding values.
- _.object = function(list, values) {
- var result = {};
- for (var i = 0, l = list.length; i < l; i++) {
- if (values) {
- result[list[i]] = values[i];
- } else {
- result[list[i][0]] = list[i][1];
- }
- }
- return result;
- };
-
// If the browser doesn't supply us with indexOf (I'm looking at you, **MSIE**),
// we need this function. Return the position of the first occurrence of an
// item in an array, or -1 if the item is not included in the array.
@@ -500,25 +424,23 @@
// If the array is large and already in sort order, pass `true`
// for **isSorted** to use binary search.
_.indexOf = function(array, item, isSorted) {
- var i = 0, l = array.length;
+ if (array == null) return -1;
+ var i, l;
if (isSorted) {
- if (typeof isSorted == 'number') {
- i = (isSorted < 0 ? Math.max(0, l + isSorted) : isSorted);
- } else {
- i = _.sortedIndex(array, item);
- return array[i] === item ? i : -1;
- }
+ i = _.sortedIndex(array, item);
+ return array[i] === item ? i : -1;
}
- if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item, isSorted);
- for (; i < l; i++) if (array[i] === item) return i;
+ if (nativeIndexOf && array.indexOf === nativeIndexOf) return array.indexOf(item);
+ for (i = 0, l = array.length; i < l; i++) if (i in array && array[i] === item) return i;
return -1;
};
// Delegates to **ECMAScript 5**'s native `lastIndexOf` if available.
- _.lastIndexOf = function(array, item, fromIndex) {
- if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item, fromIndex);
- var i = (fromIndex != null ? fromIndex : array.length);
- while (i--) if (array[i] === item) return i;
+ _.lastIndexOf = function(array, item) {
+ if (array == null) return -1;
+ if (nativeLastIndexOf && array.lastIndexOf === nativeLastIndexOf) return array.lastIndexOf(item);
+ var i = array.length;
+ while (i--) if (i in array && array[i] === item) return i;
return -1;
};
@@ -592,7 +514,7 @@
// it with the arguments supplied.
_.delay = function(func, wait) {
var args = slice.call(arguments, 2);
- return setTimeout(function(){ return func.apply(null, args); }, wait);
+ return setTimeout(function(){ return func.apply(func, args); }, wait);
};
// Defers a function, scheduling it to run after the current call stack has
@@ -604,46 +526,39 @@
// Returns a function, that, when invoked, will only be triggered at most once
// during a given window of time.
_.throttle = function(func, wait) {
- var context, args, timeout, throttling, more, result;
+ var context, args, timeout, throttling, more;
var whenDone = _.debounce(function(){ more = throttling = false; }, wait);
return function() {
context = this; args = arguments;
var later = function() {
timeout = null;
- if (more) {
- result = func.apply(context, args);
- }
+ if (more) func.apply(context, args);
whenDone();
};
if (!timeout) timeout = setTimeout(later, wait);
if (throttling) {
more = true;
} else {
- throttling = true;
- result = func.apply(context, args);
+ func.apply(context, args);
}
whenDone();
- return result;
+ throttling = true;
};
};
// Returns a function, that, as long as it continues to be invoked, will not
// be triggered. The function will be called after it stops being called for
- // N milliseconds. If `immediate` is passed, trigger the function on the
- // leading edge, instead of the trailing.
- _.debounce = function(func, wait, immediate) {
- var timeout, result;
+ // N milliseconds.
+ _.debounce = function(func, wait) {
+ var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
- if (!immediate) result = func.apply(context, args);
+ func.apply(context, args);
};
- var callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
- if (callNow) result = func.apply(context, args);
- return result;
};
};
@@ -654,9 +569,7 @@
return function() {
if (ran) return memo;
ran = true;
- memo = func.apply(this, arguments);
- func = null;
- return memo;
+ return memo = func.apply(this, arguments);
};
};
@@ -665,8 +578,7 @@
// conditionally execute the original function.
_.wrap = function(func, wrapper) {
return function() {
- var args = [func];
- push.apply(args, arguments);
+ var args = [func].concat(slice.call(arguments, 0));
return wrapper.apply(this, args);
};
};
@@ -688,9 +600,7 @@
_.after = function(times, func) {
if (times <= 0) return func();
return function() {
- if (--times < 1) {
- return func.apply(this, arguments);
- }
+ if (--times < 1) { return func.apply(this, arguments); }
};
};
@@ -708,23 +618,7 @@
// Retrieve the values of an object's properties.
_.values = function(obj) {
- var values = [];
- for (var key in obj) if (_.has(obj, key)) values.push(obj[key]);
- return values;
- };
-
- // Convert an object into a list of `[key, value]` pairs.
- _.pairs = function(obj) {
- var pairs = [];
- for (var key in obj) if (_.has(obj, key)) pairs.push([key, obj[key]]);
- return pairs;
- };
-
- // Invert the keys and values of an object. The values must be serializable.
- _.invert = function(obj) {
- var result = {};
- for (var key in obj) if (_.has(obj, key)) result[obj[key]] = key;
- return result;
+ return _.map(obj, _.identity);
};
// Return a sorted list of the function names available on the object.
@@ -747,26 +641,6 @@
return obj;
};
- // Return a copy of the object only containing the whitelisted properties.
- _.pick = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- each(keys, function(key) {
- if (key in obj) copy[key] = obj[key];
- });
- return copy;
- };
-
- // Return a copy of the object without the blacklisted properties.
- _.omit = function(obj) {
- var copy = {};
- var keys = concat.apply(ArrayProto, slice.call(arguments, 1));
- for (var key in obj) {
- if (!_.contains(keys, key)) copy[key] = obj[key];
- }
- return copy;
- };
-
// Fill in a given object with default properties.
_.defaults = function(obj) {
each(slice.call(arguments, 1), function(source) {
@@ -791,16 +665,19 @@
return obj;
};
- // Internal recursive comparison function for `isEqual`.
- var eq = function(a, b, aStack, bStack) {
+ // Internal recursive comparison function.
+ function eq(a, b, stack) {
// Identical objects are equal. `0 === -0`, but they aren't identical.
// See the Harmony `egal` proposal: http://wiki.ecmascript.org/doku.php?id=harmony:egal.
if (a === b) return a !== 0 || 1 / a == 1 / b;
// A strict comparison is necessary because `null == undefined`.
if (a == null || b == null) return a === b;
// Unwrap any wrapped objects.
- if (a instanceof _) a = a._wrapped;
- if (b instanceof _) b = b._wrapped;
+ if (a._chain) a = a._wrapped;
+ if (b._chain) b = b._wrapped;
+ // Invoke a custom `isEqual` method if one is provided.
+ if (a.isEqual && _.isFunction(a.isEqual)) return a.isEqual(b);
+ if (b.isEqual && _.isFunction(b.isEqual)) return b.isEqual(a);
// Compare `[[Class]]` names.
var className = toString.call(a);
if (className != toString.call(b)) return false;
@@ -830,15 +707,14 @@
if (typeof a != 'object' || typeof b != 'object') return false;
// Assume equality for cyclic structures. The algorithm for detecting cyclic
// structures is adapted from ES 5.1 section 15.12.3, abstract operation `JO`.
- var length = aStack.length;
+ var length = stack.length;
while (length--) {
// Linear search. Performance is inversely proportional to the number of
// unique nested structures.
- if (aStack[length] == a) return bStack[length] == b;
+ if (stack[length] == a) return true;
}
// Add the first object to the stack of traversed objects.
- aStack.push(a);
- bStack.push(b);
+ stack.push(a);
var size = 0, result = true;
// Recursively compare objects and arrays.
if (className == '[object Array]') {
@@ -848,24 +724,20 @@
if (result) {
// Deep compare the contents, ignoring non-numeric properties.
while (size--) {
- if (!(result = eq(a[size], b[size], aStack, bStack))) break;
+ // Ensure commutative equality for sparse arrays.
+ if (!(result = size in a == size in b && eq(a[size], b[size], stack))) break;
}
}
} else {
- // Objects with different constructors are not equivalent, but `Object`s
- // from different frames are.
- var aCtor = a.constructor, bCtor = b.constructor;
- if (aCtor !== bCtor && !(_.isFunction(aCtor) && (aCtor instanceof aCtor) &&
- _.isFunction(bCtor) && (bCtor instanceof bCtor))) {
- return false;
- }
+ // Objects with different constructors are not equivalent.
+ if ('constructor' in a != 'constructor' in b || a.constructor != b.constructor) return false;
// Deep compare objects.
for (var key in a) {
if (_.has(a, key)) {
// Count the expected number of properties.
size++;
// Deep compare each member.
- if (!(result = _.has(b, key) && eq(a[key], b[key], aStack, bStack))) break;
+ if (!(result = _.has(b, key) && eq(a[key], b[key], stack))) break;
}
}
// Ensure that both objects contain the same number of properties.
@@ -877,20 +749,18 @@
}
}
// Remove the first object from the stack of traversed objects.
- aStack.pop();
- bStack.pop();
+ stack.pop();
return result;
- };
+ }
// Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) {
- return eq(a, b, [], []);
+ return eq(a, b, []);
};
// Is a given array, string, or object empty?
// An "empty" object has no enumerable own-properties.
_.isEmpty = function(obj) {
- if (obj == null) return true;
if (_.isArray(obj) || _.isString(obj)) return obj.length === 0;
for (var key in obj) if (_.has(obj, key)) return false;
return true;
@@ -898,7 +768,7 @@
// Is a given value a DOM element?
_.isElement = function(obj) {
- return !!(obj && obj.nodeType === 1);
+ return !!(obj && obj.nodeType == 1);
};
// Is a given value an array?
@@ -912,36 +782,35 @@
return obj === Object(obj);
};
- // Add some isType methods: isArguments, isFunction, isString, isNumber, isDate, isRegExp.
- each(['Arguments', 'Function', 'String', 'Number', 'Date', 'RegExp'], function(name) {
- _['is' + name] = function(obj) {
- return toString.call(obj) == '[object ' + name + ']';
- };
- });
-
- // Define a fallback version of the method in browsers (ahem, IE), where
- // there isn't any inspectable "Arguments" type.
+ // Is a given variable an arguments object?
+ _.isArguments = function(obj) {
+ return toString.call(obj) == '[object Arguments]';
+ };
if (!_.isArguments(arguments)) {
_.isArguments = function(obj) {
return !!(obj && _.has(obj, 'callee'));
};
}
- // Optimize `isFunction` if appropriate.
- if (typeof (/./) !== 'function') {
- _.isFunction = function(obj) {
- return typeof obj === 'function';
- };
- }
-
- // Is a given object a finite number?
- _.isFinite = function(obj) {
- return _.isNumber(obj) && isFinite(obj);
+ // Is a given value a function?
+ _.isFunction = function(obj) {
+ return toString.call(obj) == '[object Function]';
};
- // Is the given value `NaN`? (NaN is the only number which does not equal itself).
+ // Is a given value a string?
+ _.isString = function(obj) {
+ return toString.call(obj) == '[object String]';
+ };
+
+ // Is a given value a number?
+ _.isNumber = function(obj) {
+ return toString.call(obj) == '[object Number]';
+ };
+
+ // Is the given value `NaN`?
_.isNaN = function(obj) {
- return _.isNumber(obj) && obj != +obj;
+ // `NaN` is the only value for which `===` is not reflexive.
+ return obj !== obj;
};
// Is a given value a boolean?
@@ -949,6 +818,16 @@
return obj === true || obj === false || toString.call(obj) == '[object Boolean]';
};
+ // Is a given value a date?
+ _.isDate = function(obj) {
+ return toString.call(obj) == '[object Date]';
+ };
+
+ // Is the given value a regular expression?
+ _.isRegExp = function(obj) {
+ return toString.call(obj) == '[object RegExp]';
+ };
+
// Is a given value equal to null?
_.isNull = function(obj) {
return obj === null;
@@ -959,8 +838,7 @@
return obj === void 0;
};
- // Shortcut function for checking if an object has a given property directly
- // on itself (in other words, not on a prototype).
+ // Has own property?
_.has = function(obj, key) {
return hasOwnProperty.call(obj, key);
};
@@ -981,65 +859,20 @@
};
// Run a function **n** times.
- _.times = function(n, iterator, context) {
+ _.times = function (n, iterator, context) {
for (var i = 0; i < n; i++) iterator.call(context, i);
};
- // Return a random integer between min and max (inclusive).
- _.random = function(min, max) {
- if (max == null) {
- max = min;
- min = 0;
- }
- return min + (0 | Math.random() * (max - min + 1));
+ // Escape a string for HTML interpolation.
+ _.escape = function(string) {
+ return (''+string).replace(/&/g, '&').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/'/g, ''').replace(/\//g,'/');
};
- // List of HTML entities for escaping.
- var entityMap = {
- escape: {
- '&': '&',
- '<': '<',
- '>': '>',
- '"': '"',
- "'": ''',
- '/': '/'
- }
- };
- entityMap.unescape = _.invert(entityMap.escape);
-
- // Regexes containing the keys and values listed immediately above.
- var entityRegexes = {
- escape: new RegExp('[' + _.keys(entityMap.escape).join('') + ']', 'g'),
- unescape: new RegExp('(' + _.keys(entityMap.unescape).join('|') + ')', 'g')
- };
-
- // Functions for escaping and unescaping strings to/from HTML interpolation.
- _.each(['escape', 'unescape'], function(method) {
- _[method] = function(string) {
- if (string == null) return '';
- return ('' + string).replace(entityRegexes[method], function(match) {
- return entityMap[method][match];
- });
- };
- });
-
- // If the value of the named property is a function then invoke it;
- // otherwise, return it.
- _.result = function(object, property) {
- if (object == null) return null;
- var value = object[property];
- return _.isFunction(value) ? value.call(object) : value;
- };
-
- // Add your own custom functions to the Underscore object.
+ // Add your own custom functions to the Underscore object, ensuring that
+ // they're correctly added to the OOP wrapper as well.
_.mixin = function(obj) {
each(_.functions(obj), function(name){
- var func = _[name] = obj[name];
- _.prototype[name] = function() {
- var args = [this._wrapped];
- push.apply(args, arguments);
- return result.call(this, func.apply(_, args));
- };
+ addToWrapper(name, _[name] = obj[name]);
});
};
@@ -1062,72 +895,41 @@
// When customizing `templateSettings`, if you don't want to define an
// interpolation, evaluation or escaping regex, we need one that is
// guaranteed not to match.
- var noMatch = /(.)^/;
+ var noMatch = /.^/;
- // Certain characters need to be escaped so that they can be put into a
- // string literal.
- var escapes = {
- "'": "'",
- '\\': '\\',
- '\r': 'r',
- '\n': 'n',
- '\t': 't',
- '\u2028': 'u2028',
- '\u2029': 'u2029'
+ // Within an interpolation, evaluation, or escaping, remove HTML escaping
+ // that had been previously added.
+ var unescape = function(code) {
+ return code.replace(/\\\\/g, '\\').replace(/\\'/g, "'");
};
- var escaper = /\\|'|\r|\n|\t|\u2028|\u2029/g;
-
// JavaScript micro-templating, similar to John Resig's implementation.
// Underscore templating handles arbitrary delimiters, preserves whitespace,
// and correctly escapes quotes within interpolated code.
- _.template = function(text, data, settings) {
- settings = _.defaults({}, settings, _.templateSettings);
-
- // Combine delimiters into one regular expression via alternation.
- var matcher = new RegExp([
- (settings.escape || noMatch).source,
- (settings.interpolate || noMatch).source,
- (settings.evaluate || noMatch).source
- ].join('|') + '|$', 'g');
-
- // Compile the template source, escaping string literals appropriately.
- var index = 0;
- var source = "__p+='";
- text.replace(matcher, function(match, escape, interpolate, evaluate, offset) {
- source += text.slice(index, offset)
- .replace(escaper, function(match) { return '\\' + escapes[match]; });
- source +=
- escape ? "'+\n((__t=(" + escape + "))==null?'':_.escape(__t))+\n'" :
- interpolate ? "'+\n((__t=(" + interpolate + "))==null?'':__t)+\n'" :
- evaluate ? "';\n" + evaluate + "\n__p+='" : '';
- index = offset + match.length;
- });
- source += "';\n";
-
- // If a variable is not specified, place data values in local scope.
- if (!settings.variable) source = 'with(obj||{}){\n' + source + '}\n';
-
- source = "var __t,__p='',__j=Array.prototype.join," +
- "print=function(){__p+=__j.call(arguments,'');};\n" +
- source + "return __p;\n";
-
- try {
- var render = new Function(settings.variable || 'obj', '_', source);
- } catch (e) {
- e.source = source;
- throw e;
- }
-
- if (data) return render(data, _);
- var template = function(data) {
- return render.call(this, data, _);
+ _.template = function(str, data) {
+ var c = _.templateSettings;
+ var tmpl = 'var __p=[],print=function(){__p.push.apply(__p,arguments);};' +
+ 'with(obj||{}){__p.push(\'' +
+ str.replace(/\\/g, '\\\\')
+ .replace(/'/g, "\\'")
+ .replace(c.escape || noMatch, function(match, code) {
+ return "',_.escape(" + unescape(code) + "),'";
+ })
+ .replace(c.interpolate || noMatch, function(match, code) {
+ return "'," + unescape(code) + ",'";
+ })
+ .replace(c.evaluate || noMatch, function(match, code) {
+ return "');" + unescape(code).replace(/[\r\n\t]/g, ' ') + ";__p.push('";
+ })
+ .replace(/\r/g, '\\r')
+ .replace(/\n/g, '\\n')
+ .replace(/\t/g, '\\t')
+ + "');}return __p.join('');";
+ var func = new Function('obj', '_', tmpl);
+ if (data) return func(data, _);
+ return function(data) {
+ return func.call(this, data, _);
};
-
- // Provide the compiled function source as a convenience for precompilation.
- template.source = 'function(' + (settings.variable || 'obj') + '){\n' + source + '}';
-
- return template;
};
// Add a "chain" function, which will delegate to the wrapper.
@@ -1135,15 +937,29 @@
return _(obj).chain();
};
- // OOP
+ // The OOP Wrapper
// ---------------
+
// If Underscore is called as a function, it returns a wrapped object that
// can be used OO-style. This wrapper holds altered versions of all the
// underscore functions. Wrapped objects may be chained.
+ var wrapper = function(obj) { this._wrapped = obj; };
+
+ // Expose `wrapper.prototype` as `_.prototype`
+ _.prototype = wrapper.prototype;
// Helper function to continue chaining intermediate results.
- var result = function(obj) {
- return this._chain ? _(obj).chain() : obj;
+ var result = function(obj, chain) {
+ return chain ? _(obj).chain() : obj;
+ };
+
+ // A method to easily add functions to the OOP wrapper.
+ var addToWrapper = function(name, func) {
+ wrapper.prototype[name] = function() {
+ var args = slice.call(arguments);
+ unshift.call(args, this._wrapped);
+ return result(func.apply(_, args), this._chain);
+ };
};
// Add all of the Underscore functions to the wrapper object.
@@ -1152,35 +968,32 @@
// Add all mutator Array functions to the wrapper.
each(['pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift'], function(name) {
var method = ArrayProto[name];
- _.prototype[name] = function() {
- var obj = this._wrapped;
- method.apply(obj, arguments);
- if ((name == 'shift' || name == 'splice') && obj.length === 0) delete obj[0];
- return result.call(this, obj);
+ wrapper.prototype[name] = function() {
+ var wrapped = this._wrapped;
+ method.apply(wrapped, arguments);
+ var length = wrapped.length;
+ if ((name == 'shift' || name == 'splice') && length === 0) delete wrapped[0];
+ return result(wrapped, this._chain);
};
});
// Add all accessor Array functions to the wrapper.
each(['concat', 'join', 'slice'], function(name) {
var method = ArrayProto[name];
- _.prototype[name] = function() {
- return result.call(this, method.apply(this._wrapped, arguments));
+ wrapper.prototype[name] = function() {
+ return result(method.apply(this._wrapped, arguments), this._chain);
};
});
- _.extend(_.prototype, {
+ // Start chaining a wrapped Underscore object.
+ wrapper.prototype.chain = function() {
+ this._chain = true;
+ return this;
+ };
- // Start chaining a wrapped Underscore object.
- chain: function() {
- this._chain = true;
- return this;
- },
-
- // Extracts the result from a wrapped and chained object.
- value: function() {
- return this._wrapped;
- }
-
- });
+ // Extracts the result from a wrapped and chained object.
+ wrapper.prototype.value = function() {
+ return this._wrapped;
+ };
}).call(this);
diff -r 55e7d7008efee2c5622f2505612265a9593ae992 -r 4bdb9214efd6ec510f2cc6e00224a467d36ba721 static/scripts/viz/sweepster.js
--- a/static/scripts/viz/sweepster.js
+++ b/static/scripts/viz/sweepster.js
@@ -3,8 +3,8 @@
* genomic visualization.
*/
-define(["libs/d3", "viz/trackster/util", "viz/visualization", "viz/trackster/tracks", "mvc/tools", "mvc/data"],
- function(d3, util, visualization, tracks, tools, data) {
+define(["libs/underscore", "libs/d3", "viz/trackster/util", "viz/visualization", "viz/trackster/tracks", "mvc/tools", "mvc/data"],
+ function(_, d3, util, visualization, tracks, tools, data) {
/**
* A collection of tool input settings. Object is useful for keeping a list of settings
diff -r 55e7d7008efee2c5622f2505612265a9593ae992 -r 4bdb9214efd6ec510f2cc6e00224a467d36ba721 static/scripts/viz/trackster/tracks.js
--- a/static/scripts/viz/trackster/tracks.js
+++ b/static/scripts/viz/trackster/tracks.js
@@ -1,7 +1,7 @@
define( ["libs/underscore", "viz/visualization", "viz/trackster/util",
"viz/trackster/slotting", "viz/trackster/painters", "mvc/data",
- "viz/trackster/filters", "viz/trackster_ui" ],
- function( _, visualization, util, slotting, painters, data, filters_mod, trackster_ui_mod ) {
+ "viz/trackster/filters" ],
+ function( _, visualization, util, slotting, painters, data, filters_mod ) {
var extend = _.extend;
var get_random_color = util.get_random_color;
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/55e7d7008efe/
changeset: 55e7d7008efe
user: afgane
date: 2012-10-02 03:03:00
summary: Fix workflow API imports
affected #: 1 file
diff -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 -r 55e7d7008efee2c5622f2505612265a9593ae992 lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -8,9 +8,10 @@
from sqlalchemy import desc
from galaxy import util
from galaxy import web
-from galaxy.tools.parameters import visit_input_values, DataToolParameter
+from galaxy import model
+from galaxy.tools.parameters import visit_input_values, DataToolParameter, RuntimeValue
from galaxy.web.base.controller import BaseAPIController, url_for
-from galaxy.workflow.modules import module_factory
+from galaxy.workflow.modules import module_factory, ToolModule
from galaxy.jobs.actions.post import ActionBox
from galaxy.model.item_attrs import UsesAnnotations
@@ -344,7 +345,7 @@
def _workflow_from_dict( self, trans, data, source=None ):
"""
- RPARK: copied from galaxy.web.controllers.workflows.py
+ RPARK: copied from galaxy.webapps.galaxy.controllers.workflows.py
Creates a workflow from a dict. Created workflow is stored in the database and returned.
"""
# Put parameters in workflow mode
@@ -388,7 +389,7 @@
# Stick this in the step temporarily
step.temp_input_connections = step_dict['input_connections']
# Save step annotation.
- annotation = step_dict[ 'annotation' ]
+ #annotation = step_dict[ 'annotation' ]
#if annotation:
#annotation = sanitize_html( annotation, 'utf-8', 'text/html' )
# ------------------------------------------ #
@@ -398,7 +399,7 @@
# Unpack and add post-job actions.
post_job_actions = step_dict.get( 'post_job_actions', {} )
for name, pja_dict in post_job_actions.items():
- pja = PostJobAction( pja_dict[ 'action_type' ],
+ model.PostJobAction( pja_dict[ 'action_type' ],
step, pja_dict[ 'output_name' ],
pja_dict[ 'action_arguments' ] )
# Second pass to deal with connections between steps
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: fixes and improvements to (alt)history - now renders history controls; fix to popupmenu parent parameter; pack scripts
by Bitbucket 01 Oct '12
by Bitbucket 01 Oct '12
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/3164ba737fd4/
changeset: 3164ba737fd4
user: carlfeberhard
date: 2012-10-02 00:25:35
summary: fixes and improvements to (alt)history - now renders history controls; fix to popupmenu parent parameter; pack scripts
affected #: 19 files
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 lib/galaxy/webapps/galaxy/controllers/root.py
--- a/lib/galaxy/webapps/galaxy/controllers/root.py
+++ b/lib/galaxy/webapps/galaxy/controllers/root.py
@@ -173,11 +173,19 @@
states = states.split( "," )
for encoded_id, state in zip( ids, states ):
try:
+ # assume encoded and decode to int
id = int( trans.app.security.decode_id( encoded_id ) )
except:
+ # fallback to non-encoded id
id = int( encoded_id )
+
+ # fetch new data for that id
data = trans.sa_session.query( self.app.model.HistoryDatasetAssociation ).get( id )
+
+ # if the state has changed,
if data.state != state:
+
+ # find out if we need to force a refresh on this data
job_hda = data
while job_hda.copied_from_history_dataset_association:
job_hda = job_hda.copied_from_history_dataset_association
@@ -187,12 +195,15 @@
if tool:
force_history_refresh = tool.force_history_refresh
if not job_hda.visible:
- force_history_refresh = True
+ force_history_refresh = True
+
+ # add the new state html for the item, the refresh option and the new state, map to the id
rval[encoded_id] = {
"state": data.state,
"html": unicode( trans.fill_template( "root/history_item.mako", data=data, hid=data.hid ), 'utf-8' ),
"force_history_refresh": force_history_refresh
}
+
return rval
@web.json
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/galaxy.base.js
--- a/static/scripts/galaxy.base.js
+++ b/static/scripts/galaxy.base.js
@@ -196,7 +196,7 @@
}
});
// locate the element with the id corresponding to the menu's popupmenu attr
- var box = $( "#" + menu.attr( 'popupmenu' ) );
+ var box = $( parent ).find( "#" + menu.attr( 'popupmenu' ) );
// For menus with clickable link text, make clicking on the link go through instead
// of activating the popup menu
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -69,6 +69,72 @@
}
};
+// =============================================================================
+/** Global string localization object (and global short form alias)
+ * set with either:
+ * GalaxyLocalization.setLocalizedString( original, localized )
+ * GalaxyLocalization.setLocalizedString({ original1 : localized1, original2 : localized2 })
+ * get with either:
+ * _l( original )
+ */
+//TODO: move to Galaxy.Localization (maybe galaxy.base.js)
+var GalaxyLocalization = jQuery.extend({}, {
+ aliasName : '_l',
+ localizedStrings : {},
+
+ setLocalizedString : function( str_or_obj, localizedString ){
+ // pass in either two strings (english, translated) or an obj (map) of english : translated attributes
+ //console.debug( this + '.setLocalizedString:', str_or_obj, localizedString );
+ var self = this;
+
+ // DRY non-duplicate assignment function
+ var setStringIfNotDuplicate = function( original, localized ){
+ // do not set if identical - strcmp expensive but should only happen once per page per word
+ if( original !== localized ){
+ self.localizedStrings[ original ] = localized;
+ }
+ };
+
+ if( jQuery.type( str_or_obj ) === "string" ){
+ setStringIfNotDuplicate( str_or_obj, localizedString );
+
+ } else if( jQuery.type( str_or_obj ) === "object" ){
+ jQuery.each( str_or_obj, function( key, val ){
+ //console.debug( 'key=>val', key, '=>', val );
+ // could recurse here but no reason
+ setStringIfNotDuplicate( key, val );
+ });
+
+ } else {
+ throw( 'Localization.setLocalizedString needs either a string or object as the first argument,' +
+ ' given: ' + str_or_obj );
+ }
+ },
+
+ localize : function( strToLocalize ){
+ //console.debug( this + '.localize:', strToLocalize );
+ // return the localized version if it's there, the strToLocalize if not
+ var retStr = strToLocalize;
+ if( _.has( this.localizedStrings, strToLocalize ) ){
+ //console.debug( 'found' );
+ retStr = this.localizedStrings[ strToLocalize ];
+ }
+ //console.debug( 'returning:', retStr );
+ return retStr;
+ },
+
+ toString : function(){ return 'GalaxyLocalization'; }
+});
+
+// global localization alias
+window[ GalaxyLocalization.aliasName ] = function( str ){ return GalaxyLocalization.localize( str ); };
+
+//TEST: setLocalizedString( string, string ), _l( string )
+//TEST: setLocalizedString( hash ), _l( string )
+//TEST: setLocalizedString( string === string ), _l( string )
+//TEST: _l( non assigned string )
+
+
//==============================================================================
/**
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/mvc/history.js
--- a/static/scripts/mvc/history.js
+++ b/static/scripts/mvc/history.js
@@ -6,71 +6,47 @@
Backbone.js implementation of history panel
TODO:
- replicate then refactor (could be the wrong order)
+ meta:
+ require.js
+ convert function comments to jsDoc style, complete comments
+ move inline styles into base.less
+ watch the magic strings
+ watch your globals
- fix:
- tags
- annotations
- _render_displayApps
- _render_downloadButton
- widget building (popupmenu, etc.)
- history.mako js: updater, etc.
- have info bodies prev. opened, redisplay on refresh
+ all:
+ add classes, ids on empty divs
+ incorporate relations?
+ events (local/ui and otherwise)
+ have info bodies prev. opened, redisplay on refresh
+ transfer history.mako js:
+ updater, etc.
+ create viz icon
+ trackster
+ scatterplot
+ phylo-viz
+ on ready:
+ delete function
+ check_transfer_status (running->ok)
+ quota meter update
+
+ historyItemView:
+ poly HistoryItemView (and HistoryView?) on: for_editing, display_structured, trans.user
+ don't draw body until it's first unhide event
+ HIview state transitions (eg. upload -> ok), curr: build new, delete old, place new (in render)
+ move visualizations menu
+ include phyloviz
- don't draw body until it's first unhide event
- all history.mako js -> this
- HIview state transitions (eg. upload -> ok), curr: build new, delete old, place new (in render)
- History (meta controls : collapse all, rename, annotate, etc. - see history.js.120823.bak)
- events (local/ui and otherwise)
- HistoryCollection: (collection of History: 'Saved Histories')
+ History:
+ renaming broken
+ tags rendering broken (url?)
+ annotation (url?)
+ meta controls : collapse all, rename, annotate, etc.
+
+ collection:
+ show_deleted, show_hidden (thru js - no refresh)
+
- ?move IconButtonViews -> templates?
-
- convert function comments to jsDoc style, complete comments
- collection -> show_deleted, show_hidden
- poly HistoryItemView on: for_editing, display_structured, trans.user
- incorporate relations?
- localization
- template helper {{#local}} calls _l()
-
- move inline styles into base.less
- add classes, ids on empty divs
- watch the magic strings
============================================================================= */
-
-//==============================================================================
-// jq plugin?
-//?? into template? I dunno: need to handle variadic keys, remove empty attrs (href="")
-//TODO: not happy with this (a 4th rendering/templating system!?) or it being global
-function linkHTMLTemplate( config, tag ){
- // Create an anchor (or any tag) using any config params passed in
- //NOTE!: send class attr as 'classes' to avoid res. keyword collision (jsLint)
- if( !config ){ return '<a></a>'; }
- tag = tag || 'a';
-
- var template = [ '<' + tag ];
- for( key in config ){
- var val = config[ key ];
- if( val === '' ){ continue; }
- switch( key ){
- case 'text': continue;
- case 'classes':
- // handle keyword class which is also an HTML attr name
- key = 'class';
- val = ( config.classes.join )?( config.classes.join( ' ' ) ):( config.classes );
- //note: lack of break (fall through)
- default:
- template.push( [ ' ', key, '="', val, '"' ].join( '' ) );
- }
- }
- template.push( '>' );
- if( 'text' in config ){ template.push( config.text ); }
- template.push( '</' + tag + '>' );
-
- return template.join( '' );
-}
-
-//==============================================================================
//TODO: use initialize (or validate) to check purged AND deleted -> purged XOR deleted
var HistoryItem = BaseModel.extend( LoggableMixin ).extend({
// a single HDA model
@@ -292,7 +268,6 @@
var deleteBtnData = {
title : 'Delete',
href : this.model.get( 'delete_url' ),
- target : 'galaxy_main',
id : 'historyItemDeleter-' + this.model.get( 'id' ),
icon_class : 'delete'
};
@@ -329,8 +304,7 @@
var primaryActionButtons = $( '<div/>' ).attr( 'id', 'primary-actions-' + this.model.get( 'id' ) ),
view = this;
_.each( buttonRenderingFuncs, function( fn ){
- var render_return = fn.call( view );
- primaryActionButtons.append( render_return );
+ primaryActionButtons.append( fn.call( view ) );
});
return primaryActionButtons;
},
@@ -342,8 +316,7 @@
// return either: a single download icon-button (if there are no meta files)
// or a popupmenu with links to download assoc. meta files (if there are meta files)
var downloadLinkHTML = HistoryItemView.templates.downloadLinks( this.model.toJSON() );
- this.log( '_render_downloadButton, downloadLinkHTML:', downloadLinkHTML );
-
+ //this.log( this + '_render_downloadButton, downloadLinkHTML:', downloadLinkHTML );
return $( downloadLinkHTML );
},
@@ -447,7 +420,7 @@
// ................................................................................ other elements
_render_tagArea : function(){
- if( this.model.get( 'retag_url' ) ){ return null; }
+ if( !this.model.get( 'retag_url' ) ){ return null; }
//TODO: move to mvc/tags.js
return $( HistoryItemView.templates.tagArea( this.model.toJSON() ) );
},
@@ -464,14 +437,14 @@
var displayAppsDiv = $( '<div/>' ).addClass( 'display-apps' );
if( !_.isEmpty( this.model.get( 'display_types' ) ) ){
- this.log( this + 'display_types:', this.model.get( 'display_types' ) );
+ //this.log( this + 'display_types:', this.model.get( 'display_types' ) );
//TODO:?? does this ever get used?
displayAppsDiv.append(
HistoryItemView.templates.displayApps({ displayApps : this.model.toJSON().display_types })
);
}
if( !_.isEmpty( this.model.get( 'display_apps' ) ) ){
- this.log( this + 'display_apps:', this.model.get( 'display_apps' ) );
+ //this.log( this + 'display_apps:', this.model.get( 'display_apps' ) );
displayAppsDiv.append(
HistoryItemView.templates.displayApps({ displayApps : this.model.toJSON().display_apps })
);
@@ -655,9 +628,10 @@
// Show or hide tag area; if showing tag area and it's empty, fill it.
if( tagArea.is( ":hidden" ) ){
- if( !tagElt.html() ){
+ if( !jQuery.trim( tagElt.html() ) ){
// Need to fill tag element.
$.ajax({
+ //TODO: the html from this breaks a couple of times
url: this.model.get( 'ajax_get_tag_url' ),
error: function() { alert( "Tagging failed" ); },
success: function(tag_elt_html) {
@@ -688,7 +662,7 @@
// Show or hide annotation area; if showing annotation area and it's empty, fill it.
if ( annotationArea.is( ":hidden" ) ){
- if( !annotationElem.html() ){
+ if( !jQuery.trim( annotationElem.html() ) ){
// Need to fill annotation element.
$.ajax({
url: this.model.get( 'ajax_get_annotation_url' ),
@@ -762,6 +736,7 @@
//==============================================================================
var History = BaseModel.extend( LoggableMixin ).extend({
+ //TODO: bind change events from items and collection to this (itemLengths, states)
// uncomment this out see log messages
//logger : console,
@@ -770,7 +745,8 @@
defaults : {
id : '',
name : '',
- state : '',
+ state : '',
+ //TODO:?? change these to a list of encoded ids?
state_details : {
discarded : 0,
empty : 0,
@@ -781,15 +757,51 @@
running : 0,
setting_metadata: 0,
upload : 0
- }
+ },
+
+ // maybe security issues...
+ userIsAdmin : false,
+ userRoles : [],
+ //TODO: hardcoded
+
+ //TODO: wire this to items
+ itemsLength : 0,
+ showDeleted : false,
+ showHidden : false,
+
+ diskSize : 0,
+ deleted : false,
+
+ // tagging_common.mako: render_individual_tagging_element(user=trans.get_user(),
+ // tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20")
+ tags : [],
+ annotation : null,
+ message : null,
+ quotaMsg : false,
+
+ baseURL : null,
+ hideDeletedURL : null,
+ hideHiddenURL : null,
+ tagURL : null,
+ annotateURL : null
},
initialize : function( data, history_datasets ){
- this.log( this + '.initialize', data, history_datasets );
+ //this.log( this + '.initialize', data, history_datasets );
this.items = new HistoryCollection();
},
+ toJSON : function(){
+ // unfortunately, bb doesn't call 'get' to form the JSON meaning computed vals from get aren't used, so...
+ // a simple example of override and super call
+ var json = Backbone.Model.prototype.toJSON.call( this );
+ json.itemsLength = this.items.length;
+ //this.log( this + '.json:', json );
+ return json;
+ },
+
loadDatasetsAsHistoryItems : function( datasets ){
+ //TODO: add via ajax - multiple datasets at once
// adds the given dataset/Item data to historyItems
// and updates this.state based on their states
//pre: datasets is a list of objs
@@ -799,12 +811,12 @@
stateDetails = this.get( 'state_details' );
_.each( datasets, function( dataset, index ){
- self.log( 'loading dataset: ', dataset, index );
+ //self.log( 'loading dataset: ', dataset, index );
// create an item sending along the history_id as well
var historyItem = new HistoryItem(
_.extend( dataset, { history_id: selfID } ) );
- self.log( 'as History:', historyItem );
+ //self.log( 'as History:', historyItem );
self.items.add( historyItem );
// add item's state to running totals in stateDetails
@@ -864,28 +876,42 @@
// direct attachment to existing element
el : 'body.historyPage',
- initialize : function(){
- this.log( this + '.initialize' );
+ initialize : function(){
+ this.log( this + '.initialize:', this );
this.itemViews = [];
var parent = this;
this.model.items.each( function( item ){
var itemView = new HistoryItemView({ model: item });
parent.itemViews.push( itemView );
});
- //itemViews.reverse();
},
- render : function(){
- this.log( this + '.render' );
+ render : function(){
+ this.$el.append( HistoryView.templates.historyPanel( this.model.toJSON() ) );
+ this.log( this + ' rendered from template:', this.$el );
- // render to temp, move all at once, remove temp holder
+ // set up aliases
+ this.itemsDiv = this.$el.find( '#' + this.model.get( 'id' ) + '-datasets' );
+
+ //TODO: set up widgets, tooltips, etc.
+
+ if( this.model.items.length ){
+ // render to temp, move all at once, remove temp holder
+ var tempDiv = this._render_items();
+ this.itemsDiv.append( tempDiv.children() );
+ tempDiv.remove();
+ }
+ },
+
+ _render_items : function(){
+ var div = $( '<div/>' ),
+ view = this;
//NOTE!: render in reverse (newest on top) via prepend (instead of append)
- var tempDiv = $( '<div/>' );
- _.each( this.itemViews, function( view ){
- tempDiv.prepend( view.render() );
+ _.each( this.itemViews, function( itemView ){
+ view.log( view + '.render_items:', itemView );
+ div.prepend( itemView.render() );
});
- this.$el.append( tempDiv.children() );
- tempDiv.remove();
+ return div;
},
toString : function(){
@@ -893,6 +919,13 @@
return 'HistoryView(' + nameString + ')';
}
});
+//HistoryItemView.templates = InDomTemplateLoader.getTemplates({
+HistoryView.templates = CompiledTemplateLoader.getTemplates({
+ 'history-templates.html' : {
+ historyPanel : 'template-history-historyPanel'
+ }
+});
+
//==============================================================================
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -157,79 +157,10 @@
}
});
-// =============================================================================
-/** Global string localization object (and global short form alias)
- * set with either:
- * GalaxyLocalization.setLocalizedString( original, localized )
- * GalaxyLocalization.setLocalizedString({ original1 : localized1, original2 : localized2 })
- * get with either:
- * _l( original )
- */
-//TODO: move to Galaxy.Localization
-var GalaxyLocalization = jQuery.extend({}, {
- aliasName : '_l',
- localizedStrings : {},
-
- setLocalizedString : function( str_or_obj, localizedString ){
- // pass in either two strings (english, translated) or an obj (map) of english : translated attributes
- //console.debug( this + '.setLocalizedString:', str_or_obj, localizedString );
- var self = this;
-
- // DRY non-duplicate assignment function
- var setStringIfNotDuplicate = function( original, localized ){
- // do not set if identical - strcmp expensive but should only happen once per page per word
- if( original !== localized ){
- self.localizedStrings[ original ] = localized;
- }
- };
-
- if( jQuery.type( str_or_obj ) === "string" ){
- setStringIfNotDuplicate( str_or_obj, localizedString );
-
- } else if( jQuery.type( str_or_obj ) === "object" ){
- jQuery.each( str_or_obj, function( key, val ){
- //console.debug( 'key=>val', key, '=>', val );
- // could recurse here but no reason
- setStringIfNotDuplicate( key, val );
- });
-
- } else {
- throw( 'Localization.setLocalizedString needs either a string or object as the first argument,' +
- ' given: ' + str_or_obj );
- }
- },
-
- localize : function( strToLocalize ){
- //console.debug( this + '.localize:', strToLocalize );
- // return the localized version if it's there, the strToLocalize if not
- // try/catch cheaper than if in
- try {
- //var localized = this.localizedStrings[ strToLocalize ];
- //return localized;
- return this.localizedStrings[ strToLocalize ];
- } catch( err ){
- //TODO??: potentially problematic catch all
- //console.error( err );
- return strToLocalize;
- }
- },
-
- toString : function(){ return 'GalaxyLocalization'; }
-});
-// global localization alias
-window[ GalaxyLocalization.aliasName ] = function( str ){ return GalaxyLocalization.localize( str ); };
-//TEST: setLocalizedString( string, string ), _l( string )
-//TEST: setLocalizedString( hash ), _l( string )
-//TEST: setLocalizedString( string === string ), _l( string )
-//TEST: _l( non assigned string )
-// =============================================================================
-/** UI icon-button (Backbone.View only - no model)
- *
- */
@@ -239,8 +170,3 @@
-
-
-
-
-
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/galaxy.base.js
--- a/static/scripts/packed/galaxy.base.js
+++ b/static/scripts/packed/galaxy.base.js
@@ -1,1 +1,1 @@
-(function(){var b=0;var c=["ms","moz","webkit","o"];for(var a=0;a<c.length&&!window.requestAnimationFrame;++a){window.requestAnimationFrame=window[c[a]+"RequestAnimationFrame"];window.cancelRequestAnimationFrame=window[c[a]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(h,e){var d=new Date().getTime();var f=Math.max(0,16-(d-b));var g=window.setTimeout(function(){h(d+f)},f);b=d+f;return g}}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(d){clearTimeout(d)}}}());if(!Array.indexOf){Array.prototype.indexOf=function(c){for(var b=0,a=this.length;b<a;b++){if(this[b]==c){return b}}return -1}}function obj_length(c){if(c.length!==undefined){return c.length}var b=0;for(var a in c){b++}return b}$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function make_popupmenu(b,c){var a=(b.data("menu_options"));b.data("menu_options",c);if(a){return}b.bind("click.show_popup",function(d){$(".popmenu-wrapper").remove();setTimeout(function(){var g=$("<ul class='dropdown-menu' id='"+b.attr("id")+"-menu'></ul>");var f=b.data("menu_options");if(obj_length(f)<=0){$("<li>No Options.</li>").appendTo(g)}$.each(f,function(j,i){if(i){g.append($("<li></li>").append($("<a href='#'></a>").html(j).click(i)))}else{g.append($("<li></li>").addClass("head").append($("<a href='#'></a>").html(j)))}});var h=$("<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>").append(g).appendTo("body");var e=d.pageX-h.width()/2;e=Math.min(e,$(document).scrollLeft()+$(window).width()-$(h).width()-5);e=Math.max(e,$(document).scrollLeft()+5);h.css({top:d.pageY,left:e})},10);setTimeout(function(){var f=function(h){$(h).bind("click.close_popup",function(){$(".popmenu-wrapper").remove();h.unbind("click.close_popup")})};f($(window.document));f($(window.top.document));for(var e=window.top.frames.length;e--;){var g=$(window.top.frames[e].document);f(g)}},50);return false})}function make_popup_menus(a){a=a||document;$(a).find("div[popupmenu]").each(function(){var b={};var d=$(this);d.find("a").each(function(){var g=$(this),i=g.get(0),e=i.getAttribute("confirm"),f=i.getAttribute("href"),h=i.getAttribute("target");if(!f){b[g.text()]=null}else{b[g.text()]=function(){if(!e||confirm(e)){var j;if(h=="_parent"){window.parent.location=f}else{if(h=="_top"){window.top.location=f}else{if(h=="demo"){if(j===undefined||j.closed){j=window.open(f,h);j.creator=self}}else{window.location=f}}}}}}});var c=$("#"+d.attr("popupmenu"));c.find("a").bind("click",function(f){f.stopPropagation();return true});make_popupmenu(c,b);c.addClass("popup");d.remove()})}function naturalSort(j,h){var p=/(-?[0-9\.]+)/g,k=j.toString().toLowerCase()||"",g=h.toString().toLowerCase()||"",l=String.fromCharCode(0),n=k.replace(p,l+"$1"+l).split(l),e=g.replace(p,l+"$1"+l).split(l),d=(new Date(k)).getTime(),o=d?(new Date(g)).getTime():null;if(o){if(d<o){return -1}else{if(d>o){return 1}}}var m,f;for(var i=0,c=Math.max(n.length,e.length);i<c;i++){m=parseFloat(n[i])||n[i];f=parseFloat(e[i])||e[i];if(m<f){return -1}else{if(m>f){return 1}}}return 0}function replace_big_select_inputs(a,c,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(c===undefined){c=3000}var b=b||$("select");b.each(function(){var e=$(this);var h=e.find("option").length;if((h<a)||(h>c)){return}if(e.attr("multiple")==="multiple"){return}if(e.hasClass("no-autocomplete")){return}var n=e.attr("value");var d=$("<input type='text' class='text-and-autocomplete-select'></input>");d.attr("size",40);d.attr("name",e.attr("name"));d.attr("id",e.attr("id"));d.click(function(){var o=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(o);$(this).select()});var f=[];var j={};e.children("option").each(function(){var p=$(this).text();var o=$(this).attr("value");f.push(p);j[p]=o;j[o]=o;if(o==n){d.attr("value",p)}});if(n===""||n==="?"){d.attr("value","Click to Search or Select")}if(e.attr("name")=="dbkey"){f=f.sort(naturalSort)}var g={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:c,minChars:0,hideForLessThanMinChars:false};d.autocomplete(f,g);e.replaceWith(d);var l=function(){var p=d.attr("value");var o=j[p];if(o!==null&&o!==undefined){d.attr("value",o)}else{if(n!==""){d.attr("value",n)}else{d.attr("value","?")}}};d.parents("form").submit(function(){l()});$(document).bind("convert_to_values",function(){l()});if(e.attr("refresh_on_change")=="true"){var i=e.attr("refresh_on_change_values"),m=e.attr("last_selected_value");if(i!==undefined){i=i.split(",")}var k=function(){var o=j[d.attr("value")];if(m!==o&&o!==null&&o!==undefined){if(i!==undefined&&$.inArray(o,i)===-1&&$.inArray(m,i)===-1){return}d.attr("value",o);$(window).trigger("refresh_on_change");d.parents("form").submit()}};d.bind("result",k);d.keyup(function(o){if(o.keyCode===13){k()}});d.keydown(function(o){if(o.keyCode===13){return false}})}})}$.fn.make_text_editable=function(g){var d=("num_cols" in g?g.num_cols:30),c=("num_rows" in g?g.num_rows:4),e=("use_textarea" in g?g.use_textarea:false),b=("on_finish" in g?g.on_finish:null),f=("help_text" in g?g.help_text:null);var a=$(this);a.addClass("editable-text").click(function(l){if($(this).children(":input").length>0){return}a.removeClass("editable-text");var i=function(m){a.find(":input").remove();if(m!==""){a.text(m)}else{a.html("<br>")}a.addClass("editable-text");if(b){b(m)}};var h=a.text(),k,j;if(e){k=$("<textarea/>").attr({rows:c,cols:d}).text($.trim(h)).keyup(function(m){if(m.keyCode===27){i(h)}});j=$("<button/>").text("Done").click(function(){i(k.val());return false})}else{k=$("<input type='text'/>").attr({value:$.trim(h),size:d}).blur(function(){i(h)}).keyup(function(m){if(m.keyCode===27){$(this).trigger("blur")}else{if(m.keyCode===13){i($(this).val())}}})}a.text("");a.append(k);if(j){a.append(j)}k.focus();k.select();l.stopPropagation()});if(f){a.attr("title",f).tooltip()}return a};function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text($.trim(k))}else{j=$("<input type='text'></input>").attr({value:$.trim(k),size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){if(o!==""){l.text(o)}else{l.html("<em>None</em>")}if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStorage.get("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStorage.deleteKey("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id,h=$(this).children("div.historyItemBody"),i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){var k;if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){k=$.jStorage.get("history_expand_state");if(k){delete k[j];$.jStorage.set("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){k=$.jStorage.get("history_expand_state");if(!k){k={}}k[j]=true;$.jStorage.set("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStorage.get("history_expand_state");if(!h){h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStorage.set("history_expand_state",h)}).show()};b()}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length===0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools")}}var GalaxyAsync=function(a){this.url_dict={};this.log_action=(a===undefined?false:a)};GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("select[refresh_on_change='true']").change(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");$(document).trigger("convert_to_values");a.get(0).form.submit()});$(":checkbox[refresh_on_change='true']").click(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");a.get(0).form.submit()});$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tooltip){$(".tooltip").tooltip({placement:"top"})}make_popup_menus();replace_big_select_inputs(20,1500);$("a").click(function(){var b=$(this);var c=(parent.frames&&parent.frames.galaxy_main);if((b.attr("target")=="galaxy_main")&&(!c)){var a=b.attr("href");if(a.indexOf("?")==-1){a+="?"}else{a+="&"}a+="use_panels=True";b.attr("href",a);b.attr("target","_self")}return b})});
\ No newline at end of file
+(function(){var b=0;var c=["ms","moz","webkit","o"];for(var a=0;a<c.length&&!window.requestAnimationFrame;++a){window.requestAnimationFrame=window[c[a]+"RequestAnimationFrame"];window.cancelRequestAnimationFrame=window[c[a]+"CancelRequestAnimationFrame"]}if(!window.requestAnimationFrame){window.requestAnimationFrame=function(h,e){var d=new Date().getTime();var f=Math.max(0,16-(d-b));var g=window.setTimeout(function(){h(d+f)},f);b=d+f;return g}}if(!window.cancelAnimationFrame){window.cancelAnimationFrame=function(d){clearTimeout(d)}}}());if(!Array.indexOf){Array.prototype.indexOf=function(c){for(var b=0,a=this.length;b<a;b++){if(this[b]==c){return b}}return -1}}function obj_length(c){if(c.length!==undefined){return c.length}var b=0;for(var a in c){b++}return b}$.fn.makeAbsolute=function(a){return this.each(function(){var b=$(this);var c=b.position();b.css({position:"absolute",marginLeft:0,marginTop:0,top:c.top,left:c.left,right:$(window).width()-(c.left+b.width())});if(a){b.remove().appendTo("body")}})};function make_popupmenu(b,c){var a=(b.data("menu_options"));b.data("menu_options",c);if(a){return}b.bind("click.show_popup",function(d){$(".popmenu-wrapper").remove();setTimeout(function(){var g=$("<ul class='dropdown-menu' id='"+b.attr("id")+"-menu'></ul>");var f=b.data("menu_options");if(obj_length(f)<=0){$("<li>No Options.</li>").appendTo(g)}$.each(f,function(j,i){if(i){g.append($("<li></li>").append($("<a href='#'></a>").html(j).click(i)))}else{g.append($("<li></li>").addClass("head").append($("<a href='#'></a>").html(j)))}});var h=$("<div class='popmenu-wrapper' style='position: absolute;left: 0; top: -1000;'></div>").append(g).appendTo("body");var e=d.pageX-h.width()/2;e=Math.min(e,$(document).scrollLeft()+$(window).width()-$(h).width()-5);e=Math.max(e,$(document).scrollLeft()+5);h.css({top:d.pageY,left:e})},10);setTimeout(function(){var f=function(h){$(h).bind("click.close_popup",function(){$(".popmenu-wrapper").remove();h.unbind("click.close_popup")})};f($(window.document));f($(window.top.document));for(var e=window.top.frames.length;e--;){var g=$(window.top.frames[e].document);f(g)}},50);return false})}function make_popup_menus(a){a=a||document;$(a).find("div[popupmenu]").each(function(){var b={};var d=$(this);d.find("a").each(function(){var g=$(this),i=g.get(0),e=i.getAttribute("confirm"),f=i.getAttribute("href"),h=i.getAttribute("target");if(!f){b[g.text()]=null}else{b[g.text()]=function(){if(!e||confirm(e)){var j;if(h=="_parent"){window.parent.location=f}else{if(h=="_top"){window.top.location=f}else{if(h=="demo"){if(j===undefined||j.closed){j=window.open(f,h);j.creator=self}}else{window.location=f}}}}}}});var c=$(a).find("#"+d.attr("popupmenu"));c.find("a").bind("click",function(f){f.stopPropagation();return true});make_popupmenu(c,b);c.addClass("popup");d.remove()})}function naturalSort(j,h){var p=/(-?[0-9\.]+)/g,k=j.toString().toLowerCase()||"",g=h.toString().toLowerCase()||"",l=String.fromCharCode(0),n=k.replace(p,l+"$1"+l).split(l),e=g.replace(p,l+"$1"+l).split(l),d=(new Date(k)).getTime(),o=d?(new Date(g)).getTime():null;if(o){if(d<o){return -1}else{if(d>o){return 1}}}var m,f;for(var i=0,c=Math.max(n.length,e.length);i<c;i++){m=parseFloat(n[i])||n[i];f=parseFloat(e[i])||e[i];if(m<f){return -1}else{if(m>f){return 1}}}return 0}function replace_big_select_inputs(a,c,b){if(!jQuery().autocomplete){return}if(a===undefined){a=20}if(c===undefined){c=3000}var b=b||$("select");b.each(function(){var e=$(this);var h=e.find("option").length;if((h<a)||(h>c)){return}if(e.attr("multiple")==="multiple"){return}if(e.hasClass("no-autocomplete")){return}var n=e.attr("value");var d=$("<input type='text' class='text-and-autocomplete-select'></input>");d.attr("size",40);d.attr("name",e.attr("name"));d.attr("id",e.attr("id"));d.click(function(){var o=$(this).val();$(this).val("Loading...");$(this).showAllInCache();$(this).val(o);$(this).select()});var f=[];var j={};e.children("option").each(function(){var p=$(this).text();var o=$(this).attr("value");f.push(p);j[p]=o;j[o]=o;if(o==n){d.attr("value",p)}});if(n===""||n==="?"){d.attr("value","Click to Search or Select")}if(e.attr("name")=="dbkey"){f=f.sort(naturalSort)}var g={selectFirst:false,autoFill:false,mustMatch:false,matchContains:true,max:c,minChars:0,hideForLessThanMinChars:false};d.autocomplete(f,g);e.replaceWith(d);var l=function(){var p=d.attr("value");var o=j[p];if(o!==null&&o!==undefined){d.attr("value",o)}else{if(n!==""){d.attr("value",n)}else{d.attr("value","?")}}};d.parents("form").submit(function(){l()});$(document).bind("convert_to_values",function(){l()});if(e.attr("refresh_on_change")=="true"){var i=e.attr("refresh_on_change_values"),m=e.attr("last_selected_value");if(i!==undefined){i=i.split(",")}var k=function(){var o=j[d.attr("value")];if(m!==o&&o!==null&&o!==undefined){if(i!==undefined&&$.inArray(o,i)===-1&&$.inArray(m,i)===-1){return}d.attr("value",o);$(window).trigger("refresh_on_change");d.parents("form").submit()}};d.bind("result",k);d.keyup(function(o){if(o.keyCode===13){k()}});d.keydown(function(o){if(o.keyCode===13){return false}})}})}$.fn.make_text_editable=function(g){var d=("num_cols" in g?g.num_cols:30),c=("num_rows" in g?g.num_rows:4),e=("use_textarea" in g?g.use_textarea:false),b=("on_finish" in g?g.on_finish:null),f=("help_text" in g?g.help_text:null);var a=$(this);a.addClass("editable-text").click(function(l){if($(this).children(":input").length>0){return}a.removeClass("editable-text");var i=function(m){a.find(":input").remove();if(m!==""){a.text(m)}else{a.html("<br>")}a.addClass("editable-text");if(b){b(m)}};var h=a.text(),k,j;if(e){k=$("<textarea/>").attr({rows:c,cols:d}).text($.trim(h)).keyup(function(m){if(m.keyCode===27){i(h)}});j=$("<button/>").text("Done").click(function(){i(k.val());return false})}else{k=$("<input type='text'/>").attr({value:$.trim(h),size:d}).blur(function(){i(h)}).keyup(function(m){if(m.keyCode===27){$(this).trigger("blur")}else{if(m.keyCode===13){i($(this).val())}}})}a.text("");a.append(k);if(j){a.append(j)}k.focus();k.select();l.stopPropagation()});if(f){a.attr("title",f).tooltip()}return a};function async_save_text(d,f,e,a,c,h,i,g,b){if(c===undefined){c=30}if(i===undefined){i=4}$("#"+d).live("click",function(){if($("#renaming-active").length>0){return}var l=$("#"+f),k=l.text(),j;if(h){j=$("<textarea></textarea>").attr({rows:i,cols:c}).text($.trim(k))}else{j=$("<input type='text'></input>").attr({value:$.trim(k),size:c})}j.attr("id","renaming-active");j.blur(function(){$(this).remove();l.show();if(b){b(j)}});j.keyup(function(n){if(n.keyCode===27){$(this).trigger("blur")}else{if(n.keyCode===13){var m={};m[a]=$(this).val();$(this).trigger("blur");$.ajax({url:e,data:m,error:function(){alert("Text editing for elt "+f+" failed")},success:function(o){if(o!==""){l.text(o)}else{l.html("<em>None</em>")}if(b){b(j)}}})}}});if(g){g(j)}l.hide();j.insertAfter(l);j.focus();j.select();return})}function init_history_items(d,a,c){var b=function(){try{var e=$.jStorage.get("history_expand_state");if(e){for(var g in e){$("#"+g+" div.historyItemBody").show()}}}catch(f){$.jStorage.deleteKey("history_expand_state")}if($.browser.mozilla){$("div.historyItemBody").each(function(){if(!$(this).is(":visible")){$(this).find("pre.peek").css("overflow","hidden")}})}d.each(function(){var j=this.id,h=$(this).children("div.historyItemBody"),i=h.find("pre.peek");$(this).find(".historyItemTitleBar > .historyItemTitle").wrap("<a href='javascript:void(0);'></a>").click(function(){var k;if(h.is(":visible")){if($.browser.mozilla){i.css("overflow","hidden")}h.slideUp("fast");if(!c){k=$.jStorage.get("history_expand_state");if(k){delete k[j];$.jStorage.set("history_expand_state",k)}}}else{h.slideDown("fast",function(){if($.browser.mozilla){i.css("overflow","auto")}});if(!c){k=$.jStorage.get("history_expand_state");if(!k){k={}}k[j]=true;$.jStorage.set("history_expand_state",k)}}return false})});$("#top-links > a.toggle").click(function(){var h=$.jStorage.get("history_expand_state");if(!h){h={}}$("div.historyItemBody:visible").each(function(){if($.browser.mozilla){$(this).find("pre.peek").css("overflow","hidden")}$(this).slideUp("fast");if(h){delete h[$(this).parent().attr("id")]}});$.jStorage.set("history_expand_state",h)}).show()};b()}function commatize(b){b+="";var a=/(\d+)(\d{3})/;while(a.test(b)){b=b.replace(a,"$1,$2")}return b}function reset_tool_search(a){var c=$("#galaxy_tools").contents();if(c.length===0){c=$(document)}$(this).removeClass("search_active");c.find(".toolTitle").removeClass("search_match");c.find(".toolSectionBody").hide();c.find(".toolTitle").show();c.find(".toolPanelLabel").show();c.find(".toolSectionWrapper").each(function(){if($(this).attr("id")!="recently_used_wrapper"){$(this).show()}else{if($(this).hasClass("user_pref_visible")){$(this).show()}}});c.find("#search-no-results").hide();c.find("#search-spinner").hide();if(a){var b=c.find("#tool-search-query");b.val("search tools")}}var GalaxyAsync=function(a){this.url_dict={};this.log_action=(a===undefined?false:a)};GalaxyAsync.prototype.set_func_url=function(a,b){this.url_dict[a]=b};GalaxyAsync.prototype.set_user_pref=function(a,b){var c=this.url_dict[arguments.callee];if(c===undefined){return false}$.ajax({url:c,data:{pref_name:a,pref_value:b},error:function(){return false},success:function(){return true}})};GalaxyAsync.prototype.log_user_action=function(c,b,d){if(!this.log_action){return}var a=this.url_dict[arguments.callee];if(a===undefined){return false}$.ajax({url:a,data:{action:c,context:b,params:d},error:function(){return false},success:function(){return true}})};$(document).ready(function(){$("select[refresh_on_change='true']").change(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");$(document).trigger("convert_to_values");a.get(0).form.submit()});$(":checkbox[refresh_on_change='true']").click(function(){var a=$(this),e=a.val(),d=false,c=a.attr("refresh_on_change_values");if(c){c=c.split(",");var b=a.attr("last_selected_value");if($.inArray(e,c)===-1&&$.inArray(b,c)===-1){return}}$(window).trigger("refresh_on_change");a.get(0).form.submit()});$("a[confirm]").click(function(){return confirm($(this).attr("confirm"))});if($.fn.tooltip){$(".tooltip").tooltip({placement:"top"})}make_popup_menus();replace_big_select_inputs(20,1500);$("a").click(function(){var b=$(this);var c=(parent.frames&&parent.frames.galaxy_main);if((b.attr("target")=="galaxy_main")&&(!c)){var a=b.attr("href");if(a.indexOf("?")==-1){a+="?"}else{a+="&"}a+="use_panels=True";b.attr("href",a);b.attr("target","_self")}return b})});
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/mvc/base-mvc.js
--- a/static/scripts/packed/mvc/base-mvc.js
+++ b/static/scripts/packed/mvc/base-mvc.js
@@ -1,1 +1,1 @@
-var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){if(this.model.attributes.hidden){this.$el.hide()}else{this.$el.show()}}});var LoggableMixin={logger:null,log:function(){return(this.logger)?(this.logger.log.apply(this,arguments)):(undefined)}};var TemplateLoader=_.extend({},LoggableMixin,{getTemplateLoadFn:function(){throw ("There is no templateLoadFn. Make sure you're using a subclass of TemplateLoader")},getTemplates:function(d,e){e=e||false;this.log(this,"getTemplates:",d,", forceReload:",e);var c={},a=this,b=this.getTemplateLoadFn();if(!d){return c}jQuery.each(d,function(f,g){jQuery.each(g,function(h,i){a.log(a+", templateFile:",f,"templateName:",h,", templateID:",i);c[h]=b.call(a,f,h,i)})});return c}});var CompiledTemplateLoader=_.extend({},TemplateLoader,{getTemplateLoadFn:function(){return this.loadCompiledHandlebarsTemplate},loadCompiledHandlebarsTemplate:function(b,a,c){this.log("getInDomTemplates, templateFile:",b,"templateName:",a,", templateID:",c);if(!Handlebars.templates||!Handlebars.templates[c]){throw ("Template not found: Handlebars."+c+". Check your h.templates() call in the mako file that rendered this page")}this.log("found template function:",c);return Handlebars.templates[c]}});var InDomTemplateLoader=_.extend({},TemplateLoader,{compileTemplate:function(a){if(!Handlebars||!Handlebars.compile){throw ("No Handlebars.compile found. You may only have Handlebars.runtime loaded.Include handlebars.full for this to work")}this.log("compiling template:",a);return Handlebars.compile(a)},findTemplateInDom:function(b,a,c){return $("script#"+c).last()},getTemplateLoadFn:function(){return this.loadInDomTemplate},loadInDomTemplate:function(b,a,c){this.log("getInDomTemplate, templateFile:",b,"templateName:",a,", templateID:",c);var d=this.findTemplateInDom(b,a,c);if(!d||!d.length){throw ("Template not found within the DOM: "+c+". Check that this template has been included in the page")}this.log("found template in dom:",d.html());return this.compileTemplate(d.html())}});var RemoteTemplateLoader=_.extend({},InDomTemplateLoader,{templateBaseURL:"static/scripts/templates/",getTemplateLoadFn:function(){return this.loadViaHttpGet},loadViaHttpGet:function(d,c,f){var b="static/scripts/templates/";this.log("loadViaHttpGet, templateFile:",d,"templateName:",c,", templateID:",f,"templateBaseURL:",this.templateBaseURL);var h=null;try{h=this.loadInDomTemplate(d,c,f)}catch(g){this.log("getInDomTemplate exception:"+g);if(!Handlebars.compile){throw (g)}this.log("Couldn't locate template in DOM: "+f);var a=this;var e=b+d;jQuery.ajax(e,{method:"GET",async:false,success:function(i){a.log(d+" loaded via GET. Attempting compile...");$("body").append(i);h=a.loadInDomTemplate(d,c,f)},error:function(j,i,k){throw ("Failed to fetch "+e+":"+i)}})}if(!h){throw ("Couldn't load or fetch template: "+f)}return h}});
\ No newline at end of file
+var BaseModel=Backbone.RelationalModel.extend({defaults:{name:null,hidden:false},show:function(){this.set("hidden",false)},hide:function(){this.set("hidden",true)},is_visible:function(){return !this.attributes.hidden}});var BaseView=Backbone.View.extend({initialize:function(){this.model.on("change:hidden",this.update_visible,this);this.update_visible()},update_visible:function(){if(this.model.attributes.hidden){this.$el.hide()}else{this.$el.show()}}});var LoggableMixin={logger:null,log:function(){return(this.logger)?(this.logger.log.apply(this,arguments)):(undefined)}};var GalaxyLocalization=jQuery.extend({},{aliasName:"_l",localizedStrings:{},setLocalizedString:function(b,a){var c=this;var d=function(f,e){if(f!==e){c.localizedStrings[f]=e}};if(jQuery.type(b)==="string"){d(b,a)}else{if(jQuery.type(b)==="object"){jQuery.each(b,function(e,f){d(e,f)})}else{throw ("Localization.setLocalizedString needs either a string or object as the first argument, given: "+b)}}},localize:function(b){var a=b;if(_.has(this.localizedStrings,b)){a=this.localizedStrings[b]}return a},toString:function(){return"GalaxyLocalization"}});window[GalaxyLocalization.aliasName]=function(a){return GalaxyLocalization.localize(a)};var TemplateLoader=_.extend({},LoggableMixin,{getTemplateLoadFn:function(){throw ("There is no templateLoadFn. Make sure you're using a subclass of TemplateLoader")},getTemplates:function(d,e){e=e||false;this.log(this,"getTemplates:",d,", forceReload:",e);var c={},a=this,b=this.getTemplateLoadFn();if(!d){return c}jQuery.each(d,function(f,g){jQuery.each(g,function(h,i){a.log(a+", templateFile:",f,"templateName:",h,", templateID:",i);c[h]=b.call(a,f,h,i)})});return c}});var CompiledTemplateLoader=_.extend({},TemplateLoader,{getTemplateLoadFn:function(){return this.loadCompiledHandlebarsTemplate},loadCompiledHandlebarsTemplate:function(b,a,c){this.log("getInDomTemplates, templateFile:",b,"templateName:",a,", templateID:",c);if(!Handlebars.templates||!Handlebars.templates[c]){throw ("Template not found: Handlebars."+c+". Check your h.templates() call in the mako file that rendered this page")}this.log("found template function:",c);return Handlebars.templates[c]}});var InDomTemplateLoader=_.extend({},TemplateLoader,{compileTemplate:function(a){if(!Handlebars||!Handlebars.compile){throw ("No Handlebars.compile found. You may only have Handlebars.runtime loaded.Include handlebars.full for this to work")}this.log("compiling template:",a);return Handlebars.compile(a)},findTemplateInDom:function(b,a,c){return $("script#"+c).last()},getTemplateLoadFn:function(){return this.loadInDomTemplate},loadInDomTemplate:function(b,a,c){this.log("getInDomTemplate, templateFile:",b,"templateName:",a,", templateID:",c);var d=this.findTemplateInDom(b,a,c);if(!d||!d.length){throw ("Template not found within the DOM: "+c+". Check that this template has been included in the page")}this.log("found template in dom:",d.html());return this.compileTemplate(d.html())}});var RemoteTemplateLoader=_.extend({},InDomTemplateLoader,{templateBaseURL:"static/scripts/templates/",getTemplateLoadFn:function(){return this.loadViaHttpGet},loadViaHttpGet:function(d,c,f){var b="static/scripts/templates/";this.log("loadViaHttpGet, templateFile:",d,"templateName:",c,", templateID:",f,"templateBaseURL:",this.templateBaseURL);var h=null;try{h=this.loadInDomTemplate(d,c,f)}catch(g){this.log("getInDomTemplate exception:"+g);if(!Handlebars.compile){throw (g)}this.log("Couldn't locate template in DOM: "+f);var a=this;var e=b+d;jQuery.ajax(e,{method:"GET",async:false,success:function(i){a.log(d+" loaded via GET. Attempting compile...");$("body").append(i);h=a.loadInDomTemplate(d,c,f)},error:function(j,i,k){throw ("Failed to fetch "+e+":"+i)}})}if(!h){throw ("Couldn't load or fetch template: "+f)}return h}});
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/mvc/history.js
--- a/static/scripts/packed/mvc/history.js
+++ b/static/scripts/packed/mvc/history.js
@@ -1,1 +1,1 @@
-function linkHTMLTemplate(b,a){if(!b){return"<a></a>"}a=a||"a";var c=["<"+a];for(key in b){var d=b[key];if(d===""){continue}switch(key){case"text":continue;case"classes":key="class";d=(b.classes.join)?(b.classes.join(" ")):(b.classes);default:c.push([" ",key,'="',d,'"'].join(""))}}c.push(">");if("text" in b){c.push(b.text)}c.push("</"+a+">");return c.join("")}var HistoryItem=BaseModel.extend(LoggableMixin).extend({defaults:{id:null,name:"",data_type:null,file_size:0,genome_build:null,metadata_data_lines:0,metadata_dbkey:null,metadata_sequences:0,misc_blurb:"",misc_info:"",model_class:"",state:"",deleted:false,purged:false,visible:true,for_editing:true,bodyIsShown:false},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryItem.STATES.NOT_VIEWABLE)}},isEditable:function(){return(!(this.get("deleted")||this.get("purged")))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryItem("+a+")"}});HistoryItem.STATES={NOT_VIEWABLE:"not_viewable",NEW:"new",UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",OK:"ok",EMPTY:"empty",ERROR:"error",DISCARDED:"discarded",SETTING_METADATA:"setting_metadata",FAILED_METADATA:"failed_metadata"};var HistoryItemView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(){this.log(this+".initialize:",this,this.model)},render:function(){var c=this.model.get("id"),b=this.model.get("state");this.clearReferences();this.$el.attr("id","historyItemContainer-"+c);var a=$("<div/>").attr("id","historyItem-"+c).addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+b);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);a.find(".tooltip").tooltip({placement:"bottom"});make_popup_menus(a);this.$el.children().remove();return this.$el.append(a)},clearReferences:function(){this.displayButton=null;this.editButton=null;this.deleteButton=null;this.errButton=null},_render_warnings:function(){return $(jQuery.trim(HistoryItemView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_displayButton:function(){if(this.model.get("state")===HistoryItem.STATES.UPLOAD){return null}displayBtnData=(this.model.get("purged"))?({title:"Cannot display datasets removed from disk",enabled:false,icon_class:"display"}):({title:"Display data in browser",href:this.model.get("display_url"),target:(this.model.get("for_editing"))?("galaxy_main"):(null),icon_class:"display"});this.displayButton=new IconButtonView({model:new IconButton(displayBtnData)});return this.displayButton.render().$el},_render_editButton:function(){if((this.model.get("state")===HistoryItem.STATES.UPLOAD)||(!this.model.get("for_editing"))){return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:"Edit attributes",href:this.model.get("edit_url"),target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false}if(a){b.title="Undelete dataset to edit attributes"}else{if(c){b.title="Cannot edit attributes of datasets removed from disk"}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if(!this.model.get("for_editing")){return null}var a={title:"Delete",href:this.model.get("delete_url"),target:"galaxy_main",id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if((this.model.get("deleted")||this.model.get("purged"))&&(!this.model.get("delete_url"))){a={title:"Dataset is already deleted",icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HistoryItemView.templates.titleLink(this.model.toJSON())))},_render_hdaSummary:function(){var a=this.model.toJSON();if(this.model.get("metadata_dbkey")==="?"&&this.model.isEditable()){_.extend(a,{dbkey_unknown_and_editable:true})}return HistoryItemView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var b=$("<div/>").attr("id","primary-actions-"+this.model.get("id")),a=this;_.each(c,function(d){var e=d.call(a);b.append(e)});return b},_render_downloadButton:function(){if(this.model.get("purged")){return null}var a=HistoryItemView.templates.downloadLinks(this.model.toJSON());this.log("_render_downloadButton, downloadLinkHTML:",a);return $(a)},_render_errButton:function(){if((this.model.get("state")!==HistoryItem.STATES.ERROR)||(!this.model.get("for_editing"))){return null}this.errButton=new IconButtonView({model:new IconButton({title:"View or report this error",href:this.model.get("report_error_url"),target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:"View details",href:this.model.get("show_params_url"),target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_rerunButton:function(){if(!this.model.get("for_editing")){return null}this.rerunButton=new IconButtonView({model:new IconButton({title:"Run this job again",href:this.model.get("rerun_url"),target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_tracksterButton:function(){var a=this.model.get("trackster_urls");if(!(this.model.hasData())||!(this.model.get("for_editing"))||!(a)){return null}this.tracksterButton=new IconButtonView({model:new IconButton({title:"View in Trackster",icon_class:"chart_curve"})});this.errButton.render();this.errButton.$el.addClass("trackster-add").attr({"data-url":a["data-url"],"action-url":a["action-url"],"new-url":a["new-url"]});return this.errButton.$el},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("retag_url"))){return null}this.tagButton=new IconButtonView({model:new IconButton({title:"Edit dataset tags",target:"galaxy_main",href:this.model.get("retag_url"),icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("annotate_url"))){return null}this.annotateButton=new IconButtonView({model:new IconButton({title:"Edit dataset annotation",target:"galaxy_main",href:this.model.get("annotate_url"),icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(this.model.get("retag_url")){return null}return $(HistoryItemView.templates.tagArea(this.model.toJSON()))},_render_annotationArea:function(){if(!this.model.get("annotate_url")){return null}return $(HistoryItemView.templates.annotationArea(this.model.toJSON()))},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){this.log(this+"display_types:",this.model.get("display_types"));a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_types}))}if(!_.isEmpty(this.model.get("display_apps"))){this.log(this+"display_apps:",this.model.get("display_apps"));a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_apps}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body_not_viewable:function(a){a.append($("<div>You do not have permission to view dataset.</div>"))},_render_body_uploading:function(a){a.append($("<div>Dataset is uploading</div>"))},_render_body_queued:function(a){a.append($("<div>Job is waiting to run.</div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_running:function(a){a.append("<div>Job is currently running.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append(("An error occurred running this job: <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]))},_render_body_discarded:function(a){a.append("<div>The job creating this dataset was cancelled before completion.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_setting_metadata:function(a){a.append($("<div>Metadata is being auto-detected.</div>"))},_render_body_empty:function(a){a.append($("<div>No data: <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_failed_metadata:function(a){a.append($(HistoryItemView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},_render_body:function(){var b=this.model.get("state");var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(b){case HistoryItem.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryItem.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryItem.STATES.QUEUED:this._render_body_queued(a);break;case HistoryItem.STATES.RUNNING:this._render_body_running(a);break;case HistoryItem.STATES.ERROR:this._render_body_error(a);break;case HistoryItem.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryItem.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryItem.STATES.EMPTY:this._render_body_empty(a);break;case HistoryItem.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryItem.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+b+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.model.get("bodyIsShown")===false){a.hide()}return a},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!a.html()){$.ajax({url:this.model.get("ajax_get_tag_url"),error:function(){alert("Tagging failed")},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.model.get("ajax_set_annotation_url");if(d.is(":hidden")){if(!c.html()){$.ajax({url:this.model.get("ajax_get_annotation_url"),error:function(){alert("Annotations failed")},success:function(e){if(e===""){e="<em>Describe or add notes to dataset</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toggleBodyVisibility:function(){this.log(this+".toggleBodyVisibility");this.$el.find(".historyItemBody").toggle()},toString:function(){var a=(this.model)?(this.model+""):("");return"HistoryItemView("+a+")"}});HistoryItemView.templates=CompiledTemplateLoader.getTemplates({"common-templates.html":{warningMsg:"template-warningmessagesmall"},"history-templates.html":{messages:"template-history-warning-messages",titleLink:"template-history-titleLink",hdaSummary:"template-history-hdaSummary",downloadLinks:"template-history-downloadLinks",failedMetadata:"template-history-failedMetaData",tagArea:"template-history-tagArea",annotationArea:"template-history-annotationArea",displayApps:"template-history-displayApps"}});var HistoryCollection=Backbone.Collection.extend({model:HistoryItem,toString:function(){return("HistoryCollection()")}});var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",state_details:{discarded:0,empty:0,error:0,failed_metadata:0,ok:0,queued:0,running:0,setting_metadata:0,upload:0}},initialize:function(b,a){this.log(this+".initialize",b,a);this.items=new HistoryCollection()},loadDatasetsAsHistoryItems:function(c){var a=this,b=this.get("id"),d=this.get("state_details");_.each(c,function(f,e){a.log("loading dataset: ",f,e);var h=new HistoryItem(_.extend(f,{history_id:b}));a.log("as History:",h);a.items.add(h);var g=f.state;d[g]+=1});this.set("state_details",d);this._stateFromStateDetails();return this},_stateFromStateDetails:function(){this.set("state","");var a=this.get("state_details");if((a.error>0)||(a.failed_metadata>0)){this.set("state",HistoryItem.STATES.ERROR)}else{if((a.running>0)||(a.setting_metadata>0)){this.set("state",HistoryItem.STATES.RUNNING)}else{if(a.queued>0){this.set("state",HistoryItem.STATES.QUEUED)}else{if(a.ok===this.items.length){this.set("state",HistoryItem.STATES.OK)}else{throw ("_stateFromStateDetails: unable to determine history state from state details: "+this.state_details)}}}}return this},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});var HistoryView=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",initialize:function(){this.log(this+".initialize");this.itemViews=[];var a=this;this.model.items.each(function(c){var b=new HistoryItemView({model:c});a.itemViews.push(b)})},render:function(){this.log(this+".render");var a=$("<div/>");_.each(this.itemViews,function(b){a.prepend(b.render())});this.$el.append(a.children());a.remove()},toString:function(){var a=this.model.get("name")||"";return"HistoryView("+a+")"}});
\ No newline at end of file
+var HistoryItem=BaseModel.extend(LoggableMixin).extend({defaults:{id:null,name:"",data_type:null,file_size:0,genome_build:null,metadata_data_lines:0,metadata_dbkey:null,metadata_sequences:0,misc_blurb:"",misc_info:"",model_class:"",state:"",deleted:false,purged:false,visible:true,for_editing:true,bodyIsShown:false},initialize:function(){this.log(this+".initialize",this.attributes);this.log("\tparent history_id: "+this.get("history_id"));if(!this.get("accessible")){this.set("state",HistoryItem.STATES.NOT_VIEWABLE)}},isEditable:function(){return(!(this.get("deleted")||this.get("purged")))},hasData:function(){return(this.get("file_size")>0)},toString:function(){var a=this.get("id")||"";if(this.get("name")){a+=':"'+this.get("name")+'"'}return"HistoryItem("+a+")"}});HistoryItem.STATES={NOT_VIEWABLE:"not_viewable",NEW:"new",UPLOAD:"upload",QUEUED:"queued",RUNNING:"running",OK:"ok",EMPTY:"empty",ERROR:"error",DISCARDED:"discarded",SETTING_METADATA:"setting_metadata",FAILED_METADATA:"failed_metadata"};var HistoryItemView=BaseView.extend(LoggableMixin).extend({tagName:"div",className:"historyItemContainer",initialize:function(){this.log(this+".initialize:",this,this.model)},render:function(){var c=this.model.get("id"),b=this.model.get("state");this.clearReferences();this.$el.attr("id","historyItemContainer-"+c);var a=$("<div/>").attr("id","historyItem-"+c).addClass("historyItemWrapper").addClass("historyItem").addClass("historyItem-"+b);a.append(this._render_warnings());a.append(this._render_titleBar());this.body=$(this._render_body());a.append(this.body);a.find(".tooltip").tooltip({placement:"bottom"});make_popup_menus(a);this.$el.children().remove();return this.$el.append(a)},clearReferences:function(){this.displayButton=null;this.editButton=null;this.deleteButton=null;this.errButton=null},_render_warnings:function(){return $(jQuery.trim(HistoryItemView.templates.messages(this.model.toJSON())))},_render_titleBar:function(){var a=$('<div class="historyItemTitleBar" style="overflow: hidden"></div>');a.append(this._render_titleButtons());a.append('<span class="state-icon"></span>');a.append(this._render_titleLink());return a},_render_titleButtons:function(){var a=$('<div class="historyItemButtons"></div>');a.append(this._render_displayButton());a.append(this._render_editButton());a.append(this._render_deleteButton());return a},_render_displayButton:function(){if(this.model.get("state")===HistoryItem.STATES.UPLOAD){return null}displayBtnData=(this.model.get("purged"))?({title:"Cannot display datasets removed from disk",enabled:false,icon_class:"display"}):({title:"Display data in browser",href:this.model.get("display_url"),target:(this.model.get("for_editing"))?("galaxy_main"):(null),icon_class:"display"});this.displayButton=new IconButtonView({model:new IconButton(displayBtnData)});return this.displayButton.render().$el},_render_editButton:function(){if((this.model.get("state")===HistoryItem.STATES.UPLOAD)||(!this.model.get("for_editing"))){return null}var c=this.model.get("purged"),a=this.model.get("deleted"),b={title:"Edit attributes",href:this.model.get("edit_url"),target:"galaxy_main",icon_class:"edit"};if(a||c){b.enabled=false}if(a){b.title="Undelete dataset to edit attributes"}else{if(c){b.title="Cannot edit attributes of datasets removed from disk"}}this.editButton=new IconButtonView({model:new IconButton(b)});return this.editButton.render().$el},_render_deleteButton:function(){if(!this.model.get("for_editing")){return null}var a={title:"Delete",href:this.model.get("delete_url"),id:"historyItemDeleter-"+this.model.get("id"),icon_class:"delete"};if((this.model.get("deleted")||this.model.get("purged"))&&(!this.model.get("delete_url"))){a={title:"Dataset is already deleted",icon_class:"delete",enabled:false}}this.deleteButton=new IconButtonView({model:new IconButton(a)});return this.deleteButton.render().$el},_render_titleLink:function(){return $(jQuery.trim(HistoryItemView.templates.titleLink(this.model.toJSON())))},_render_hdaSummary:function(){var a=this.model.toJSON();if(this.model.get("metadata_dbkey")==="?"&&this.model.isEditable()){_.extend(a,{dbkey_unknown_and_editable:true})}return HistoryItemView.templates.hdaSummary(a)},_render_primaryActionButtons:function(c){var b=$("<div/>").attr("id","primary-actions-"+this.model.get("id")),a=this;_.each(c,function(d){b.append(d.call(a))});return b},_render_downloadButton:function(){if(this.model.get("purged")){return null}var a=HistoryItemView.templates.downloadLinks(this.model.toJSON());return $(a)},_render_errButton:function(){if((this.model.get("state")!==HistoryItem.STATES.ERROR)||(!this.model.get("for_editing"))){return null}this.errButton=new IconButtonView({model:new IconButton({title:"View or report this error",href:this.model.get("report_error_url"),target:"galaxy_main",icon_class:"bug"})});return this.errButton.render().$el},_render_showParamsButton:function(){this.showParamsButton=new IconButtonView({model:new IconButton({title:"View details",href:this.model.get("show_params_url"),target:"galaxy_main",icon_class:"information"})});return this.showParamsButton.render().$el},_render_rerunButton:function(){if(!this.model.get("for_editing")){return null}this.rerunButton=new IconButtonView({model:new IconButton({title:"Run this job again",href:this.model.get("rerun_url"),target:"galaxy_main",icon_class:"arrow-circle"})});return this.rerunButton.render().$el},_render_tracksterButton:function(){var a=this.model.get("trackster_urls");if(!(this.model.hasData())||!(this.model.get("for_editing"))||!(a)){return null}this.tracksterButton=new IconButtonView({model:new IconButton({title:"View in Trackster",icon_class:"chart_curve"})});this.errButton.render();this.errButton.$el.addClass("trackster-add").attr({"data-url":a["data-url"],"action-url":a["action-url"],"new-url":a["new-url"]});return this.errButton.$el},_render_secondaryActionButtons:function(b){var c=$("<div/>"),a=this;c.attr("style","float: right;").attr("id","secondary-actions-"+this.model.get("id"));_.each(b,function(d){c.append(d.call(a))});return c},_render_tagButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("retag_url"))){return null}this.tagButton=new IconButtonView({model:new IconButton({title:"Edit dataset tags",target:"galaxy_main",href:this.model.get("retag_url"),icon_class:"tags"})});return this.tagButton.render().$el},_render_annotateButton:function(){if(!(this.model.hasData())||!(this.model.get("for_editing"))||(!this.model.get("annotate_url"))){return null}this.annotateButton=new IconButtonView({model:new IconButton({title:"Edit dataset annotation",target:"galaxy_main",href:this.model.get("annotate_url"),icon_class:"annotate"})});return this.annotateButton.render().$el},_render_tagArea:function(){if(!this.model.get("retag_url")){return null}return $(HistoryItemView.templates.tagArea(this.model.toJSON()))},_render_annotationArea:function(){if(!this.model.get("annotate_url")){return null}return $(HistoryItemView.templates.annotationArea(this.model.toJSON()))},_render_displayApps:function(){if(!this.model.hasData()){return null}var a=$("<div/>").addClass("display-apps");if(!_.isEmpty(this.model.get("display_types"))){a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_types}))}if(!_.isEmpty(this.model.get("display_apps"))){a.append(HistoryItemView.templates.displayApps({displayApps:this.model.toJSON().display_apps}))}return a},_render_peek:function(){if(!this.model.get("peek")){return null}return $("<div/>").append($("<pre/>").attr("id","peek"+this.model.get("id")).addClass("peek").append(this.model.get("peek")))},_render_body_not_viewable:function(a){a.append($("<div>You do not have permission to view dataset.</div>"))},_render_body_uploading:function(a){a.append($("<div>Dataset is uploading</div>"))},_render_body_queued:function(a){a.append($("<div>Job is waiting to run.</div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_running:function(a){a.append("<div>Job is currently running.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_error:function(a){if(!this.model.get("purged")){a.append($("<div>"+this.model.get("misc_blurb")+"</div>"))}a.append(("An error occurred running this job: <i>"+$.trim(this.model.get("misc_info"))+"</i>"));a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]))},_render_body_discarded:function(a){a.append("<div>The job creating this dataset was cancelled before completion.</div>");a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_setting_metadata:function(a){a.append($("<div>Metadata is being auto-detected.</div>"))},_render_body_empty:function(a){a.append($("<div>No data: <i>"+this.model.get("misc_blurb")+"</i></div>"));a.append(this._render_primaryActionButtons([this._render_showParamsButton,this._render_rerunButton]))},_render_body_failed_metadata:function(a){a.append($(HistoryItemView.templates.failedMetadata(this.model.toJSON())));this._render_body_ok(a)},_render_body_ok:function(a){a.append(this._render_hdaSummary());a.append(this._render_primaryActionButtons([this._render_downloadButton,this._render_errButton,this._render_showParamsButton,this._render_rerunButton]));a.append(this._render_secondaryActionButtons([this._render_tagButton,this._render_annotateButton]));a.append('<div class="clear"/>');a.append(this._render_tagArea());a.append(this._render_annotationArea());a.append(this._render_displayApps());a.append(this._render_peek())},_render_body:function(){var b=this.model.get("state");var a=$("<div/>").attr("id","info-"+this.model.get("id")).addClass("historyItemBody").attr("style","display: block");switch(b){case HistoryItem.STATES.NOT_VIEWABLE:this._render_body_not_viewable(a);break;case HistoryItem.STATES.UPLOAD:this._render_body_uploading(a);break;case HistoryItem.STATES.QUEUED:this._render_body_queued(a);break;case HistoryItem.STATES.RUNNING:this._render_body_running(a);break;case HistoryItem.STATES.ERROR:this._render_body_error(a);break;case HistoryItem.STATES.DISCARDED:this._render_body_discarded(a);break;case HistoryItem.STATES.SETTING_METADATA:this._render_body_setting_metadata(a);break;case HistoryItem.STATES.EMPTY:this._render_body_empty(a);break;case HistoryItem.STATES.FAILED_METADATA:this._render_body_failed_metadata(a);break;case HistoryItem.STATES.OK:this._render_body_ok(a);break;default:a.append($('<div>Error: unknown dataset state "'+b+'".</div>'))}a.append('<div style="clear: both"></div>');if(this.model.get("bodyIsShown")===false){a.hide()}return a},events:{"click .historyItemTitle":"toggleBodyVisibility","click a.icon-button.tags":"loadAndDisplayTags","click a.icon-button.annotate":"loadAndDisplayAnnotation"},loadAndDisplayTags:function(b){this.log(this+".loadAndDisplayTags",b);var c=this.$el.find(".tag-area"),a=c.find(".tag-elt");if(c.is(":hidden")){if(!jQuery.trim(a.html())){$.ajax({url:this.model.get("ajax_get_tag_url"),error:function(){alert("Tagging failed")},success:function(d){a.html(d);a.find(".tooltip").tooltip();c.slideDown("fast")}})}else{c.slideDown("fast")}}else{c.slideUp("fast")}return false},loadAndDisplayAnnotation:function(b){this.log(this+".loadAndDisplayAnnotation",b);var d=this.$el.find(".annotation-area"),c=d.find(".annotation-elt"),a=this.model.get("ajax_set_annotation_url");if(d.is(":hidden")){if(!jQuery.trim(c.html())){$.ajax({url:this.model.get("ajax_get_annotation_url"),error:function(){alert("Annotations failed")},success:function(e){if(e===""){e="<em>Describe or add notes to dataset</em>"}c.html(e);d.find(".tooltip").tooltip();async_save_text(c.attr("id"),c.attr("id"),a,"new_annotation",18,true,4);d.slideDown("fast")}})}else{d.slideDown("fast")}}else{d.slideUp("fast")}return false},toggleBodyVisibility:function(){this.log(this+".toggleBodyVisibility");this.$el.find(".historyItemBody").toggle()},toString:function(){var a=(this.model)?(this.model+""):("");return"HistoryItemView("+a+")"}});HistoryItemView.templates=CompiledTemplateLoader.getTemplates({"common-templates.html":{warningMsg:"template-warningmessagesmall"},"history-templates.html":{messages:"template-history-warning-messages",titleLink:"template-history-titleLink",hdaSummary:"template-history-hdaSummary",downloadLinks:"template-history-downloadLinks",failedMetadata:"template-history-failedMetaData",tagArea:"template-history-tagArea",annotationArea:"template-history-annotationArea",displayApps:"template-history-displayApps"}});var HistoryCollection=Backbone.Collection.extend({model:HistoryItem,toString:function(){return("HistoryCollection()")}});var History=BaseModel.extend(LoggableMixin).extend({defaults:{id:"",name:"",state:"",state_details:{discarded:0,empty:0,error:0,failed_metadata:0,ok:0,queued:0,running:0,setting_metadata:0,upload:0},userIsAdmin:false,userRoles:[],itemsLength:0,showDeleted:false,showHidden:false,diskSize:0,deleted:false,tags:[],annotation:null,message:null,quotaMsg:false,baseURL:null,hideDeletedURL:null,hideHiddenURL:null,tagURL:null,annotateURL:null},initialize:function(b,a){this.items=new HistoryCollection()},toJSON:function(){var a=Backbone.Model.prototype.toJSON.call(this);a.itemsLength=this.items.length;return a},loadDatasetsAsHistoryItems:function(c){var a=this,b=this.get("id"),d=this.get("state_details");_.each(c,function(f,e){var h=new HistoryItem(_.extend(f,{history_id:b}));a.items.add(h);var g=f.state;d[g]+=1});this.set("state_details",d);this._stateFromStateDetails();return this},_stateFromStateDetails:function(){this.set("state","");var a=this.get("state_details");if((a.error>0)||(a.failed_metadata>0)){this.set("state",HistoryItem.STATES.ERROR)}else{if((a.running>0)||(a.setting_metadata>0)){this.set("state",HistoryItem.STATES.RUNNING)}else{if(a.queued>0){this.set("state",HistoryItem.STATES.QUEUED)}else{if(a.ok===this.items.length){this.set("state",HistoryItem.STATES.OK)}else{throw ("_stateFromStateDetails: unable to determine history state from state details: "+this.state_details)}}}}return this},toString:function(){var a=(this.get("name"))?(","+this.get("name")):("");return"History("+this.get("id")+a+")"}});var HistoryView=BaseView.extend(LoggableMixin).extend({el:"body.historyPage",initialize:function(){this.log(this+".initialize:",this);this.itemViews=[];var a=this;this.model.items.each(function(c){var b=new HistoryItemView({model:c});a.itemViews.push(b)})},render:function(){this.$el.append(HistoryView.templates.historyPanel(this.model.toJSON()));this.log(this+" rendered from template:",this.$el);this.itemsDiv=this.$el.find("#"+this.model.get("id")+"-datasets");if(this.model.items.length){var a=this._render_items();this.itemsDiv.append(a.children());a.remove()}},_render_items:function(){var b=$("<div/>"),a=this;_.each(this.itemViews,function(c){a.log(a+".render_items:",c);b.prepend(c.render())});return b},toString:function(){var a=this.model.get("name")||"";return"HistoryView("+a+")"}});HistoryView.templates=CompiledTemplateLoader.getTemplates({"history-templates.html":{historyPanel:"template-history-historyPanel"}});
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(c){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",c.attributes.title).addClass("icon-button menu-button").addClass(c.attributes.icon_class).appendTo(a.$el).click(c.attributes.on_click);if(c.attributes.tooltip_config){b.tooltip(c.attributes.tooltip_config)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});var GalaxyLocalization=jQuery.extend({},{aliasName:"_l",localizedStrings:{},setLocalizedString:function(b,a){var c=this;var d=function(f,e){if(f!==e){c.localizedStrings[f]=e}};if(jQuery.type(b)==="string"){d(b,a)}else{if(jQuery.type(b)==="object"){jQuery.each(b,function(e,f){d(e,f)})}else{throw ("Localization.setLocalizedString needs either a string or object as the first argument, given: "+b)}}},localize:function(b){try{return this.localizedStrings[b]}catch(a){return b}},toString:function(){return"GalaxyLocalization"}});window[GalaxyLocalization.aliasName]=function(a){return GalaxyLocalization.localize(a)};
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,tooltip_config:{},isMenuButton:true,id:null,href:null,target:null,enabled:true,visible:true}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=$(Handlebars.partials.iconButton(this.model.toJSON()));a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(this.model.attributes.on_click){this.model.attributes.on_click(a);return false}return true}});IconButtonView.templates={iconButton:Handlebars.partials.iconButton};var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(c){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",c.attributes.title).addClass("icon-button menu-button").addClass(c.attributes.icon_class).appendTo(a.$el).click(c.attributes.on_click);if(c.attributes.tooltip_config){b.tooltip(c.attributes.tooltip_config)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var GalaxyPaths=Backbone.Model.extend({defaults:{root_path:"",image_path:""}});
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/templates/compiled/helpers-common-templates.js
--- a/static/scripts/packed/templates/compiled/helpers-common-templates.js
+++ b/static/scripts/packed/templates/compiled/helpers-common-templates.js
@@ -1,1 +1,1 @@
-Handlebars.registerPartial("clearFloatDiv",function(a){return'<div class="clear"></div>'});Handlebars.registerHelper("warningmessagesmall",function(a){return'<div class="warningmessagesmall"><strong>'+a.fn(this)+"</strong></div>"});Handlebars.registerPartial("iconButton",function(c,b){var a="";a+=(c.enabled)?("<a"):("<span");if(c.title){a+=' title="'+c.title+'"'}a+=' class="icon-button';if(c.isMenuButton){a+=" menu-button"}if(c.title){a+=" tooltip"}a+=" "+c.icon_class;if(!c.enabled){a+="_disabled"}a+='"';if(c.id){a+=' id="'+c.id+'"'}a+=' href="'+((c.href)?(c.href):("javascript:void(0);"))+'"';if(c.target){a+=' target="'+c.target+'"'}if(!c.visible){a+=' style="display: none;"'}a+=">"+((c.enabled)?("</a>"):("</span>"));return a});
\ No newline at end of file
+Handlebars.registerPartial("clearFloatDiv",function(a){return'<div class="clear"></div>'});Handlebars.registerHelper("warningmessagesmall",function(a){return'<div class="warningmessagesmall"><strong>'+a.fn(this)+"</strong></div>"});Handlebars.registerHelper("local",function(a){return _l(a.fn(this))});Handlebars.registerPartial("iconButton",function(c,b){var a="";a+=(c.enabled)?("<a"):("<span");if(c.title){a+=' title="'+c.title+'"'}a+=' class="icon-button';if(c.isMenuButton){a+=" menu-button"}if(c.title){a+=" tooltip"}a+=" "+c.icon_class;if(!c.enabled){a+="_disabled"}a+='"';if(c.id){a+=' id="'+c.id+'"'}a+=' href="'+((c.href)?(c.href):("javascript:void(0);"))+'"';if(c.target){a+=' target="'+c.target+'"'}if(!c.visible){a+=' style="display: none;"'}a+=">"+((c.enabled)?("</a>"):("</span>"));return a});
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/templates/compiled/template-history-downloadLinks.js
--- a/static/scripts/packed/templates/compiled/template-history-downloadLinks.js
+++ b/static/scripts/packed/templates/compiled/template-history-downloadLinks.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-downloadLinks"]=b(function(g,l,f,k,j){f=f||g.helpers;var c,h="function",i=this.escapeExpression,m=this;function e(s,r){var p="",q,o;p+='\n<div popupmenu="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a class="action-button" href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'">Download Dataset</a>\n <a>Additional Files</a>\n ';q=s.meta_files;q=f.each.call(s,q,{hash:{},inverse:m.noop,fn:m.program(2,d,r)});if(q||q===0){p+=q}p+='\n</div>\n<div style="float:left;" class="menubutton split popup" id="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n</div>\n';return p}function d(s,r){var p="",q,o;p+='\n <a class="action-button" href="';o=f.meta_download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_download_url;q=typeof q===h?q():q}p+=i(q)+'">Download ';o=f.meta_file_type;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_file_type;q=typeof q===h?q():q}p+=i(q)+"</a>\n ";return p}function n(p,o){return'\n<a href="" title="Download" class="icon-button disk tooltip"></a>\n'}c=l.meta_files;c=f["if"].call(l,c,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j)});if(c||c===0){return c}else{return""}})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-downloadLinks"]=b(function(g,l,f,k,j){f=f||g.helpers;var c,h="function",i=this.escapeExpression,m=this;function e(s,r){var p="",q,o;p+='\n<div popupmenu="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a class="action-button" href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'">Download Dataset</a>\n <a>Additional Files</a>\n ';q=s.meta_files;q=f.each.call(s,q,{hash:{},inverse:m.noop,fn:m.program(2,d,r)});if(q||q===0){p+=q}p+='\n</div>\n<div style="float:left;" class="menubutton split popup" id="dataset-';o=f.id;if(o){q=o.call(s,{hash:{}})}else{q=s.id;q=typeof q===h?q():q}p+=i(q)+'-popup">\n <a href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n</div>\n';return p}function d(s,r){var p="",q,o;p+='\n <a class="action-button" href="';o=f.meta_download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_download_url;q=typeof q===h?q():q}p+=i(q)+'">Download ';o=f.meta_file_type;if(o){q=o.call(s,{hash:{}})}else{q=s.meta_file_type;q=typeof q===h?q():q}p+=i(q)+"</a>\n ";return p}function n(s,r){var p="",q,o;p+='\n<a href="';o=f.download_url;if(o){q=o.call(s,{hash:{}})}else{q=s.download_url;q=typeof q===h?q():q}p+=i(q)+'" title="Download" class="icon-button disk tooltip"></a>\n';return p}c=l.meta_files;c=f["if"].call(l,c,{hash:{},inverse:m.program(4,n,j),fn:m.program(1,e,j)});if(c||c===0){return c}else{return""}})})();
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/templates/compiled/template-history-historyPanel.js
--- /dev/null
+++ b/static/scripts/packed/templates/compiled/template-history-historyPanel.js
@@ -0,0 +1,1 @@
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a["template-history-historyPanel"]=b(function(k,C,A,s,J){A=A||k.helpers;var B="",o,n,y=this,f="function",c=A.blockHelperMissing,e=this.escapeExpression;function u(L,K){return"refresh"}function t(L,K){return"collapse all"}function r(O,N){var L="",M,K;L+='\n <div style="width: 40px; float: right; white-space: nowrap;">\n <a id="history-tag" title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(6,q,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(6,q,N)})}if(M||M===0){L+=M}L+='"\n class="icon-button tags tooltip" target="galaxy_main" href="';K=A.tagURL;if(K){M=K.call(O,{hash:{}})}else{M=O.tagURL;M=typeof M===f?M():M}L+=e(M)+'"></a>\n <a id="history-annotate" title="';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(8,m,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(8,m,N)})}if(M||M===0){L+=M}L+='"\n class="icon-button annotate tooltip" target="galaxy_main" href="';K=A.annotateURL;if(K){M=K.call(O,{hash:{}})}else{M=O.annotateURL;M=typeof M===f?M():M}L+=e(M)+'"></a>\n </div>\n ';return L}function q(L,K){return"Edit history tags"}function m(L,K){return"Edit history annotation"}function I(O,N){var L="",M,K;L+='\n<div class="historyLinks">\n <a href="';K=A.hideDeletedURL;if(K){M=K.call(O,{hash:{}})}else{M=O.hideDeletedURL;M=typeof M===f?M():M}L+=e(M)+'">';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(11,H,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(11,H,N)})}if(M||M===0){L+=M}L+="</a>\n</div>\n";return L}function H(L,K){return"hide deleted"}function G(O,N){var L="",M,K;L+='\n<div class="historyLinks">\n <a href="';K=A.hideHiddenURL;if(K){M=K.call(O,{hash:{}})}else{M=O.hideHiddenURL;M=typeof M===f?M():M}L+=e(M)+'">';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(14,F,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(14,F,N)})}if(M||M===0){L+=M}L+="</a>\n</div>\n";return L}function F(L,K){return"hide hidden"}function E(O,N){var L="",M,K;L+="\n ";L+='\n <div id="history-size" style="position: absolute; top: 3px; right: 0px;">';K=A.diskSize;if(K){M=K.call(O,{hash:{}})}else{M=O.diskSize;M=typeof M===f?M():M}L+=e(M)+'</div>\n <div id="history-name" style="margin-right: 50px;" class="tooltip editable-text" title="Click to rename history">';K=A.name;if(K){M=K.call(O,{hash:{}})}else{M=O.name;M=typeof M===f?M():M}L+=e(M)+"</div>\n \n ";return L}function D(O,N){var L="",M,K;L+='\n <div id="history-size">';K=A.diskSize;if(K){M=K.call(O,{hash:{}})}else{M=O.diskSize;M=typeof M===f?M():M}L+=e(M)+"</div>\n ";return L}function p(O,N){var L="",M,K;L+="\n";K=A.warningmessagesmall;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(21,l,N)})}else{M=O.warningmessagesmall;M=typeof M===f?M():M}if(!A.warningmessagesmall){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(21,l,N)})}if(M||M===0){L+=M}L+="\n";return L}function l(N,M){var L,K;K=A.local;if(K){L=K.call(N,{hash:{},inverse:y.noop,fn:y.program(22,j,M)})}else{L=N.local;L=typeof L===f?L():L}if(!A.local){L=c.call(N,L,{hash:{},inverse:y.noop,fn:y.program(22,j,M)})}if(L||L===0){return L}else{return""}}function j(L,K){return"You are currently viewing a deleted history!"}function i(N,M){var K="",L;K+="\n";K+='\n<div style="margin: 0px 5px 10px 5px">\n\n <div id="history-tag-area" style="display: none">\n <b>Tags:</b>\n ';K+="\n ";K+='\n </div>\n\n <div id="history-annotation-area" style="display: none">\n <strong>Annotation / Notes:</strong>\n <div id="history-annotation-container">\n <div id="history-annotation" class="tooltip editable-text" title="Click to edit annotation">\n ';L=N.annotation;L=A["if"].call(N,L,{hash:{},inverse:y.program(27,g,M),fn:y.program(25,h,M)});if(L||L===0){K+=L}K+="\n </div>\n </div>\n </div>\n</div>\n";return K}function h(O,N){var L="",M,K;L+="\n ";K=A.annotation;if(K){M=K.call(O,{hash:{}})}else{M=O.annotation;M=typeof M===f?M():M}L+=e(M)+"\n ";return L}function g(L,K){return"\n <em>Describe or add notes to history</em>\n "}function d(O,N){var L="",M,K;L+='\n<div id="message-container">\n <div class="';K=A.status;if(K){M=K.call(O,{hash:{}})}else{M=O.status;M=typeof M===f?M():M}L+=e(M)+'message">\n ';K=A.message;if(K){M=K.call(O,{hash:{}})}else{M=O.message;M=typeof M===f?M():M}L+=e(M)+"\n </div><br />\n</div>\n";return L}function z(L,K){return'\n <div id="quota-message" class="errormessage">\n You are over your disk quota. Tool execution is on hold until your disk usage drops below your allocated quota.\n </div>\n <br/>\n '}function x(O,N){var L="",M,K;L+='\n<div id="';K=A.id;if(K){M=K.call(O,{hash:{}})}else{M=O.id;M=typeof M===f?M():M}L+=e(M)+'-datasets" class="history-datasets-list">\n ';L+="\n</div>\n\n";return L}function w(O,N){var L="",M,K;L+='\n<div class="infomessagesmall" id="emptyHistoryMessage">\n';K=A.local;if(K){M=K.call(O,{hash:{},inverse:y.noop,fn:y.program(36,v,N)})}else{M=O.local;M=typeof M===f?M():M}if(!A.local){M=c.call(O,M,{hash:{},inverse:y.noop,fn:y.program(36,v,N)})}if(M||M===0){L+=M}L+="\n</div>\n";return L}function v(L,K){return"Your history is empty. Click 'Get Data' on the left pane to start"}B+='<div id="top-links" class="historyLinks">\n <a title="';n=A.local;if(n){o=n.call(C,{hash:{},inverse:y.noop,fn:y.program(1,u,J)})}else{o=C.local;o=typeof o===f?o():o}if(!A.local){o=c.call(C,o,{hash:{},inverse:y.noop,fn:y.program(1,u,J)})}if(o||o===0){B+=o}B+='" class="icon-button arrow-circle tooltip" href="';n=A.baseURL;if(n){o=n.call(C,{hash:{}})}else{o=C.baseURL;o=typeof o===f?o():o}B+=e(o)+"\"></a>\n <a title='";n=A.local;if(n){o=n.call(C,{hash:{},inverse:y.noop,fn:y.program(3,t,J)})}else{o=C.local;o=typeof o===f?o():o}if(!A.local){o=c.call(C,o,{hash:{},inverse:y.noop,fn:y.program(3,t,J)})}if(o||o===0){B+=o}B+="' class='icon-button toggle tooltip' href='#' style=\"display: none\"></a>\n ";o=C.userRoles;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(5,r,J)});if(o||o===0){B+=o}B+='\n</div>\n<div class="clear"></div>\n\n';B+="\n";o=C.showDeleted;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(10,I,J)});if(o||o===0){B+=o}B+="\n\n";o=C.showHidden;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(13,G,J)});if(o||o===0){B+=o}B+="\n\n";B+='\n<div id="history-name-area" class="historyLinks">\n <div id="history-name-container" style="position: relative;">\n ';o=C.userRoles;o=A["if"].call(C,o,{hash:{},inverse:y.program(18,D,J),fn:y.program(16,E,J)});if(o||o===0){B+=o}B+='\n </div> \n</div>\n<div style="clear: both;"></div>\n\n';o=C.deleted;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(20,p,J)});if(o||o===0){B+=o}B+="\n\n";B+="\n";B+="\n";o=C.userRoles;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(24,i,J)});if(o||o===0){B+=o}B+="\n\n";o=C.message;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(29,d,J)});if(o||o===0){B+=o}B+='\n\n<div id="quota-message-container">\n ';o=C.over_quota;o=A["if"].call(C,o,{hash:{},inverse:y.noop,fn:y.program(31,z,J)});if(o||o===0){B+=o}B+="\n</div>\n\n";o=C.itemsLength;o=A["if"].call(C,o,{hash:{},inverse:y.program(35,w,J),fn:y.program(33,x,J)});if(o||o===0){B+=o}return B})})();
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/packed/templates/compiled/tool_search.js
--- a/static/scripts/packed/templates/compiled/tool_search.js
+++ b/static/scripts/packed/templates/compiled/tool_search.js
@@ -1,1 +1,1 @@
-(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.tool_search=b(function(e,l,d,k,j){d=d||e.helpers;var h="",c,g,f="function",i=this.escapeExpression;h+='<input type="text" name="query" value="';g=d.search_hint_string;if(g){c=g.call(l,{hash:{}})}else{c=l.search_hint_string;c=typeof c===f?c():c}h+=i(c)+'" id="tool-search-query" autocomplete="off" class="search-query parent-width" />\n<a id="search-clear-btn" class="icon-button cross-circle tooltip" title="clear search (esc)"></a>\n<img src="';g=d.spinner_url;if(g){c=g.call(l,{hash:{}})}else{c=l.spinner_url;c=typeof c===f?c():c}h+=i(c)+'" id="search-spinner" class="search-spinner"/>';return h})})();
\ No newline at end of file
+(function(){var b=Handlebars.template,a=Handlebars.templates=Handlebars.templates||{};a.tool_search=b(function(e,l,d,k,j){d=d||e.helpers;var h="",c,g,f="function",i=this.escapeExpression;h+='<input type="text" name="query" value="';g=d.search_hint_string;if(g){c=g.call(l,{hash:{}})}else{c=l.search_hint_string;c=typeof c===f?c():c}h+=i(c)+'" id="tool-search-query" autocomplete="off" class="search-query parent-width" />\n<a id="search-clear-btn" class="tooltip" title="clear search (esc)"></a>\n<img src="';g=d.spinner_url;if(g){c=g.call(l,{hash:{}})}else{c=l.spinner_url;c=typeof c===f?c():c}h+=i(c)+'" id="search-spinner" class="search-spinner"/>';return h})})();
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/templates/common-templates.html
--- a/static/scripts/templates/common-templates.html
+++ b/static/scripts/templates/common-templates.html
@@ -14,6 +14,15 @@
});
</script>
+<script type="text/javascript" class="helper-common" id="helper-local">
+/** Calls _l (from base-mvc.js) to localize strings (if poosible)
+ * This helper is specifically for localization within templates
+ */
+Handlebars.registerHelper( 'local', function( options ){
+ return _l( options.fn( this ) );
+});
+</script>
+
<script type="text/template" class="template-common" id="template-warningmessagesmall">
{{! renders a warning in a (mostly css) highlighted, iconned warning box }}
<div class="warningmessagesmall"><strong>{{{ warning }}}</strong></div>
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/templates/compiled/helpers-common-templates.js
--- a/static/scripts/templates/compiled/helpers-common-templates.js
+++ b/static/scripts/templates/compiled/helpers-common-templates.js
@@ -8,6 +8,12 @@
Handlebars.registerHelper( 'warningmessagesmall', function( options ){
return '<div class="warningmessagesmall"><strong>' + options.fn( this ) + '</strong></div>'
});
+/** Calls _l (from base-mvc.js) to localize strings (if poosible)
+ * This helper is specifically for localization within templates
+ */
+Handlebars.registerHelper( 'local', function( options ){
+ return _l( options.fn( this ) );
+});
/** Renders a glx style icon-button (see IconButton in mvc/ui.js)
* can be used in either of the following ways:
* within a template: {{> iconButton buttonData}}
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/templates/compiled/template-history-downloadLinks.js
--- a/static/scripts/templates/compiled/template-history-downloadLinks.js
+++ b/static/scripts/templates/compiled/template-history-downloadLinks.js
@@ -45,8 +45,13 @@
function program4(depth0,data) {
-
- return "\n<a href=\"\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n";}
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<a href=\"";
+ foundHelper = helpers.download_url;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.download_url; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\" title=\"Download\" class=\"icon-button disk tooltip\"></a>\n";
+ return buffer;}
stack1 = depth0.meta_files;
stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(4, program4, data),fn:self.program(1, program1, data)});
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/templates/compiled/template-history-historyPanel.js
--- /dev/null
+++ b/static/scripts/templates/compiled/template-history-historyPanel.js
@@ -0,0 +1,272 @@
+(function() {
+ var template = Handlebars.template, templates = Handlebars.templates = Handlebars.templates || {};
+templates['template-history-historyPanel'] = template(function (Handlebars,depth0,helpers,partials,data) {
+ helpers = helpers || Handlebars.helpers;
+ var buffer = "", stack1, foundHelper, self=this, functionType="function", blockHelperMissing=helpers.blockHelperMissing, escapeExpression=this.escapeExpression;
+
+function program1(depth0,data) {
+
+
+ return "refresh";}
+
+function program3(depth0,data) {
+
+
+ return "collapse all";}
+
+function program5(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n <div style=\"width: 40px; float: right; white-space: nowrap;\">\n <a id=\"history-tag\" title=\"";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(6, program6, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(6, program6, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\"\n class=\"icon-button tags tooltip\" target=\"galaxy_main\" href=\"";
+ foundHelper = helpers.tagURL;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.tagURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\"></a>\n <a id=\"history-annotate\" title=\"";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(8, program8, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(8, program8, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\"\n class=\"icon-button annotate tooltip\" target=\"galaxy_main\" href=\"";
+ foundHelper = helpers.annotateURL;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.annotateURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\"></a>\n </div>\n ";
+ return buffer;}
+function program6(depth0,data) {
+
+
+ return "Edit history tags";}
+
+function program8(depth0,data) {
+
+
+ return "Edit history annotation";}
+
+function program10(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<div class=\"historyLinks\">\n <a href=\"";
+ foundHelper = helpers.hideDeletedURL;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.hideDeletedURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\">";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(11, program11, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</a>\n</div>\n";
+ return buffer;}
+function program11(depth0,data) {
+
+
+ return "hide deleted";}
+
+function program13(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<div class=\"historyLinks\">\n <a href=\"";
+ foundHelper = helpers.hideHiddenURL;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.hideHiddenURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\">";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(14, program14, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "</a>\n</div>\n";
+ return buffer;}
+function program14(depth0,data) {
+
+
+ return "hide hidden";}
+
+function program16(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n ";
+ buffer += "\n <div id=\"history-size\" style=\"position: absolute; top: 3px; right: 0px;\">";
+ foundHelper = helpers.diskSize;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.diskSize; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "</div>\n <div id=\"history-name\" style=\"margin-right: 50px;\" class=\"tooltip editable-text\" title=\"Click to rename history\">";
+ foundHelper = helpers.name;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.name; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "</div>\n \n ";
+ return buffer;}
+
+function program18(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n <div id=\"history-size\">";
+ foundHelper = helpers.diskSize;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.diskSize; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "</div>\n ";
+ return buffer;}
+
+function program20(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n";
+ foundHelper = helpers.warningmessagesmall;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(21, program21, data)}); }
+ else { stack1 = depth0.warningmessagesmall; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.warningmessagesmall) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(21, program21, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n";
+ return buffer;}
+function program21(depth0,data) {
+
+ var stack1, foundHelper;
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(22, program22, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(22, program22, data)}); }
+ if(stack1 || stack1 === 0) { return stack1; }
+ else { return ''; }}
+function program22(depth0,data) {
+
+
+ return "You are currently viewing a deleted history!";}
+
+function program24(depth0,data) {
+
+ var buffer = "", stack1;
+ buffer += "\n";
+ buffer += "\n<div style=\"margin: 0px 5px 10px 5px\">\n\n <div id=\"history-tag-area\" style=\"display: none\">\n <b>Tags:</b>\n ";
+ buffer += "\n ";
+ buffer += "\n </div>\n\n <div id=\"history-annotation-area\" style=\"display: none\">\n <strong>Annotation / Notes:</strong>\n <div id=\"history-annotation-container\">\n <div id=\"history-annotation\" class=\"tooltip editable-text\" title=\"Click to edit annotation\">\n ";
+ stack1 = depth0.annotation;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(27, program27, data),fn:self.program(25, program25, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </div>\n </div>\n </div>\n</div>\n";
+ return buffer;}
+function program25(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n ";
+ foundHelper = helpers.annotation;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.annotation; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\n ";
+ return buffer;}
+
+function program27(depth0,data) {
+
+
+ return "\n <em>Describe or add notes to history</em>\n ";}
+
+function program29(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<div id=\"message-container\">\n <div class=\"";
+ foundHelper = helpers.status;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.status; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "message\">\n ";
+ foundHelper = helpers.message;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.message; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\n </div><br />\n</div>\n";
+ return buffer;}
+
+function program31(depth0,data) {
+
+
+ return "\n <div id=\"quota-message\" class=\"errormessage\">\n You are over your disk quota. Tool execution is on hold until your disk usage drops below your allocated quota.\n </div>\n <br/>\n ";}
+
+function program33(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<div id=\"";
+ foundHelper = helpers.id;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.id; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "-datasets\" class=\"history-datasets-list\">\n ";
+ buffer += "\n</div>\n\n";
+ return buffer;}
+
+function program35(depth0,data) {
+
+ var buffer = "", stack1, foundHelper;
+ buffer += "\n<div class=\"infomessagesmall\" id=\"emptyHistoryMessage\">\n";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(36, program36, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(36, program36, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n</div>\n";
+ return buffer;}
+function program36(depth0,data) {
+
+
+ return "Your history is empty. Click 'Get Data' on the left pane to start";}
+
+ buffer += "<div id=\"top-links\" class=\"historyLinks\">\n <a title=\"";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(1, program1, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\" class=\"icon-button arrow-circle tooltip\" href=\"";
+ foundHelper = helpers.baseURL;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{}}); }
+ else { stack1 = depth0.baseURL; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ buffer += escapeExpression(stack1) + "\"></a>\n <a title='";
+ foundHelper = helpers.local;
+ if (foundHelper) { stack1 = foundHelper.call(depth0, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); }
+ else { stack1 = depth0.local; stack1 = typeof stack1 === functionType ? stack1() : stack1; }
+ if (!helpers.local) { stack1 = blockHelperMissing.call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(3, program3, data)}); }
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "' class='icon-button toggle tooltip' href='#' style=\"display: none\"></a>\n ";
+ stack1 = depth0.userRoles;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(5, program5, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n</div>\n<div class=\"clear\"></div>\n\n";
+ buffer += "\n";
+ stack1 = depth0.showDeleted;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(10, program10, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n";
+ stack1 = depth0.showHidden;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(13, program13, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n";
+ buffer += "\n<div id=\"history-name-area\" class=\"historyLinks\">\n <div id=\"history-name-container\" style=\"position: relative;\">\n ";
+ stack1 = depth0.userRoles;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(18, program18, data),fn:self.program(16, program16, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n </div> \n</div>\n<div style=\"clear: both;\"></div>\n\n";
+ stack1 = depth0.deleted;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(20, program20, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n";
+ buffer += "\n";
+ buffer += "\n";
+ stack1 = depth0.userRoles;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(24, program24, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n";
+ stack1 = depth0.message;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(29, program29, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n\n<div id=\"quota-message-container\">\n ";
+ stack1 = depth0.over_quota;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.noop,fn:self.program(31, program31, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ buffer += "\n</div>\n\n";
+ stack1 = depth0.itemsLength;
+ stack1 = helpers['if'].call(depth0, stack1, {hash:{},inverse:self.program(35, program35, data),fn:self.program(33, program33, data)});
+ if(stack1 || stack1 === 0) { buffer += stack1; }
+ return buffer;});
+})();
\ No newline at end of file
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 static/scripts/templates/history-templates.html
--- a/static/scripts/templates/history-templates.html
+++ b/static/scripts/templates/history-templates.html
@@ -64,7 +64,7 @@
<a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a></div>
{{else}}
-<a href="" title="Download" class="icon-button disk tooltip"></a>
+<a href="{{download_url}}" title="Download" class="icon-button disk tooltip"></a>
{{/if}}
</script>
@@ -96,3 +96,112 @@
<br />
{{/each}}
</script>
+
+<!--
+History panel/page - the main container for hdas (gen. on the left hand of the glx page)
+-->
+<script type="text/template" class="template-history" id="template-history-historyPanel">
+<div id="top-links" class="historyLinks">
+ <a title="{{#local}}refresh{{/local}}" class="icon-button arrow-circle tooltip" href="{{baseURL}}"></a>
+ <a title='{{#local}}collapse all{{/local}}' class='icon-button toggle tooltip' href='#' style="display: none"></a>
+ {{#if userRoles}}
+ <div style="width: 40px; float: right; white-space: nowrap;">
+ <a id="history-tag" title="{{#local}}Edit history tags{{/local}}"
+ class="icon-button tags tooltip" target="galaxy_main" href="{{tagURL}}"></a>
+ <a id="history-annotate" title="{{#local}}Edit history annotation{{/local}}"
+ class="icon-button annotate tooltip" target="galaxy_main" href="{{annotateURL}}"></a>
+ </div>
+ {{/if}}
+</div>
+<div class="clear"></div>
+
+{{! TODO: move to js with no reload - use each with historyLinks }}
+{{#if showDeleted}}
+<div class="historyLinks">
+ <a href="{{hideDeletedURL}}">{{#local}}hide deleted{{/local}}</a>
+</div>
+{{/if}}
+
+{{#if showHidden}}
+<div class="historyLinks">
+ <a href="{{hideHiddenURL}}">{{#local}}hide hidden{{/local}}</a>
+</div>
+{{/if}}
+
+{{! history name (if any) }}
+<div id="history-name-area" class="historyLinks">
+ <div id="history-name-container" style="position: relative;">
+ {{#if userRoles}}
+ {{! TODO: factor out conditional css }}
+ <div id="history-size" style="position: absolute; top: 3px; right: 0px;">{{diskSize}}</div>
+ <div id="history-name" style="margin-right: 50px;" class="tooltip editable-text" title="Click to rename history">{{name}}</div>
+
+ {{else}}
+ <div id="history-size">{{diskSize}}</div>
+ {{/if}}
+ </div>
+</div>
+<div style="clear: both;"></div>
+
+{{#if deleted}}
+{{#warningmessagesmall}}{{#local}}You are currently viewing a deleted history!{{/local}}{{/warningmessagesmall}}
+{{/if}}
+
+{{! tags and annotations }}
+{{! TODO: wire these to js events }}
+{{#if userRoles}}
+{{! TODO: move inline styles out }}
+<div style="margin: 0px 5px 10px 5px">
+
+ <div id="history-tag-area" style="display: none">
+ <b>Tags:</b>
+ {{! load via js render_individual_tagging_element }}
+ {{! render_individual_tagging_element(user=trans.get_user(), tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20") }}
+ </div>
+
+ <div id="history-annotation-area" style="display: none">
+ <strong>Annotation / Notes:</strong>
+ <div id="history-annotation-container">
+ <div id="history-annotation" class="tooltip editable-text" title="Click to edit annotation">
+ {{#if annotation}}
+ {{annotation}}
+ {{else}}
+ <em>Describe or add notes to history</em>
+ {{/if}}
+ </div>
+ </div>
+ </div>
+</div>
+{{/if}}
+
+{{#if message}}
+<div id="message-container">
+ <div class="{{status}}message">
+ {{message}}
+ </div><br />
+</div>
+{{/if}}
+
+<div id="quota-message-container">
+ {{#if over_quota}}
+ <div id="quota-message" class="errormessage">
+ You are over your disk quota. Tool execution is on hold until your disk usage drops below your allocated quota.
+ </div>
+ <br/>
+ {{/if}}
+</div>
+
+{{#if itemsLength}}
+<div id="{{id}}-datasets" class="history-datasets-list">
+ {{! NOTE: HistoryItemViews will be appended here }}
+</div>
+
+{{else}}{{! no history items }}
+<div class="infomessagesmall" id="emptyHistoryMessage">
+{{#local}}Your history is empty. Click 'Get Data' on the left pane to start{{/local}}
+</div>
+{{/if}}
+</script>
+
+
+
diff -r 78f37cb76a5f981febf36b8119278c59d2319e91 -r 3164ba737fd44f0ec842d6f2d743563d18d1dd74 templates/root/alternate_history.mako
--- a/templates/root/alternate_history.mako
+++ b/templates/root/alternate_history.mako
@@ -97,15 +97,16 @@
# edit attr button
if for_editing:
if not( hda.deleted or hda.purged ):
- edit_url = h.url_for( controller='dataset', action='edit', dataset_id=encoded_data_id )
+ edit_url = h.url_for( controller='dataset', action='edit',
+ dataset_id=encoded_data_id )
add_to_data( edit_url=edit_url )
# delete button
if for_editing and not ( deleted or dataset_purged or purged ):
- add_to_data( delete_url=h.url_for( controller='dataset', action='delete', dataset_id=encoded_data_id,
- ##TODO: loose end
- show_deleted_on_refresh=show_deleted
- ))
+ delete_url = h.url_for( controller='dataset', action='delete',
+ dataset_id=encoded_data_id,
+ show_deleted_on_refresh=show_deleted )
+ add_to_data( delete_url=delete_url )
# ................................................................ primary actions (error, info, download)
# download links (hda and associated meta files)
@@ -127,7 +128,21 @@
# error report
if for_editing:
#NOTE: no state == 'error' check
- add_to_data( report_error_url=h.url_for( h.url_for( controller='dataset', action='errors', id=encoded_data_id ) ) )
+ ##TODO: has to have an _UN_ encoded id
+ #report_error_url = h.url_for( controller='dataset', action='errors', id=encoded_data_id )
+ report_error_url = h.url_for( controller='dataset', action='errors', id=hda.id )
+ add_to_data( report_error_url=report_error_url )
+
+ # info/params
+ show_params_url = h.url_for( controller='dataset', action='show_params', dataset_id=encoded_data_id )
+ add_to_data( show_params_url=show_params_url )
+
+ # rerun
+ if for_editing:
+ ##TODO: has to have an _UN_ encoded id
+ #rerun_url = h.url_for( controller='tool_runner', action='rerun', id=encoded_data_id )
+ rerun_url = h.url_for( controller='tool_runner', action='rerun', id=hda.id )
+ add_to_data( rerun_url=rerun_url )
# visualizations
if hda.ext in app.datatypes_registry.get_available_tracks():
@@ -265,39 +280,61 @@
%></%def>
-
+##TODO: remove after filling tags.js
+<%namespace file="../tagging_common.mako" import="render_individual_tagging_element" /><%def name="context_to_js()"><%
##print 'context', context, dir( context )
##print 'context.kwargs', context.kwargs
##print 'history:', history
- user_is_admin = trans.user_is_admin()
- user_roles = trans.get_current_user_roles()
- prepped_hdas = [
- prep_hda( hda, True ) for hda in datasets ]
+ ##TODO: move to API
+ for_editing = True
context_dict = {
'history' : {
- 'id' : trans.security.encode_id( history.id ),
- 'name' : history.name
+ 'id' : trans.security.encode_id( history.id ),
+ 'name' : history.name,
+
+ 'status' : status,
+ 'showDeleted' : show_deleted,
+ 'showHidden' : show_hidden,
+ 'quotaMsg' : over_quota,
+ 'message' : message, ##'go outside'
+
+ 'deleted' : history.deleted,
+ 'diskSize' : history.get_disk_size( nice_size=True ),
+
+ ## maybe security issues...
+ 'userIsAdmin' : trans.user_is_admin(),
+ 'userRoles' : [ role.get_api_value() for role in trans.get_current_user_roles() ],
+
+ ##tagging_common.mako: render_individual_tagging_element(user=trans.get_user(),
+ ## tagged_item=history, elt_context="history.mako", use_toggle_link=False, input_size="20")
+ 'tags' : [],
+ ##TODO: broken - of course
+ ##TODO: remove after filling tags.js
+ ##'tagHTML' : render_individual_tagging_element(
+ ## user=trans.get_user(),
+ ## tagged_item=history,
+ ## elt_context="history.mako",
+ ## use_toggle_link=False,
+ ## input_size="20"),
+ ##TODO:?? h.to_unicode( annotation ) | h
+ 'annotation' : h.to_unicode( annotation ),
+
+ ##TODO: broken
+ 'baseURL' : h.url_for( 'history', show_deleted=show_deleted ),
+ 'hideDeletedURL' : h.url_for( 'history', show_deleted=False ),
+ 'hideHiddenURL' : h.url_for( 'history', show_hidden=False ),
+ 'tagURL' : h.url_for( controller='history', action='tag' ),
+ 'annotateURL' : h.url_for( controller='history', action='annotate' )
},
- 'annotation' : annotation,
- 'hdas' : prepped_hdas,
- 'hdaId' : hda_id,
- 'showDeleted' : show_deleted,
- 'showHidden' : show_hidden,
- 'quotaMsg' : over_quota,
- 'message' : message,
- 'status' : status,
+ 'hdas' : [ prep_hda( hda, for_editing ) for hda in datasets ],
# some of these may be unneeded when all is said and done...
- 'forEditing' : True,
-
- ## maybe security issues...
- 'userIsAdmin' : user_is_admin,
- 'userRoles' : [ role.get_api_value() for role in user_roles ],
-
+ 'hdaId' : hda_id,
+ 'forEditing' : for_editing,
}
%>
${ h.to_json_string( context_dict ) }
@@ -307,9 +344,7 @@
${parent.javascripts()}
${h.js(
- "libs/jquery/jstorage", "libs/jquery/jquery.autocomplete",
- ##"libs/handlebars.full",
- "galaxy.autocom_tagging",
+ "libs/jquery/jstorage", "libs/jquery/jquery.autocomplete", "galaxy.autocom_tagging",
"mvc/base-mvc", "mvc/ui"
)}
@@ -324,15 +359,12 @@
"template-history-downloadLinks",
"template-history-tagArea",
"template-history-annotationArea",
- "template-history-displayApps"
+ "template-history-displayApps",
+
+ "template-history-historyPanel"
)}
- ## if using in-dom templates they need to go here (before the Backbone classes are defined)
- ##NOTE: it's impossible(?) to include _ templates in this way bc they use identical delims as mako
- ## (without altering Underscore.templateSettings)
- ##<%include file="../../static/scripts/templates/common-templates.html" />
- ##<%include file="../../static/scripts/templates/history-templates.html" />
-
+ ##TODO: fix: curr hasta be _after_ h.templates - move somehow
${h.js(
"mvc/history"
##"mvc/tags", "mvc/annotations"
@@ -345,40 +377,34 @@
// Init. on document load.
var pageData = ${context_to_js()};
-
- //USE_MOCK_DATA = true;
- USE_CURR_DATA = true;
+ if( console && console.debug ){
+ window.pageData = pageData;
+
+ ##_.each( pageData.hdas, function( hda ){
+ ## console.debug( hda );
+ ##});
+ }
// on ready
+ USE_CURR_DATA = true;
$(function(){
if( console && console.debug ){ console.debug( 'using backbone.js in history panel' ); }
- if( window.USE_MOCK_DATA ){
- if( console && console.debug ){ console.debug( '\t using mock data' ); }
- createMockHistoryData();
- return;
-
- //TODO: handle empty history
- } else if ( window.USE_CURR_DATA ){
- if( console && console.debug ){ console.debug( '\t using current history data' ); }
+ if ( window.USE_CURR_DATA ){
+ // Navigate to a dataset.
+ if( pageData.hdaId ){
+ self.location = "#" + pageData.hdaId;
+ }
+
glx_history = new History( pageData.history ).loadDatasetsAsHistoryItems( pageData.hdas );
glx_history_view = new HistoryView({ model: glx_history });
glx_history_view.render();
return;
+
+ } else {
+ // sandbox
}
-
- // sandbox here
- // testing iconButton
- //ibm = new IconButton({
- // icon_class : 'information',
- // on_click : function( event ){ console.debug( 'blerg' ); },
- //});
- //mockObj = { one : 1 };
- //ibv = new IconButtonView({ model : ibm });
- //new_click = function( event ){ console.debug( mockObj.one ); }
- //$( 'body' ).append( ibv.render().$el );
-
});
</script>
@@ -387,7 +413,8 @@
<%def name="stylesheets()">
${parent.stylesheets()}
${h.css("base", "history", "autocomplete_tagging" )}
- <style>"
+ <style>
+ ## TODO: move to base.less
.historyItemBody {
display: none;
}
@@ -425,164 +452,4 @@
${_('Galaxy History')}
</%def>
-<body class="historyPage"></body>
-
-<script type="text/javascript">
-function createMockHistoryData(){
- mockHistory = {};
- mockHistory.data = {
-
- template : {
- id : 'a799d38679e985db',
- name : 'template',
- data_type : 'fastq',
- file_size : 226297533,
- genome_build : '?',
- metadata_data_lines : 0,
- metadata_dbkey : '?',
- metadata_sequences : 0,
- misc_blurb : '215.8 MB',
- misc_info : 'uploaded fastq file (misc_info)',
- model_class : 'HistoryDatasetAssociation',
- download_url : '',
- state : 'ok',
- visible : true,
- deleted : false,
- purged : false,
-
- hid : 0,
- //TODO: move to history
- for_editing : true,
- //for_editing : false,
-
- //?? not needed
- //can_edit : true,
- //can_edit : false,
-
- accessible : true,
-
- //TODO: move into model functions (build there (and cache?))
- //!! be careful with adding these accrd. to permissions
- //!! IOW, don't send them via template/API if the user doesn't have perms to use
- //!! (even if they don't show up)
- undelete_url : '',
- purge_url : '',
- unhide_url : '',
-
- display_url : 'example.com/display',
- edit_url : 'example.com/edit',
- delete_url : 'example.com/delete',
-
- show_params_url : 'example.com/show_params',
- rerun_url : 'example.com/rerun',
-
- retag_url : 'example.com/retag',
- annotate_url : 'example.com/annotate',
-
- peek : [
- '<table cellspacing="0" cellpadding="3"><tr><th>1.QNAME</th><th>2.FLAG</th><th>3.RNAME</th><th>4.POS</th><th>5.MAPQ</th><th>6.CIGAR</th><th>7.MRNM</th><th>8.MPOS</th><th>9.ISIZE</th><th>10.SEQ</th><th>11.QUAL</th><th>12.OPT</th></tr>',
- '<tr><td colspan="100%">@SQ SN:gi|87159884|ref|NC_007793.1| LN:2872769</td></tr>',
- '<tr><td colspan="100%">@PG ID:bwa PN:bwa VN:0.5.9-r16</td></tr>',
- '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 73 gi|87159884|ref|NC_007793.1| 2720169 37 101M = 2720169 0 NAATATGACATTATTTTCAAAACAGCTGAAAATTTAGACGTACCGATTTATCTACATCCCGCGCCAGTTAACAGTGACATTTATCAATCATACTATAAAGG !!!!!!!!!!$!!!$!!!!!$!!!!!!$!$!$$$!!$!!$!!!!!!!!!!!$!</td></tr>',
- '<tr><td colspan="100%">!!!$!$!$$!!$$!!$!!!!!!!!!!!!!!!!!!!!!!!!!!$!!$!! XT:A:U NM:i:1 SM:i:37 AM:i:0 X0:i:1 X1:i:0 XM:i:1 XO:i:0 XG:i:0 MD:Z:0A100</td></tr>',
- '<tr><td colspan="100%">HWUSI-EAS664L:15:64HOJAAXX:1:1:13280:968 133 gi|87159884|ref|NC_007793.1| 2720169 0 * = 2720169 0 NAAACTGTGGCTTCGTTNNNNNNNNNNNNNNNGTGANNNNNNNNNNNNNNNNNNNGNNNNNNNNNNNNNNNNNNNNCNAANNNNNNNNNNNNNNNNNNNNN !!!!!!!!!!!!$!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',
- '<tr><td colspan="100%">!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!</td></tr>',
- '</table>'
- ].join( '' )
- }
-
- };
- _.extend( mockHistory.data, {
-
- notAccessible :
- _.extend( _.clone( mockHistory.data.template ),
- { accessible : false }),
-
- //deleted, purged, visible
- deleted :
- _.extend( _.clone( mockHistory.data.template ),
- { deleted : true,
- delete_url : '',
- purge_url : 'example.com/purge',
- undelete_url : 'example.com/undelete' }),
- purgedNotDeleted :
- _.extend( _.clone( mockHistory.data.template ),
- { purged : true,
- delete_url : '' }),
- notvisible :
- _.extend( _.clone( mockHistory.data.template ),
- { visible : false,
- unhide_url : 'example.com/unhide' }),
-
- hasDisplayApps :
- _.extend( _.clone( mockHistory.data.template ),
- { display_apps : {
- 'display in IGB' : {
- Web: "/display_application/63cd3858d057a6d1/igb_bam/Web",
- Local: "/display_application/63cd3858d057a6d1/igb_bam/Local"
- }
- }
- }
- ),
- canTrackster :
- _.extend( _.clone( mockHistory.data.template ),
- { trackster_urls : {
- 'data-url' : "example.com/trackster-data",
- 'action-url' : "example.com/trackster-action",
- 'new-url' : "example.com/trackster-new"
- }
- }
- ),
- zeroSize :
- _.extend( _.clone( mockHistory.data.template ),
- { file_size : 0 }),
-
- hasMetafiles :
- _.extend( _.clone( mockHistory.data.template ), {
- download_meta_urls : {
- 'bam_index' : "example.com/bam-index"
- }
- }),
-
- //states
- upload :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.UPLOAD }),
- queued :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.QUEUED }),
- running :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.RUNNING }),
- empty :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.EMPTY }),
- error :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.ERROR,
- report_error_url: 'example.com/report_err' }),
- discarded :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.DISCARDED }),
- setting_metadata :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.SETTING_METADATA }),
- failed_metadata :
- _.extend( _.clone( mockHistory.data.template ),
- { state : HistoryItem.STATES.FAILED_METADATA })
-/*
-*/
- });
-
- //mockHistory.views.deleted.logger = console;
- mockHistory.items = {};
- mockHistory.views = {};
- for( key in mockHistory.data ){
- mockHistory.items[ key ] = new HistoryItem( mockHistory.data[ key ] );
- mockHistory.items[ key ].set( 'name', key );
- mockHistory.views[ key ] = new HistoryItemView({ model : mockHistory.items[ key ] });
- //console.debug( 'view: ', mockHistory.views[ key ] );
- $( 'body' ).append( mockHistory.views[ key ].render() );
- }
-}
-</script>
\ No newline at end of file
+<body class="historyPage"></body>
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/78f37cb76a5f/
changeset: 78f37cb76a5f
user: james_taylor
date: 2012-10-01 22:55:29
summary: admin: another import fix
affected #: 1 file
diff -r 3c8f65f7e1a4f4217499f2369907a75a8dbcb4e9 -r 78f37cb76a5f981febf36b8119278c59d2319e91 lib/galaxy/web/base/controllers/admin.py
--- a/lib/galaxy/web/base/controllers/admin.py
+++ b/lib/galaxy/web/base/controllers/admin.py
@@ -4,6 +4,7 @@
from galaxy.model.orm import *
from galaxy.util import inflector
+from galaxy.web.form_builder import CheckboxField
class Admin( object ):
# Override these
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Handle unavailable tool shed when checking for updates to installed tool shed repositories at Galaxy server startup.
by Bitbucket 01 Oct '12
by Bitbucket 01 Oct '12
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/3c8f65f7e1a4/
changeset: 3c8f65f7e1a4
user: greg
date: 2012-10-01 22:31:25
summary: Handle unavailable tool shed when checking for updates to installed tool shed repositories at Galaxy server startup.
affected #: 1 file
diff -r 348ae95c02cca1d6d1b446738631ecbcf76c810a -r 3c8f65f7e1a4f4217499f2369907a75a8dbcb4e9 lib/galaxy/tool_shed/update_manager.py
--- a/lib/galaxy/tool_shed/update_manager.py
+++ b/lib/galaxy/tool_shed/update_manager.py
@@ -36,9 +36,13 @@
tool_shed_url = get_url_from_repository_tool_shed( self.app, repository )
url = '%s/repository/check_for_updates?name=%s&owner=%s&changeset_revision=%s&webapp=update_manager' % \
( tool_shed_url, repository.name, repository.owner, repository.changeset_revision )
- response = urllib2.urlopen( url )
- text = response.read()
- response.close()
+ try:
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ except Exception, e:
+ # The required tool shed may be unavailable.
+ text = 'False'
return string_as_bool( text )
def shutdown( self ):
self.running = False
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: james_taylor: removing webapp parameter from admin templates, fixing an import and some linting errors
by Bitbucket 01 Oct '12
by Bitbucket 01 Oct '12
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/348ae95c02cc/
changeset: 348ae95c02cc
user: james_taylor
date: 2012-10-01 22:16:50
summary: removing webapp parameter from admin templates, fixing an import and some linting errors
affected #: 14 files
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a lib/galaxy/web/base/controllers/admin.py
--- a/lib/galaxy/web/base/controllers/admin.py
+++ b/lib/galaxy/web/base/controllers/admin.py
@@ -1,8 +1,10 @@
-from datetime import date, datetime, timedelta
+from datetime import datetime, timedelta
-from galaxy import config, tools, web, util
+from galaxy import web, util
from galaxy.model.orm import *
+from galaxy.util import inflector
+
class Admin( object ):
# Override these
user_list_grid = None
@@ -296,7 +298,6 @@
@web.expose
@web.require_admin
def mark_role_deleted( self, trans, **kwd ):
- params = util.Params( kwd )
id = kwd.get( 'id', None )
if not id:
message = "No role ids received for deleting"
@@ -319,7 +320,6 @@
@web.expose
@web.require_admin
def undelete_role( self, trans, **kwd ):
- params = util.Params( kwd )
id = kwd.get( 'id', None )
if not id:
message = "No role ids received for undeleting"
@@ -358,7 +358,6 @@
# - DefaultHistoryPermissions where role_id == Role.id
# - GroupRoleAssociations where role_id == Role.id
# - DatasetPermissionss where role_id == Role.id
- params = util.Params( kwd )
id = kwd.get( 'id', None )
if not id:
message = "No role ids received for purging"
@@ -608,7 +607,6 @@
@web.expose
@web.require_admin
def undelete_group( self, trans, **kwd ):
- params = util.Params( kwd )
id = kwd.get( 'id', None )
if not id:
message = "No group ids received for undeleting"
@@ -642,7 +640,6 @@
def purge_group( self, trans, **kwd ):
# This method should only be called for a Group that has previously been deleted.
# Purging a deleted Group simply deletes all UserGroupAssociations and GroupRoleAssociations.
- params = util.Params( kwd )
id = kwd.get( 'id', None )
if not id:
message = "No group ids received for purging"
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/dataset_security/group/group.mako
--- a/templates/admin/dataset_security/group/group.mako
+++ b/templates/admin/dataset_security/group/group.mako
@@ -51,7 +51,6 @@
<div class="toolFormTitle">Group '${group.name}'</div><div class="toolFormBody"><form name="associate_group_role_user" id="associate_group_role_user" action="${h.url_for( action='manage_users_and_roles_for_group', id=trans.security.encode_id( group.id ) )}" method="post" >
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><div class="form-row"><div style="float: left; margin-right: 10px;"><label>Roles associated with '${group.name}'</label>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/dataset_security/group/group_create.mako
--- a/templates/admin/dataset_security/group/group_create.mako
+++ b/templates/admin/dataset_security/group/group_create.mako
@@ -57,7 +57,6 @@
<div class="toolFormBody"><form name="associate_group_role_user" id="associate_group_role_user" action="${h.url_for( action='create_group' )}" method="post" ><div class="form-row">
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><input name="name" type="textfield" value="${name}" size=40"/></div>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/dataset_security/group/group_rename.mako
--- a/templates/admin/dataset_security/group/group_rename.mako
+++ b/templates/admin/dataset_security/group/group_rename.mako
@@ -10,7 +10,6 @@
<div class="toolFormBody"><form name="library" action="${h.url_for( controller='admin', action='rename_group' )}" method="post" ><div class="form-row">
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><div style="float: left; width: 250px; margin-right: 10px;"><input type="text" name="name" value="${group.name}" size="40"/>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/dataset_security/role/role.mako
--- a/templates/admin/dataset_security/role/role.mako
+++ b/templates/admin/dataset_security/role/role.mako
@@ -51,7 +51,6 @@
<div class="toolFormTitle">Role '${role.name}'</div><div class="toolFormBody"><form name="associate_role_user_group" id="associate_role_user_group" action="${h.url_for( action='manage_users_and_groups_for_role', id=trans.security.encode_id( role.id ) )}" method="post" >
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><div class="form-row"><div style="float: left; margin-right: 10px;"><label>Users associated with '${role.name}'</label>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/dataset_security/role/role_create.mako
--- a/templates/admin/dataset_security/role/role_create.mako
+++ b/templates/admin/dataset_security/role/role_create.mako
@@ -57,7 +57,6 @@
<div class="toolFormBody"><form name="associate_role_group_user" id="associate_role_group_user" action="${h.url_for( action='create_role' )}" method="post" ><div class="form-row">
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><input name="name" type="textfield" value="${name}" size=40"/></div>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/dataset_security/role/role_rename.mako
--- a/templates/admin/dataset_security/role/role_rename.mako
+++ b/templates/admin/dataset_security/role/role_rename.mako
@@ -10,7 +10,6 @@
<div class="toolFormBody"><form name="library" action="${h.url_for( controller='admin', action='rename_role' )}" method="post" ><div class="form-row">
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><div style="float: left; width: 250px; margin-right: 10px;"><input type="text" name="name" value="${role.name}" size="40"/>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/quota/quota.mako
--- a/templates/admin/quota/quota.mako
+++ b/templates/admin/quota/quota.mako
@@ -51,7 +51,6 @@
<div class="toolFormTitle">Quota '${name}'</div><div class="toolFormBody"><form name="associate_quota_user_group" id="associate_quota_user_group" action="${h.url_for( action='manage_users_and_groups_for_quota', id=id )}" method="post" >
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><div class="form-row"><div style="float: left; margin-right: 10px;"><label>Users associated with '${name}'</label>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/quota/quota_create.mako
--- a/templates/admin/quota/quota_create.mako
+++ b/templates/admin/quota/quota_create.mako
@@ -66,7 +66,6 @@
<div class="toolFormBody"><form name="associate_quota_group_user" id="associate_quota_group_user" action="${h.url_for( action='create_quota' )}" method="post" ><div class="form-row">
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><input name="name" type="textfield" value="${name}" size=40"/></div>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/quota/quota_edit.mako
--- a/templates/admin/quota/quota_edit.mako
+++ b/templates/admin/quota/quota_edit.mako
@@ -26,7 +26,6 @@
<div class="toolFormTitle">Change quota amount</div><div class="toolFormBody"><form name="library" action="${h.url_for( controller='admin', action='edit_quota' )}" method="post" >
- <input name="webapp" type="hidden" value="${webapp}"/><input name="id" type="hidden" value="${id}"/><div class="form-row"><label>Amount</label>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/quota/quota_rename.mako
--- a/templates/admin/quota/quota_rename.mako
+++ b/templates/admin/quota/quota_rename.mako
@@ -19,7 +19,6 @@
<div class="toolFormBody"><form name="library" action="${h.url_for( controller='admin', action='rename_quota' )}" method="post" ><div class="form-row">
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><label>Name:</label><div style="float: left; width: 250px; margin-right: 10px;"><input type="text" name="name" value="${name}" size="40"/>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/quota/quota_set_default.mako
--- a/templates/admin/quota/quota_set_default.mako
+++ b/templates/admin/quota/quota_set_default.mako
@@ -28,7 +28,6 @@
<div class="toolFormTitle">Set quota default</div><div class="toolFormBody"><form name="set_quota_default" id="set_quota_default" action="${h.url_for( action='set_quota_default' )}" method="post" >
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><input name="id" type="hidden" value="${id}"/><div class="form-row"><label>Is this quota a default for a class of users (if yes, what type)?</label>
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/user/reset_password.mako
--- a/templates/admin/user/reset_password.mako
+++ b/templates/admin/user/reset_password.mako
@@ -9,7 +9,6 @@
<div class="toolFormTitle">Reset password for users</div><div class="toolFormBody"><form name="form" action="${h.url_for( controller='admin', action='reset_user_password' )}" method="post" >
- <input name="webapp" type="hidden" value="${webapp}" size=40"/><input type="hidden" name="id" value="${id}" size="40">
%for user in users:
<div class="form-row">
diff -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf -r 348ae95c02cca1d6d1b446738631ecbcf76c810a templates/admin/user/user.mako
--- a/templates/admin/user/user.mako
+++ b/templates/admin/user/user.mako
@@ -76,7 +76,6 @@
</div></div><div class="form-row">
- <input type="hidden" name="webapp" value="${webapp}"/><input type="submit" name="user_roles_groups_edit_button" value="Save"/></div></form>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: james_taylor: test framework: no longer pass webapp argument to requests
by Bitbucket 01 Oct '12
by Bitbucket 01 Oct '12
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/2e0d02ea0aaf/
changeset: 2e0d02ea0aaf
user: james_taylor
date: 2012-10-01 21:24:36
summary: test framework: no longer pass webapp argument to requests
affected #: 2 files
diff -r cda0af45c3d3bd4fa9e62b37b5cc91f5272a0178 -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf test/base/twilltestcase.py
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -835,12 +835,11 @@
self.assertTrue( genome_build == dbkey )
# Functions associated with user accounts
- def create( self, cntrller='user', email='test(a)bx.psu.edu', password='testuser', username='admin-user', webapp='galaxy', redirect='' ):
+ def create( self, cntrller='user', email='test(a)bx.psu.edu', password='testuser', username='admin-user', redirect='' ):
# HACK: don't use panels because late_javascripts() messes up the twill browser and it
# can't find form fields (and hence user can't be logged in).
self.visit_url( "%s/user/create?cntrller=%s&use_panels=False" % ( self.url, cntrller ) )
tc.fv( '1', 'email', email )
- tc.fv( '1', 'webapp', webapp )
tc.fv( '1', 'redirect', redirect )
tc.fv( '1', 'password', password )
tc.fv( '1', 'confirm', password )
@@ -945,17 +944,16 @@
self.visit_url( "%s/%s" % ( self.url, url ) )
self.check_page_for_string( 'Default history permissions have been changed.' )
self.home()
- def login( self, email='test(a)bx.psu.edu', password='testuser', username='admin-user', webapp='galaxy', redirect='' ):
+ def login( self, email='test(a)bx.psu.edu', password='testuser', username='admin-user', redirect='' ):
# test(a)bx.psu.edu is configured as an admin user
previously_created, username_taken, invalid_username = \
- self.create( email=email, password=password, username=username, webapp=webapp, redirect=redirect )
+ self.create( email=email, password=password, username=username, redirect=redirect )
if previously_created:
# The acount has previously been created, so just login.
# HACK: don't use panels because late_javascripts() messes up the twill browser and it
# can't find form fields (and hence user can't be logged in).
self.visit_url( "%s/user/login?use_panels=False" % self.url )
tc.fv( '1', 'email', email )
- tc.fv( '1', 'webapp', webapp )
tc.fv( '1', 'redirect', redirect )
tc.fv( '1', 'password', password )
tc.submit( 'login_button' )
@@ -1221,13 +1219,12 @@
# Dataset Security stuff
# Tests associated with users
def create_new_account_as_admin( self, email='test4(a)bx.psu.edu', password='testuser',
- username='regular-user4', webapp='galaxy', redirect='' ):
+ username='regular-user4', redirect='' ):
"""Create a new account for another user"""
# HACK: don't use panels because late_javascripts() messes up the twill browser and it
# can't find form fields (and hence user can't be logged in).
self.visit_url( "%s/user/create?cntrller=admin" % self.url )
tc.fv( '1', 'email', email )
- tc.fv( '1', 'webapp', webapp )
tc.fv( '1', 'redirect', redirect )
tc.fv( '1', 'password', password )
tc.fv( '1', 'confirm', password )
diff -r cda0af45c3d3bd4fa9e62b37b5cc91f5272a0178 -r 2e0d02ea0aaf51301582671740c9281a1a8e15cf test/functional/test_admin_features.py
--- a/test/functional/test_admin_features.py
+++ b/test/functional/test_admin_features.py
@@ -29,7 +29,6 @@
previously_created, username_taken, invalid_username = self.create_new_account_as_admin( email='diff(a)you.com',
password=password,
username='admin-user',
- webapp='galaxy',
redirect='' )
if not username_taken:
raise AssertionError, "The public name (%s) is already being used by another user, but no error was displayed" \
@@ -39,14 +38,12 @@
previously_created, username_taken, invalid_username = self.create_new_account_as_admin( email='diff(a)you.com',
password=password,
username='h',
- webapp='galaxy',
redirect='' )
if not invalid_username:
raise AssertionError, "The public name (%s) is is invalid, but no error was displayed" % username
previously_created, username_taken, invalid_username = self.create_new_account_as_admin( email=email,
password=password,
username='regular-user3',
- webapp='galaxy',
redirect='' )
# Get the user object for later tests
global regular_user3
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Handle unavailable main Galaxy tool shed when checking for migrated tools.
by Bitbucket 01 Oct '12
by Bitbucket 01 Oct '12
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/cda0af45c3d3/
changeset: cda0af45c3d3
user: greg
date: 2012-10-01 21:04:52
summary: Handle unavailable main Galaxy tool shed when checking for migrated tools.
affected #: 2 files
diff -r 4ccb8691639233bb99b4f3e3ebb9b9eacf4c9461 -r cda0af45c3d3bd4fa9e62b37b5cc91f5272a0178 lib/galaxy/tool_shed/migrate/check.py
--- a/lib/galaxy/tool_shed/migrate/check.py
+++ b/lib/galaxy/tool_shed/migrate/check.py
@@ -43,6 +43,8 @@
db_schema = schema.ControlledSchema( engine, migrate_repository )
latest_tool_migration_script_number = migrate_repository.versions.latest
if latest_tool_migration_script_number != db_schema.version:
+ # The default behavior is that the tool shed is down.
+ tool_shed_accessible = False
if app.new_installation:
# New installations will not be missing tools, so we don't need to worry about them.
missing_tool_configs_dict = odict()
@@ -51,8 +53,12 @@
if tool_panel_configs:
# The missing_tool_configs_dict contents are something like:
# {'emboss_antigenic.xml': [('emboss', '5.0.0', 'package', '\nreadme blah blah blah\n')]}
- missing_tool_configs_dict = check_for_missing_tools( app, tool_panel_configs, latest_tool_migration_script_number )
+ tool_shed_accessible, missing_tool_configs_dict = check_for_missing_tools( app, tool_panel_configs, latest_tool_migration_script_number )
else:
+ # It doesn't matter if the tool shed is accessible since there are no migrated tools defined in the local Galaxy instance, but
+ # we have to set the value of tool_shed_accessible to True so that the value of migrate_tools.version can be correctly set in
+ # the database.
+ tool_shed_accessible = True
missing_tool_configs_dict = odict()
have_tool_dependencies = False
for k, v in missing_tool_configs_dict.items():
@@ -63,79 +69,82 @@
if os.path.abspath( os.path.join( os.getcwd(), 'universe_wsgi.ini' ) ) != galaxy_config_file:
config_arg = ' -c %s' % galaxy_config_file.replace( os.path.abspath( os.getcwd() ), '.' )
if not app.config.running_functional_tests:
- # Automatically update the value of the migrate_tools.version database table column.
- cmd = 'sh manage_tools.sh%s upgrade' % config_arg
- proc = subprocess.Popen( args=cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
- return_code = proc.wait()
- output = proc.stdout.read( 32768 )
- if return_code != 0:
- raise Exception( "Error attempting to update the value of migrate_tools.version: %s" % output )
- elif missing_tool_configs_dict:
- if len( tool_panel_configs ) == 1:
- plural = ''
- tool_panel_config_file_names = tool_panel_configs[ 0 ]
- else:
- plural = 's'
- tool_panel_config_file_names = ', '.join( tool_panel_configs )
- msg = "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
- msg += "\n\nThe list of files at the end of this message refers to tools that are configured to load into the tool panel for\n"
- msg += "this Galaxy instance, but have been removed from the Galaxy distribution. These tools and their dependencies can be\n"
- msg += "automatically installed from the Galaxy tool shed at http://toolshed.g2.bx.psu.edu.\n\n"
- msg += "To skip this process, attempt to start your Galaxy server again (e.g., sh run.sh or whatever you use). If you do this,\n"
- msg += "be aware that these tools will no longer be available in your Galaxy tool panel, and entries for each of them should\n"
- msg += "be removed from your file%s named %s.\n\n" % ( plural, tool_panel_config_file_names )
- msg += "CRITICAL NOTE IF YOU PLAN TO INSTALL\n"
- msg += "The location in which the tool repositories will be installed is the value of the 'tool_path' attribute in the <tool>\n"
- msg += 'tag of the file named ./migrated_tool_conf.xml (i.e., <toolbox tool_path="../shed_tools">). The default location\n'
- msg += "setting is '../shed_tools', which may be problematic for some cluster environments, so make sure to change it before\n"
- msg += "you execute the installation process if appropriate. The configured location must be outside of the Galaxy installation\n"
- msg += "directory or it must be in a sub-directory protected by a properly configured .hgignore file if the directory is within\n"
- msg += "the Galaxy installation directory hierarchy. This is because tool shed repositories will be installed using mercurial's\n"
- msg += "clone feature, which creates .hg directories and associated mercurial repository files. Not having .hgignore properly\n"
- msg += "configured could result in undesired behavior when modifying or updating your local Galaxy instance or the tool shed\n"
- msg += "repositories if they are in directories that pose conflicts. See mercurial's .hgignore documentation at the following\n"
- msg += "URL for details.\n\nhttp://mercurial.selenic.com/wiki/.hgignore\n\n"
- if have_tool_dependencies:
- msg += "The following tool dependencies can also optionally be installed (see the option flag in the command below). If you\n"
- msg += "choose to install them (recommended), they will be installed within the location specified by the 'tool_dependency_dir'\n"
- msg += "setting in your main Galaxy configuration file (e.g., uninverse_wsgi.ini).\n"
- processed_tool_dependencies = []
+ if tool_shed_accessible:
+ # Automatically update the value of the migrate_tools.version database table column.
+ cmd = 'sh manage_tools.sh%s upgrade' % config_arg
+ proc = subprocess.Popen( args=cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT )
+ return_code = proc.wait()
+ output = proc.stdout.read( 32768 )
+ if return_code != 0:
+ raise Exception( "Error attempting to update the value of migrate_tools.version: %s" % output )
+ elif missing_tool_configs_dict:
+ if len( tool_panel_configs ) == 1:
+ plural = ''
+ tool_panel_config_file_names = tool_panel_configs[ 0 ]
+ else:
+ plural = 's'
+ tool_panel_config_file_names = ', '.join( tool_panel_configs )
+ msg = "\n>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>"
+ msg += "\n\nThe list of files at the end of this message refers to tools that are configured to load into the tool panel for\n"
+ msg += "this Galaxy instance, but have been removed from the Galaxy distribution. These tools and their dependencies can be\n"
+ msg += "automatically installed from the Galaxy tool shed at http://toolshed.g2.bx.psu.edu.\n\n"
+ msg += "To skip this process, attempt to start your Galaxy server again (e.g., sh run.sh or whatever you use). If you do this,\n"
+ msg += "be aware that these tools will no longer be available in your Galaxy tool panel, and entries for each of them should\n"
+ msg += "be removed from your file%s named %s.\n\n" % ( plural, tool_panel_config_file_names )
+ msg += "CRITICAL NOTE IF YOU PLAN TO INSTALL\n"
+ msg += "The location in which the tool repositories will be installed is the value of the 'tool_path' attribute in the <tool>\n"
+ msg += 'tag of the file named ./migrated_tool_conf.xml (i.e., <toolbox tool_path="../shed_tools">). The default location\n'
+ msg += "setting is '../shed_tools', which may be problematic for some cluster environments, so make sure to change it before\n"
+ msg += "you execute the installation process if appropriate. The configured location must be outside of the Galaxy installation\n"
+ msg += "directory or it must be in a sub-directory protected by a properly configured .hgignore file if the directory is within\n"
+ msg += "the Galaxy installation directory hierarchy. This is because tool shed repositories will be installed using mercurial's\n"
+ msg += "clone feature, which creates .hg directories and associated mercurial repository files. Not having .hgignore properly\n"
+ msg += "configured could result in undesired behavior when modifying or updating your local Galaxy instance or the tool shed\n"
+ msg += "repositories if they are in directories that pose conflicts. See mercurial's .hgignore documentation at the following\n"
+ msg += "URL for details.\n\nhttp://mercurial.selenic.com/wiki/.hgignore\n\n"
+ if have_tool_dependencies:
+ msg += "The following tool dependencies can also optionally be installed (see the option flag in the command below). If you\n"
+ msg += "choose to install them (recommended), they will be installed within the location specified by the 'tool_dependency_dir'\n"
+ msg += "setting in your main Galaxy configuration file (e.g., uninverse_wsgi.ini).\n"
+ processed_tool_dependencies = []
+ for missing_tool_config, tool_dependencies in missing_tool_configs_dict.items():
+ for tool_dependencies_tup in tool_dependencies:
+ if tool_dependencies_tup not in processed_tool_dependencies:
+ msg += "------------------------------------\n"
+ msg += "Tool Dependency\n"
+ msg += "------------------------------------\n"
+ msg += "Name: %s, Version: %s, Type: %s\n" % ( tool_dependencies_tup[ 0 ],
+ tool_dependencies_tup[ 1 ],
+ tool_dependencies_tup[ 2 ] )
+ if tool_dependencies_tup[ 3 ]:
+ msg += "Requirements and installation information:\n"
+ msg += "%s\n" % tool_dependencies_tup[ 3 ]
+ else:
+ msg += "\n"
+ msg += "------------------------------------\n"
+ processed_tool_dependencies.append( tool_dependencies_tup )
+ msg += "\n"
+ msg += "%s" % output.replace( 'done', '' )
+ msg += "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ msg += "sh ./scripts/migrate_tools/%04d_tools.sh\n" % latest_tool_migration_script_number
+ msg += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"
+ if have_tool_dependencies:
+ msg += "The tool dependencies listed above will be installed along with the repositories if you add the 'install_dependencies'\n"
+ msg += "option to the above command like this:\n\n"
+ msg += "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
+ msg += "sh ./scripts/migrate_tools/%04d_tools.sh install_dependencies\n" % latest_tool_migration_script_number
+ msg += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"
+ msg += "Tool dependencies can be installed after the repositories have been installed as well.\n\n"
+ msg += "After the installation process finishes, you can start your Galaxy server. As part of this installation process,\n"
+ msg += "entries for each of the following tool config files will be added to the file named ./migrated_tool_conf.xml, so these\n"
+ msg += "tools will continue to be loaded into your tool panel. Because of this, existing entries for these files should be\n"
+ msg += "removed from your file%s named %s, but only after the installation process finishes.\n\n" % ( plural, tool_panel_config_file_names )
for missing_tool_config, tool_dependencies in missing_tool_configs_dict.items():
- for tool_dependencies_tup in tool_dependencies:
- if tool_dependencies_tup not in processed_tool_dependencies:
- msg += "------------------------------------\n"
- msg += "Tool Dependency\n"
- msg += "------------------------------------\n"
- msg += "Name: %s, Version: %s, Type: %s\n" % ( tool_dependencies_tup[ 0 ],
- tool_dependencies_tup[ 1 ],
- tool_dependencies_tup[ 2 ] )
- if tool_dependencies_tup[ 3 ]:
- msg += "Requirements and installation information:\n"
- msg += "%s\n" % tool_dependencies_tup[ 3 ]
- else:
- msg += "\n"
- msg += "------------------------------------\n"
- processed_tool_dependencies.append( tool_dependencies_tup )
- msg += "\n"
- msg += "%s" % output.replace( 'done', '' )
- msg += "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
- msg += "sh ./scripts/migrate_tools/%04d_tools.sh\n" % latest_tool_migration_script_number
- msg += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"
- if have_tool_dependencies:
- msg += "The tool dependencies listed above will be installed along with the repositories if you add the 'install_dependencies'\n"
- msg += "option to the above command like this:\n\n"
- msg += "vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv\n"
- msg += "sh ./scripts/migrate_tools/%04d_tools.sh install_dependencies\n" % latest_tool_migration_script_number
- msg += "^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n\n"
- msg += "Tool dependencies can be installed after the repositories have been installed as well.\n\n"
- msg += "After the installation process finishes, you can start your Galaxy server. As part of this installation process,\n"
- msg += "entries for each of the following tool config files will be added to the file named ./migrated_tool_conf.xml, so these\n"
- msg += "tools will continue to be loaded into your tool panel. Because of this, existing entries for these files should be\n"
- msg += "removed from your file%s named %s, but only after the installation process finishes.\n\n" % ( plural, tool_panel_config_file_names )
- for missing_tool_config, tool_dependencies in missing_tool_configs_dict.items():
- msg += "%s\n" % missing_tool_config
- msg += "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
- raise Exception( msg )
+ msg += "%s\n" % missing_tool_config
+ msg += "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n"
+ raise Exception( msg )
+ else:
+ log.debug( "The main Galaxy tool shed is not currently available, so skipped tool migration %s until next server startup" % db_schema.version )
else:
log.info( "At migrate_tools version %d" % db_schema.version )
diff -r 4ccb8691639233bb99b4f3e3ebb9b9eacf4c9461 -r cda0af45c3d3bd4fa9e62b37b5cc91f5272a0178 lib/galaxy/tool_shed/migrate/common.py
--- a/lib/galaxy/tool_shed/migrate/common.py
+++ b/lib/galaxy/tool_shed/migrate/common.py
@@ -21,6 +21,8 @@
root = tree.getroot()
tool_shed = root.get( 'name' )
tool_shed_url = get_tool_shed_url_from_tools_xml_file_path( app, tool_shed )
+ # The default behavior is that the tool shed is down.
+ tool_shed_accessible = False
if tool_shed_url:
for elem in root:
if elem.tag == 'repository':
@@ -30,36 +32,44 @@
changeset_revision = elem.get( 'changeset_revision' )
url = '%s/repository/get_tool_dependencies?name=%s&owner=%s&changeset_revision=%s&webapp=install_manager' % \
( tool_shed_url, repository_name, REPOSITORY_OWNER, changeset_revision )
- response = urllib2.urlopen( url )
- text = response.read()
- response.close()
- if text:
- tool_dependencies_dict = tool_shed_decode( text )
- for dependency_key, requirements_dict in tool_dependencies_dict.items():
- tool_dependency_name = requirements_dict[ 'name' ]
- tool_dependency_version = requirements_dict[ 'version' ]
- tool_dependency_type = requirements_dict[ 'type' ]
- tool_dependency_readme = requirements_dict.get( 'readme', '' )
- tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type, tool_dependency_readme ) )
- for tool_elem in elem.findall( 'tool' ):
- migrated_tool_configs_dict[ tool_elem.get( 'file' ) ] = tool_dependencies
- # Parse the proprietary tool_panel_configs (the default is tool_conf.xml) and generate the list of missing tool config file names.
- missing_tool_configs_dict = odict()
- for tool_panel_config in tool_panel_configs:
- tree = util.parse_xml( tool_panel_config )
- root = tree.getroot()
- for elem in root:
- if elem.tag == 'tool':
- missing_tool_configs_dict = check_tool_tag_set( elem, migrated_tool_configs_dict, missing_tool_configs_dict )
- elif elem.tag == 'section':
- for section_elem in elem:
- if section_elem.tag == 'tool':
- missing_tool_configs_dict = check_tool_tag_set( section_elem, migrated_tool_configs_dict, missing_tool_configs_dict )
+ try:
+ response = urllib2.urlopen( url )
+ text = response.read()
+ response.close()
+ tool_shed_accessible = True
+ except Exception, e:
+ # Tool shed may be unavailable - we have to set tool_shed_accessible since we're looping.
+ tool_shed_accessible = False
+ print "The URL\n%s\nraised the exception:\n%s\n" % ( url, str( e ) )
+ if tool_shed_accessible:
+ if text:
+ tool_dependencies_dict = tool_shed_decode( text )
+ for dependency_key, requirements_dict in tool_dependencies_dict.items():
+ tool_dependency_name = requirements_dict[ 'name' ]
+ tool_dependency_version = requirements_dict[ 'version' ]
+ tool_dependency_type = requirements_dict[ 'type' ]
+ tool_dependency_readme = requirements_dict.get( 'readme', '' )
+ tool_dependencies.append( ( tool_dependency_name, tool_dependency_version, tool_dependency_type, tool_dependency_readme ) )
+ for tool_elem in elem.findall( 'tool' ):
+ migrated_tool_configs_dict[ tool_elem.get( 'file' ) ] = tool_dependencies
+ if tool_shed_accessible:
+ # Parse the proprietary tool_panel_configs (the default is tool_conf.xml) and generate the list of missing tool config file names.
+ missing_tool_configs_dict = odict()
+ for tool_panel_config in tool_panel_configs:
+ tree = util.parse_xml( tool_panel_config )
+ root = tree.getroot()
+ for elem in root:
+ if elem.tag == 'tool':
+ missing_tool_configs_dict = check_tool_tag_set( elem, migrated_tool_configs_dict, missing_tool_configs_dict )
+ elif elem.tag == 'section':
+ for section_elem in elem:
+ if section_elem.tag == 'tool':
+ missing_tool_configs_dict = check_tool_tag_set( section_elem, migrated_tool_configs_dict, missing_tool_configs_dict )
else:
exception_msg = '\n\nThe entry for the main Galaxy tool shed at %s is missing from the %s file. ' % ( tool_shed, app.config.tool_sheds_config )
exception_msg += 'The entry for this tool shed must always be available in this file, so re-add it before attempting to start your Galaxy server.\n'
raise Exception( exception_msg )
- return missing_tool_configs_dict
+ return tool_shed_accessible, missing_tool_configs_dict
def check_tool_tag_set( elem, migrated_tool_configs_dict, missing_tool_configs_dict ):
file_path = elem.get( 'file', None )
if file_path:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: pgcleanup: Print a useful message if no options are given.
by Bitbucket 01 Oct '12
by Bitbucket 01 Oct '12
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/4ccb86916392/
changeset: 4ccb86916392
user: natefoo
date: 2012-10-01 19:45:37
summary: pgcleanup: Print a useful message if no options are given.
affected #: 1 file
diff -r 844e566f36acc3d94856a55c0d4d4dcf291f8b81 -r 4ccb8691639233bb99b4f3e3ebb9b9eacf4c9461 scripts/cleanup_datasets/pgcleanup.py
--- a/scripts/cleanup_datasets/pgcleanup.py
+++ b/scripts/cleanup_datasets/pgcleanup.py
@@ -76,6 +76,11 @@
self.options.sequence = [ x.strip() for x in self.options.sequence.split(',') ]
+ if self.options.sequence == ['']:
+ print "Error: At least one action must be specified in the action sequence\n"
+ parser.print_help()
+ sys.exit(0)
+
def __setup_logging(self):
format = "%(funcName)s %(levelname)s %(asctime)s %(message)s"
if self.options.debug:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
01 Oct '12
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/changeset/844e566f36ac/
changeset: 844e566f36ac
user: greg
date: 2012-10-01 18:24:53
summary: Handle the case where a tool dependency definition changed in a tool shed repository and the new definition was pulled to a Galaxy installed repository when the Galaxy admin got updates for the repository.
affected #: 5 files
diff -r de2c99ce5f749582c3ce3bfb02422588c70b1a06 -r 844e566f36acc3d94856a55c0d4d4dcf291f8b81 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -3077,10 +3077,16 @@
self.error_message = error_message
@property
def can_install( self ):
- return self.status in [ self.installation_status.NEVER_INSTALLED, self.installation_status.UNINSTALLED ]
+ return self.status in [ self.installation_status.NEVER_INSTALLED, self.installation_status.UNINSTALLED ]
@property
def can_uninstall( self ):
- return self.status in [ self.installation_status.ERROR, self.installation_status.INSTALLED ]
+ return self.status in [ self.installation_status.ERROR, self.installation_status.INSTALLED ]
+ @property
+ def can_update( self ):
+ return self.status in [ self.installation_status.NEVER_INSTALLED,
+ self.installation_status.INSTALLED,
+ self.installation_status.ERROR,
+ self.installation_status.UNINSTALLED ]
@property
def in_error_state( self ):
return self.status == self.installation_status.ERROR
diff -r de2c99ce5f749582c3ce3bfb02422588c70b1a06 -r 844e566f36acc3d94856a55c0d4d4dcf291f8b81 lib/galaxy/tool_shed/install_manager.py
--- a/lib/galaxy/tool_shed/install_manager.py
+++ b/lib/galaxy/tool_shed/install_manager.py
@@ -138,6 +138,7 @@
relative_install_dir=relative_install_dir,
repository_files_dir=None,
resetting_all_metadata_on_repository=False,
+ updating_installed_repository=False,
webapp='galaxy' )
tool_shed_repository.metadata = metadata_dict
self.app.sa_session.add( tool_shed_repository )
diff -r de2c99ce5f749582c3ce3bfb02422588c70b1a06 -r 844e566f36acc3d94856a55c0d4d4dcf291f8b81 lib/galaxy/util/shed_util.py
--- a/lib/galaxy/util/shed_util.py
+++ b/lib/galaxy/util/shed_util.py
@@ -528,7 +528,6 @@
status=app.model.ToolDependency.installation_status.NEVER_INSTALLED,
set_status=set_status )
tool_dependency_objects.append( tool_dependency )
-
elif tool_dependency_type == 'set_environment':
for env_elem in elem:
# <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable>
@@ -603,13 +602,19 @@
tool_dependencies_dict[ 'set_environment' ] = [ requirements_dict ]
return tool_dependencies_dict
def generate_metadata_for_changeset_revision( app, repository, repository_clone_url, relative_install_dir=None, repository_files_dir=None,
- resetting_all_metadata_on_repository=False, webapp='galaxy' ):
+ resetting_all_metadata_on_repository=False, updating_installed_repository=False, webapp='galaxy' ):
"""
Generate metadata for a repository using it's files on disk. To generate metadata for changeset revisions older than the repository tip,
the repository will have been cloned to a temporary location and updated to a specified changeset revision to access that changeset revision's
disk files, so the value of repository_files_dir will not always be repository.repo_path (it could be an absolute path to a temporary directory
containing a clone). If it is an absolute path, the value of relative_install_dir must contain repository.repo_path.
"""
+ if updating_installed_repository:
+ # Keep the original tool shed repository metadata if setting metadata on a repository installed into a local Galaxy instance for which
+ # we have pulled updates.
+ original_repository_metadata = repository.metadata
+ else:
+ original_repository_metadata = None
readme_file_names = get_readme_file_names( repository.name )
metadata_dict = {}
invalid_file_tups = []
@@ -724,7 +729,11 @@
# This step must be done after metadata for tools has been defined.
tool_dependencies_config = get_config_from_disk( 'tool_dependencies.xml', files_dir )
if tool_dependencies_config:
- metadata_dict = generate_tool_dependency_metadata( tool_dependencies_config, metadata_dict )
+ metadata_dict = generate_tool_dependency_metadata( app,
+ repository,
+ tool_dependencies_config,
+ metadata_dict,
+ original_repository_metadata=original_repository_metadata )
if invalid_tool_configs:
metadata_dict [ 'invalid_tools' ] = invalid_tool_configs
# Reset the value of the app's tool_data_path and tool_data_table_config_path to their respective original values.
@@ -747,11 +756,16 @@
if requirements_dict:
tool_dependencies_dict[ dependency_key ] = requirements_dict
return tool_dependencies_dict
-def generate_tool_dependency_metadata( tool_dependencies_config, metadata_dict ):
+def generate_tool_dependency_metadata( app, repository, tool_dependencies_config, metadata_dict, original_repository_metadata=None ):
"""
If the combination of name, version and type of each element is defined in the <requirement> tag for at least one tool in the repository,
then update the received metadata_dict with information from the parsed tool_dependencies_config.
"""
+ if original_repository_metadata:
+ # Keep a copy of the original tool dependencies dictionary in the metadata.
+ original_tool_dependencies_dict = original_repository_metadata.get( 'tool_dependencies', None )
+ else:
+ original_tool_dependencies_dict = None
try:
tree = ElementTree.parse( tool_dependencies_config )
except Exception, e:
@@ -770,6 +784,10 @@
if tool_dependencies_dict:
metadata_dict[ 'tool_dependencies' ] = tool_dependencies_dict
if tool_dependencies_dict:
+ if original_tool_dependencies_dict:
+ # We're generating metadata on an update pulled to a tool shed repository installed into a Galaxy instance, so handle changes to
+ # tool dependencies appropriately.
+ handle_existing_tool_dependencies_that_changed_in_update( app, repository, original_tool_dependencies_dict, tool_dependencies_dict )
metadata_dict[ 'tool_dependencies' ] = tool_dependencies_dict
return metadata_dict
def generate_tool_guid( repository_clone_url, tool ):
@@ -1470,6 +1488,24 @@
# Reset the tool_data_tables by loading the empty tool_data_table_conf.xml file.
reset_tool_data_tables( app )
return repository_tools_tups
+def handle_existing_tool_dependencies_that_changed_in_update( app, repository, original_dependency_dict, new_dependency_dict ):
+ """
+ This method is called when a Galaxy admin is getting updates for an installed tool shed repository in order to cover the case where an
+ existing tool dependency was changed (e.g., the version of the dependency was changed) but the tool version for which it is a dependency
+ was not changed. In this case, we only want to determine if any of the dependency information defined in original_dependency_dict was
+ changed in new_dependency_dict. We don't care if new dependencies were added in new_dependency_dict since they will just be treated as
+ missing dependencies for the tool.
+ """
+ updated_tool_dependency_names = []
+ deleted_tool_dependency_names = []
+ for original_dependency_key, original_dependency_val_dict in original_dependency_dict.items():
+ if original_dependency_key not in new_dependency_dict:
+ updated_tool_dependency = update_existing_tool_dependency( app, repository, original_dependency_val_dict, new_dependency_dict )
+ if updated_tool_dependency:
+ updated_tool_dependency_names.append( updated_tool_dependency.name )
+ else:
+ deleted_tool_dependency_names.append( original_dependency_val_dict[ 'name' ] )
+ return updated_tool_dependency_names, deleted_tool_dependency_names
def handle_missing_index_file( app, tool_path, sample_files, repository_tools_tups, sample_files_copied ):
"""
Inspect each tool to see if it has any input parameters that are dynamically generated select lists that depend on a .loc file.
@@ -1862,21 +1898,28 @@
trans.app.toolbox.write_integrated_tool_panel_config_file()
def remove_tool_dependency( trans, tool_dependency ):
dependency_install_dir = tool_dependency.installation_directory( trans.app )
- try:
- shutil.rmtree( dependency_install_dir )
- removed = True
- error_message = ''
- log.debug( "Removed tool dependency installation directory: %s" % str( dependency_install_dir ) )
- except Exception, e:
- removed = False
- error_message = "Error removing tool dependency installation directory %s: %s" % ( str( dependency_install_dir ), str( e ) )
- log.debug( error_message )
+ removed, error_message = remove_tool_dependency_installation_directory( dependency_install_dir )
if removed:
tool_dependency.status = trans.model.ToolDependency.installation_status.UNINSTALLED
tool_dependency.error_message = None
trans.sa_session.add( tool_dependency )
trans.sa_session.flush()
return removed, error_message
+def remove_tool_dependency_installation_directory( dependency_install_dir ):
+ if os.path.exists( dependency_install_dir ):
+ try:
+ shutil.rmtree( dependency_install_dir )
+ removed = True
+ error_message = ''
+ log.debug( "Removed tool dependency installation directory: %s" % str( dependency_install_dir ) )
+ except Exception, e:
+ removed = False
+ error_message = "Error removing tool dependency installation directory %s: %s" % ( str( dependency_install_dir ), str( e ) )
+ log.debug( error_message )
+ else:
+ removed = True
+ error_message = ''
+ return removed, error_message
def reset_tool_data_tables( app ):
# Reset the tool_data_tables to an empty dictionary.
app.tool_data_tables.data_tables = {}
@@ -1925,7 +1968,7 @@
translated.append( '' )
return ''.join( translated )
def to_html_str( text ):
- """Translates the characters in text to sn html string"""
+ """Translates the characters in text to an html string"""
translated = []
for c in text:
if c in VALID_CHARS:
@@ -1954,6 +1997,63 @@
else:
translated_string = ''
return translated_string
+def update_existing_tool_dependency( app, repository, original_dependency_dict, new_dependencies_dict ):
+ """
+ Update an exsiting tool dependency whose definition was updated in a change set pulled by a Galaxy administrator when getting updates
+ to an installed tool shed repository. The original_dependency_dict is a single tool dependency definition, an example of which is:
+ {"name": "bwa",
+ "readme": "\\nCompiling BWA requires zlib and libpthread to be present on your system.\\n ",
+ "type": "package",
+ "version": "0.6.2"}
+ The new_dependencies_dict is the dictionary generated by the generate_tool_dependency_metadata method.
+ """
+ new_tool_dependency = None
+ original_name = original_dependency_dict[ 'name' ]
+ original_type = original_dependency_dict[ 'type' ]
+ original_version = original_dependency_dict[ 'version' ]
+ # Locate the appropriate tool_dependency associated with the repository.
+ tool_dependency = None
+ for tool_dependency in repository.tool_dependencies:
+ if tool_dependency.name == original_name and tool_dependency.type == original_type and tool_dependency.version == original_version:
+ break
+ if tool_dependency and tool_dependency.can_update:
+ dependency_install_dir = tool_dependency.installation_directory( app )
+ removed_from_disk, error_message = remove_tool_dependency_installation_directory( dependency_install_dir )
+ if removed_from_disk:
+ sa_session = app.model.context.current
+ new_dependency_name = None
+ new_dependency_type = None
+ new_dependency_version = None
+ for new_dependency_key, new_dependency_val_dict in new_dependencies_dict.items():
+ # Match on name only, hopefully this will be enough!
+ if original_name == new_dependency_val_dict[ 'name' ]:
+ new_dependency_name = new_dependency_val_dict[ 'name' ]
+ new_dependency_type = new_dependency_val_dict[ 'type' ]
+ new_dependency_version = new_dependency_val_dict[ 'version' ]
+ break
+ if new_dependency_name and new_dependency_type and new_dependency_version:
+ # Update all attributes of the tool_dependency record in the database.
+ log.debug( "Updating tool dependency '%s' with type '%s' and version '%s' to have new type '%s' and version '%s'." % \
+ ( str( tool_dependency.name ),
+ str( tool_dependency.type ),
+ str( tool_dependency.version ),
+ str( new_dependency_type ),
+ str( new_dependency_version ) ) )
+ tool_dependency.type = new_dependency_type
+ tool_dependency.version = new_dependency_version
+ tool_dependency.status = app.model.ToolDependency.installation_status.UNINSTALLED
+ tool_dependency.error_message = None
+ sa_session.add( tool_dependency )
+ sa_session.flush()
+ new_tool_dependency = tool_dependency
+ else:
+ # We have no new tool dependency definition based on a matching dependency name, so remove the existing tool dependency record
+ # from the database.
+ log.debug( "Deleting tool dependency with name '%s', type '%s' and version '%s' from the database since it is no longer defined." % \
+ ( str( tool_dependency.name ), str( tool_dependency.type ), str( tool_dependency.version ) ) )
+ sa_session.delete( tool_dependency )
+ sa_session.flush()
+ return new_tool_dependency
def update_repository( repo, ctx_rev=None ):
"""
Update the cloned repository to changeset_revision. It is critical that the installed repository is updated to the desired
diff -r de2c99ce5f749582c3ce3bfb02422588c70b1a06 -r 844e566f36acc3d94856a55c0d4d4dcf291f8b81 lib/galaxy/webapps/community/controllers/common.py
--- a/lib/galaxy/webapps/community/controllers/common.py
+++ b/lib/galaxy/webapps/community/controllers/common.py
@@ -753,6 +753,7 @@
relative_install_dir=repo_dir,
repository_files_dir=work_dir,
resetting_all_metadata_on_repository=True,
+ updating_installed_repository=False,
webapp='community' )
if current_metadata_dict:
if not metadata_changeset_revision and not metadata_dict:
@@ -828,6 +829,7 @@
relative_install_dir=repo_dir,
repository_files_dir=None,
resetting_all_metadata_on_repository=False,
+ updating_installed_repository=False,
webapp='community' )
if metadata_dict:
downloadable = is_downloadable( metadata_dict )
diff -r de2c99ce5f749582c3ce3bfb02422588c70b1a06 -r 844e566f36acc3d94856a55c0d4d4dcf291f8b81 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -731,6 +731,7 @@
relative_install_dir=relative_install_dir,
repository_files_dir=None,
resetting_all_metadata_on_repository=False,
+ updating_installed_repository=False,
webapp='galaxy' )
tool_shed_repository.metadata = metadata_dict
trans.sa_session.add( tool_shed_repository )
@@ -1447,6 +1448,7 @@
relative_install_dir=relative_install_dir,
repository_files_dir=None,
resetting_all_metadata_on_repository=False,
+ updating_installed_repository=False,
webapp='galaxy' )
repository.metadata = metadata_dict
trans.sa_session.add( repository )
@@ -1566,8 +1568,7 @@
# Filter tool dependencies to only those that are installed.
tool_dependencies_for_uninstallation = []
for tool_dependency in tool_dependencies:
- if tool_dependency.status in [ trans.model.ToolDependency.installation_status.INSTALLED,
- trans.model.ToolDependency.installation_status.ERROR ]:
+ if tool_dependency.can_uninstall:
tool_dependencies_for_uninstallation.append( tool_dependency )
for tool_dependency in tool_dependencies_for_uninstallation:
uninstalled, error_message = remove_tool_dependency( trans, tool_dependency )
@@ -1616,14 +1617,16 @@
repository_clone_url = os.path.join( tool_shed_url, 'repos', owner, name )
pull_repository( repo, repository_clone_url, latest_ctx_rev )
update_repository( repo, latest_ctx_rev )
+ tool_shed = clean_tool_shed_url( tool_shed_url )
# Update the repository metadata.
- tool_shed = clean_tool_shed_url( tool_shed_url )
metadata_dict, invalid_file_tups = generate_metadata_for_changeset_revision( app=trans.app,
repository=repository,
repository_clone_url=repository_clone_url,
relative_install_dir=relative_install_dir,
repository_files_dir=None,
- resetting_all_metadata_on_repository=False )
+ resetting_all_metadata_on_repository=False,
+ updating_installed_repository=True,
+ webapp='galaxy' )
repository.metadata = metadata_dict
# Update the repository changeset_revision in the database.
repository.changeset_revision = latest_changeset_revision
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0