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
March 2014
- 1 participants
- 170 discussions
commit/galaxy-central: guerler: Charts: Add processing queue
by commits-noreply@bitbucket.org 28 Mar '14
by commits-noreply@bitbucket.org 28 Mar '14
28 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b1110a8e67c3/
Changeset: b1110a8e67c3
User: guerler
Date: 2014-03-28 19:38:36
Summary: Charts: Add processing queue
Affected #: 20 files
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,7 +1,9 @@
// dependencies
-define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage',
+define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils',
+ 'plugin/library/jobs', 'plugin/library/datasets', 'plugin/library/storage',
'plugin/views/viewer', 'plugin/views/editor',
- 'plugin/models/config', 'plugin/models/chart', 'plugin/charts/types'],
+ 'plugin/models/config', 'plugin/models/chart',
+ 'plugin/charts/types'],
function( Modal, Portlet, Ui, Utils, Jobs, Datasets, Storage,
ViewerView, EditorView,
Config, Chart, Types
@@ -14,7 +16,7 @@
initialize: function(options)
{
// deactivate all debugs outputs
- window.console.debug = function() {};
+ //window.console.debug = function() {};
// link options
this.options = options;
@@ -39,7 +41,7 @@
this.jobs = new Jobs(this);
this.datasets = new Datasets(this);
this.storage = new Storage(this);
-
+
//
// views
//
@@ -59,7 +61,10 @@
this.go('viewer');
// draw chart
- this.chart.trigger('redraw');
+ var self = this;
+ this.chart.deferred.execute(function() {
+ self.chart.trigger('redraw');
+ });
}
},
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/build-app.js
--- a/config/plugins/visualizations/charts/static/build-app.js
+++ b/config/plugins/visualizations/charts/static/build-app.js
@@ -3,4 +3,4 @@
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore may be freely distributed under the MIT license.
-(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,t,r){n("GET",e,{},t,r)}function n(e,t,n,r,i){if(e=="GET"||e=="DELETE")t.indexOf("?")==-1?t+="?":t+="&",t+=$.param(n);var s=new XMLHttpRequest;s.open(e,t,!0),s.setRequestHeader("Accept","application/json"),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-Type","application/json"),s.onloadend=function(){var e=s.status;try{response=jQuery.parseJSON(s.responseText)}catch(t){response=s.responseText}e==200?r&&r(response):i&&i(response)},e=="GET"||e=="DELETE"?s.send():s.send(JSON.stringify(n))}function r(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function i(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function s(t,n){return t?e.defaults(t,n):n}function o(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function u(){return(new Date).getTime().toString(36)}function a(e){var t=$("<p></p>");return t.append(e),t}function f(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:i,cssGetAttribute:r,get:t,merge:s,bytesToString:o,uuid:u,time:f,wrap:a,request:n}}),define("mvc/ui/ui-modal",["utils/utils"],function(e){var t=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#title-text"),this.options.height&&(this.$el.find("#body").css("height",this.options.height),this.$el.find("#content").css("overflow",this.options.overflow)),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var n=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),n.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var n=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),n.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t){this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div class="toolForm portlet-view no-highlight">';if(e.title||e.icon)t+='<div id="title" class="toolFormTitle portlet-title"><div id="operations" class="portlet-operations"/><div style="overflow: hidden;">',e.icon&&(t+='<div class="portlet-title-icon fa '+e.icon+'"> </div>'),t+='<div id="title-text" class="portlet-title-text">'+e.title+"</div>",t+="</div></div>";return t+='<div id="body" class="toolFormBody portlet-body">',e.placement=="top"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+='<div id="content" class="portlet-content"/>',e.placement=="bottom"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+="</div></div>",t}});return{View:t}}),define("plugin/library/ui-select",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",empty:"No data available",visible:!0,wait:!1},selected:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find("#select"),this.$icon=this.$el.find("#icon"),this.selected=this.options.value;var n=this;this.options.onchange&&this.$select.on("change",function(){n.value(n.$select.val())}),this._refresh(),this.options.visible||this.hide(),this.options.wait?this.wait():this.show()},value:function(e){var t=this.selected;e!==undefined&&(this.selected=e,this.$select.val(e));var n=this.selected;return n&&n!=t&&this.options.onchange&&this.options.onchange(n),n},text:function(){return this.$select.find("option:selected").text()},show:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down"),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin"),this.$select.hide()},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){this.$select.find("option").remove();for(var t in e)this.$select.append(this._templateOption(e[t]));!this.selected&&e.length>0&&this.value(e[0].value),this._refresh()},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.$select.append(this._templateOption({value:"null",label:this.options.empty})),this.disable()):(this.enable(),this.selected&&this.$select.val(this.selected))},_exists:function(e){return 0!=this.$select.find("option[value="+e+"]").length},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){var t='<div id="'+e.id+'" class="styled-select">'+'<div class="button">'+'<i id="icon"/>'+"</div>"+'<select id="select" class="select '+e.cls+" "+e.id+'">';for(key in e.data){var n=e.data[key],r="";if(n.value==e.value||n.value=="")r="selected";t+='<option value="'+n.value+'" '+r+">"+n.label+"</option>"}return t+="</select></div>",t}});return{View:t}}),define("plugin/library/ui",["utils/utils","plugin/library/ui-select"],function(e,t){var n=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.find("b").html(e)},_template:function(e){return"<label><b>"+e.title+"</b></label>"},value:function(){return options.title}}),r=Backbone.View.extend({optionsDefault:{id:null,title:"","float":"right",cls:"btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="margin-right: 5px; float: '+e.float+';" type="button" class="btn '+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),i=Backbone.View.extend({optionsDefault:{"float":"right",icon:"",tooltip:"",placement:"bottom",title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" style="font-size: 1.2em;"/> '+e.title+"</div>"}}),s=Backbone.View.extend({optionsDefault:{title:"",id:null,"float":"right",cls:"icon-btn",icon:"",tooltip:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="margin-right: 5px; float: '+e.float+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div style="margin-right: 5px; margin-left: 5px;"><i class="icon fa '+e.icon+'"/> '+'<span style="position: relative; font-size: 0.8em; font-weight: normal; top: -1px;">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),o=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)">'+e.title+"</a></div>"}}),u=Backbone.View.extend({optionsDefault:{message:"",status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>")},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.fadeIn();if(!t.persistent){var n=this;window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="alert alert-'+e.status+'" style="padding: 2px 2px 2px 10px;">'+e.message+"</div>"}}),a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),f=Backbone.View.extend({optionsDefault:{title:"Unlabeled",body:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.body&&this.$el.find(".body").append(this.options.body)},_template:function(e){return'<div id="title" class="title">'+e.title+":"+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:"",title:"",target:"",href:"",onunload:null,onclick:null,visible:!0,icon:null,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide()},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t='<div id="'+e.id+'" class="button-menu btn-group">'+'<button type="button" class="root btn btn-default dropdown-toggle" data-toggle="dropdown">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),"</button></div>",t}}),c=Backbone.View.extend({optionsDefault:{value:"",type:"text",placeholder:"",disabled:!1,visible:!0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.options.onchange&&this.$el.on("input",function(){n.options.onchange()})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="form-control">'}});return{Label:n,Button:r,Icon:i,ButtonIcon:s,Input:c,Anchor:o,Message:u,Searchbox:a,Title:f,Select:t,ButtonMenu:l}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},cleanup:function(t){var n=t.get("dataset_id_job");if(n!=""){var r=this;e.request("PUT",config.root+"api/histories/none/contents/"+n,{deleted:!0},function(){r._refreshHdas()}),t.set("dataset_id_job","")}},submit:function(t,n,r,i){var s=this,o=t.id,u=t.get("type"),a=this.app.types.get(u);data={tool_id:"rkit",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:u,columns:r,settings:n}},t.state("submit","Sending job request..."),e.request("POST",config.root+"api/tools",data,function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response.");else{s._refreshHdas();var n=e.outputs[0];t.state("queued","Job has been queued..."),t.set("dataset_id_job",n.id),s._loop(n.id,function(e){switch(e.state){case"ok":return t.state("success","Job completed successfully..."),i(e),!0;case"error":return t.state("failed","Job has failed. Please check the history for details."),!0;case"running":return t.state("running","Job is running..."),!1}})}},function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the R-kit. Please make sure it is installed. "+n)})},_loop:function(t,n){var r=this;e.request("GET",config.root+"api/jobs/"+t,{},function(e){n(e)||setTimeout(function(){r._loop(t,n)},r.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshHdas()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(t,n,r){var i=this;if(t.groups)this._fetch(t,n);else{var s=this.list[t.id];if(s){n(s);return}e.request("GET",config.root+"api/datasets/"+t.id,{},function(e){switch(e.state){case"error":r&&r(e);break;default:i.list[t.id]=e,n(e)}})}},_fetch:function(t,n){var r=t.start?t.start:0,i=Math.abs(t.end-t.start),s=this.app.config.get("query_limit");if(!i||i>s)i=s;var o="",u={},a=0;for(var f in t.groups){var l=t.groups[f];for(var c in l.columns){var h=l.columns[c];o+=h+",",u[h]=a,a++}}if(a==0){n({});return}o=o.substring(0,o.length-1);var p=t.groups.slice(0);for(var f in p)p[f].values=[];var d=this;e.request("GET",config.root+"api/datasets/"+t.id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},function(e){for(var i in e.data){var s=e.data[i];for(var o in t.groups){var a=t.groups[o],f={x:parseInt(i)+r};for(var l in a.columns){var c=a.columns[l],h=u[c],d=s[h];if(isNaN(d)||!d)d=0;f[l]=d}p[o].values.push(f)}}n(p)})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/models/chart",["plugin/models/groups","mvc/visualization/visualization-model"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model;var n=this;this.on("change:state",function(){var e=n.get("state");n.ready(e)&&n.trigger("ready"),console.debug(e+" : "+n.get("state_info"))})},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state_info",t),this.set("state",e)},ready:function(){return this.get("state")=="ok"||this.get("state")=="failed"||this.get("state")=="initialized"},editable:function(){return this.get("state")=="ok"||this.get("state")=="failed"},deferred:function(e){this.ready()?e():this.once("ready",function(){e()})}})}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;this.chart.set(e.attributes),this.chart.settings.set(e.settings);for(var t in e.groups)this.chart.groups.add(new n(e.groups[t]));return this.chart.state("ok","Loaded previously saved visualization..."),this.chart.set("modified",!1),!0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._create_svg();var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("change:state",function(){var e=r.$el.find("#info"),t=e.find("#icon");t.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var n=r.chart.get("state");switch(n){case"ok":e.hide();break;case"failed":t.addClass("fa fa-warning");break;default:t.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_create_svg:function(){this.svg&&this.svg.remove(),this.$el.append($(this._template_svg())),this.svg=d3.select(this.$el.find("svg")[0])},_draw:function(e){var t=this;this._create_svg(),e.state("wait","Please wait...");var n=e.get("type"),r=this.app.types.get(n);if(!r.execute||r.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+n+"/"+n],function(n){var i=new n(t.app,{svg:t.svg});r.execute?e.get("dataset_id_job")==""?t.app.jobs.submit(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){this.app.storage.save(),i.draw(e,t._defaultRequestDictionary(e))}):i.draw(e,t._defaultRequestDictionary(e)):i.draw(e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t=this.app.types.get(e.get("type")),n="",r=0;return e.groups.each(function(e){for(var i in t.columns)n+=i+"_"+ ++r+":"+(parseInt(e.get(i))+1)+", "}),n.substring(0,n.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t=this.app.types.get(e.get("type")),n={groups:[]};t.execute?n.id=e.get("dataset_id_job"):n.id=e.get("dataset_id");var r=0;return e.groups.each(function(e){var i={};for(var s in t.columns)i[s]=e.get(s);n.groups.push({key:++r+":"+e.get("key"),columns:i})}),n},_template:function(){return'<div style="height: 100%; min-height: 50px;"><div id="info" style="position: absolute; margin-left: 10px; margin-top: 10px; margin-bottom: 50px;"><span id="icon" style="font-size: 1.2em; display: inline-block;"/><span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/></div></div>'},_template_svg:function(){return'<svg style="height: calc(100% - 80px)"/>'}})}),define("plugin/views/viewer",["utils/utils","plugin/library/ui","mvc/ui/ui-portlet","plugin/models/group","plugin/views/viewport"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,r){this.app=e,this.chart=this.app.chart,this.viewport_view=new i(e);var s=this;this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",operations:{edit_button:new t.ButtonIcon({icon:"fa-gear",tooltip:"Customize Chart",title:"Customize",onclick:function(){s._wait(s.chart,function(){s.app.go("editor")})}})}}),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var s=this;this.chart.on("change:title",function(){s._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){if(e.editable())t();else{var n=this;this.app.modal.show({title:"Please wait!",body:"Your chart is currently being processed. Please wait and try again.",buttons:{Close:function(){n.app.modal.hide()},Retry:function(){n.app.modal.hide(),setTimeout(function(){n._wait(e,t)},n.app.config.get("query_timeout"))}}})}}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},add:function(e){var t=e.id,n={$title:$(this._template_tab(e)),$content:$(this._template_tab_content(e)),removable:e.ondel?!0:!1};this.list[t]=n,this.options.onnew?this.$nav.find("#new-tab").before(n.$title):this.$nav.append(n.$title),n.$content.append(e.$el),this.$content.append(n.$content),_.size(this.list)==1&&(n.$title.addClass("active"),n.$content.addClass("active"),this.first_tab=t);if(e.ondel){var r=this,i=n.$title.find("#delete");i.tooltip({title:"Delete this tab",placement:"bottom",container:r.$el}),i.on("click",function(){return i.tooltip("destroy"),r.$el.find(".tooltip").remove(),e.ondel(),!1})}e.onclick&&n.$title.on("click",function(){e.onclick()})},del:function(e){var t=this.list[e];t.$title.remove(),t.$content.remove(),delete t,this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab)},delRemovable:function(){for(var e in this.list){var t=this.list[e];t.removable&&this.del(e)}},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&this.list[e].$title.find("a").tab("show")},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.list[e].$title.find("#text");return t&&n.html(t),n.html()},_template:function(e){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="title-'+e.id+'">'+'<a title="" href="#tab-'+e.id+'" data-toggle="tab" data-original-title="">'+'<span id="text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="tab-'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("plugin/library/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null},events:{click:"_onclick",dblclick:"_ondblclick"},first:!0,initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(t));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=$("<tr></tr>")},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t){var n=$("<td></td>");t&&n.css("width",t),n.append(e),this.row.append(n)},append:function(e){this._commit(e)},prepend:function(e){this._commit(e,!0)},remove:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},removeAll:function(){this.$tbody.html(""),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t){this.remove(e),this.row.attr("id",e),t?this.$tbody.prepend(this.row):this.$tbody.append(this.row),this.row=$("<tr></tr>"),this.row_count++,this._refresh()},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="grid"><thead></thead><tbody style="cursor: pointer;"></tbody></table><tmessage>'+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({columns:[],initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(){s.group.set("key",s.group_key.value())}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.app.types.get(n);this.table.removeAll();var s={};for(var o in i.columns){var u=this.group.get(o);u||this.group.set(o,0);var a=i.columns[o],f=new t.Select.View({id:"select_"+o,gid:o,onchange:function(e){r.group.set(this.gid,e),r.chart.set("modified",!0)},value:u,wait:!0});this.table.add(a.title,"25%"),this.table.add(f.$el),this.table.append(o),s[o]=f}this.chart.state("wait","Loading metadata..."),this.app.datasets.request({id:e},function(e){r.columns=[];var t=e.metadata_column_types;for(var n in t)(t[n]=="int"||t[n]=="float")&&r.columns.push({label:"Column: "+(parseInt(n)+1)+" ["+t[n]+"]",value:n});for(var n in s)s[n].update(r.columns),s[n].show();r.chart.state("initialized","Metadata initialized...")})},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){var r=Backbone.View.extend({initialize:function(r){this.table_title=new t.Label({title:r.title}),this.table=new e.View({content:r.content});var i=$("<div/>");i.append(n.wrap(this.table_title.$el)),i.append(n.wrap(this.table.$el)),this.setElement(i)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.removeAll();for(var n in e)this._add(n,e[n],t)},_add:function(e,n,r){var i=null,s=n.type;switch(s){case"text":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"select":i=new t.Select.View({data:n.data,onchange:function(){r.set(e,i.value())}});break;case"slider":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"separator":i=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(s!="separator"){r.get(e)||r.set(e,n.init),i.value(r.get(e));var o=$("<div/>");o.append(i.$el),o.append('<div class="toolParamHelp" style="font-size: 0.9em;">'+n.info+"</div>"),this.table.add('<span style="white-space: nowrap;">'+n.title+"</span>","25%"),this.table.add(o)}else this.table.add('<h6 style="white-space: nowrap;">'+n.title+":<h6/>"),this.table.add($("<div/>"));this.table.append(e)}});return{View:r}}),define("plugin/views/settings",["plugin/library/ui","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View({title:"Chart options:",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refreshTable()})},_refreshTable:function(){var e=this.chart.get("type");if(!e)return;var t=this.app.types.get(e);this.form.title(t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui-table","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(s,o){var u=this;this.app=s,this.chart=this.app.chart,this.options=i.merge(o,this.optionsDefault),this.portlet=new r.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new n.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){u.app.go("viewer"),u._saveChart()}}),back:new n.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){u.app.go("viewer"),u.app.storage.load()}})}}),this.table=new t.View({header:!1,onconfirm:function(e){u.chart.groups.length>0?u.app.modal.show({title:"Switching to another chart type?",body:"If you continue your settings and selections will be cleared.",buttons:{Cancel:function(){u.app.modal.hide()},Continue:function(){u.app.modal.hide(),u.table.value(e)}}}):u.table.value(e)},onchange:function(e){u.chart.groups.reset(),u.chart.settings.clear(),u.chart.set({type:e})},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"});var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),h.execute?this.table.add(h.title+" (requires processing)"):this.table.add(h.title),this.table.append(c)}this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=u._addGroupModel();u.tabs.show(e.id)}}),this.title=new n.Input({placeholder:"Chart title",onchange:function(){u.chart.set("title",u.title.value())}});var p=$("<div/>");p.append(i.wrap((new n.Label({title:"Provide a chart title:"})).$el)),p.append(i.wrap(this.title.$el)),p.append(i.wrap((new n.Label({title:"Select a chart type:"})).$el)),p.append(i.wrap(this.table.$el)),this.tabs.add({id:"main",title:"Start",$el:p}),this.settings=new a(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var u=this;this.chart.on("change:title",function(e){u._refreshTitle()}),this.chart.on("change:type",function(e){u.table.value(e.get("type"))}),this.chart.on("reset",function(e){u._resetChart()}),this.app.chart.on("redraw",function(e){u.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){u._addGroup(e)}),this.app.chart.groups.on("remove",function(e){u._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){u._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){u._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Chart data"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new o({id:i.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new u(this.app,{group:e}),r=t.chart.groups.length;this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey()},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",i.uuid()),this.chart.set("type","bardiagram"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.table.value(),title:this.title.value(),date:i.time()}),this.chart.groups.length==0&&this._addGroupModel();var e=this;this.chart.deferred(function(){e.app.storage.save(),e.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e3,query_timeout:500}})}),define("plugin/charts/_nvd3/config",[],function(){return{title:"",columns:{y:{title:"Values for y-axis"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},x_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},y_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/bardiagram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/histogram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:!0,columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_tick:{init:".3"}}})}),define("plugin/charts/horizontal/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram (horizontal)",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/line/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/linewithfocus/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/piechart/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Pie chart"})}),define("plugin/charts/scatterplot/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/stackedarea/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/types",["plugin/charts/bardiagram/config","plugin/charts/histogram/config","plugin/charts/horizontal/config","plugin/charts/line/config","plugin/charts/linewithfocus/config","plugin/charts/piechart/config","plugin/charts/scatterplot/config","plugin/charts/stackedarea/config"],function(e,t,n,r,i,s,o,u){return Backbone.Model.extend({defaults:{bardiagram:e,horizontal:n,histogram:t,line:r,linewithfocus:i,piechart:s,scatterplot:o,stackedarea:u}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","plugin/library/ui","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c){return Backbone.View.extend({initialize:function(t){window.console.debug=function(){},this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new f,this.types=new c,this.chart=new l,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.viewer_view=new u(this),this.editor_view=new a(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el),this.storage.load()?(this.go("viewer"),this.chart.trigger("redraw")):this.go("editor")},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},execute:function(e){},onunload:function(){},log:function(e,t){console.log(e+" "+t)}})});
\ No newline at end of file
+(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,t,r){n("GET",e,{},t,r)}function n(e,t,n,r,i){if(e=="GET"||e=="DELETE")t.indexOf("?")==-1?t+="?":t+="&",t+=$.param(n);var s=new XMLHttpRequest;s.open(e,t,!0),s.setRequestHeader("Accept","application/json"),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-Type","application/json"),s.onloadend=function(){var e=s.status;try{response=jQuery.parseJSON(s.responseText)}catch(t){response=s.responseText}e==200?r&&r(response):i&&i(response)},e=="GET"||e=="DELETE"?s.send():s.send(JSON.stringify(n))}function r(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function i(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function s(t,n){return t?e.defaults(t,n):n}function o(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function u(){return(new Date).getTime().toString(36)}function a(e){var t=$("<p></p>");return t.append(e),t}function f(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:i,cssGetAttribute:r,get:t,merge:s,bytesToString:o,uuid:u,time:f,wrap:a,request:n}}),define("mvc/ui/ui-modal",["utils/utils"],function(e){var t=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#title-text"),this.options.height&&(this.$el.find("#body").css("height",this.options.height),this.$el.find("#content").css("overflow",this.options.overflow)),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var n=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),n.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var n=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),n.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t){this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div class="toolForm portlet-view no-highlight">';if(e.title||e.icon)t+='<div id="title" class="toolFormTitle portlet-title"><div id="operations" class="portlet-operations"/><div style="overflow: hidden;">',e.icon&&(t+='<div class="portlet-title-icon fa '+e.icon+'"> </div>'),t+='<div id="title-text" class="portlet-title-text">'+e.title+"</div>",t+="</div></div>";return t+='<div id="body" class="toolFormBody portlet-body">',e.placement=="top"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+='<div id="content" class="portlet-content"/>',e.placement=="bottom"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+="</div></div>",t}});return{View:t}}),define("plugin/library/ui-select",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",empty:"No data available",visible:!0,wait:!1},selected:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find("#select"),this.$icon=this.$el.find("#icon"),this.selected=this.options.value;var n=this;this.options.onchange&&this.$select.on("change",function(){n.value(n.$select.val())}),this._refresh(),this.options.visible||this.hide(),this.options.wait?this.wait():this.show()},value:function(e){var t=this.selected;e!==undefined&&(this.selected=e,this.$select.val(e));var n=this.selected;return n&&n!=t&&this.options.onchange&&this.options.onchange(n),n},text:function(){return this.$select.find("option:selected").text()},show:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down"),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin"),this.$select.hide()},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){this.$select.find("option").remove();for(var t in e)this.$select.append(this._templateOption(e[t]));!this.selected&&e.length>0&&this.value(e[0].value),this._refresh()},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.$select.append(this._templateOption({value:"null",label:this.options.empty})),this.disable()):(this.enable(),this.selected&&this.$select.val(this.selected))},_exists:function(e){return 0!=this.$select.find("option[value="+e+"]").length},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){var t='<div id="'+e.id+'" class="styled-select">'+'<div class="button">'+'<i id="icon"/>'+"</div>"+'<select id="select" class="select '+e.cls+" "+e.id+'">';for(key in e.data){var n=e.data[key],r="";if(n.value==e.value||n.value=="")r="selected";t+='<option value="'+n.value+'" '+r+">"+n.label+"</option>"}return t+="</select></div>",t}});return{View:t}}),define("plugin/library/ui",["utils/utils","plugin/library/ui-select"],function(e,t){var n=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.find("b").html(e)},_template:function(e){return"<label><b>"+e.title+"</b></label>"},value:function(){return options.title}}),r=Backbone.View.extend({optionsDefault:{id:null,title:"","float":"right",cls:"btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="margin-right: 5px; float: '+e.float+';" type="button" class="btn '+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),i=Backbone.View.extend({optionsDefault:{"float":"right",icon:"",tooltip:"",placement:"bottom",title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" style="font-size: 1.2em;"/> '+e.title+"</div>"}}),s=Backbone.View.extend({optionsDefault:{title:"",id:null,"float":"right",cls:"icon-btn",icon:"",tooltip:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="margin-right: 5px; float: '+e.float+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div style="margin-right: 5px; margin-left: 5px;"><i class="icon fa '+e.icon+'"/> '+'<span style="position: relative; font-size: 0.8em; font-weight: normal; top: -1px;">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),o=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)">'+e.title+"</a></div>"}}),u=Backbone.View.extend({optionsDefault:{message:"",status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>")},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.fadeIn();if(!t.persistent){var n=this;window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="alert alert-'+e.status+'" style="padding: 2px 2px 2px 10px;">'+e.message+"</div>"}}),a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),f=Backbone.View.extend({optionsDefault:{title:"Unlabeled",body:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.body&&this.$el.find(".body").append(this.options.body)},_template:function(e){return'<div id="title" class="title">'+e.title+":"+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:"",title:"",target:"",href:"",onunload:null,onclick:null,visible:!0,icon:null,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide()},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t='<div id="'+e.id+'" class="button-menu btn-group">'+'<button type="button" class="root btn btn-default dropdown-toggle" data-toggle="dropdown">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),"</button></div>",t}}),c=Backbone.View.extend({optionsDefault:{value:"",type:"text",placeholder:"",disabled:!1,visible:!0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.options.onchange&&this.$el.on("input",function(){n.options.onchange()})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="form-control">'}});return{Label:n,Button:r,Icon:i,ButtonIcon:s,Input:c,Anchor:o,Message:u,Searchbox:a,Title:f,Select:t,ButtonMenu:l}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},cleanup:function(t){var n=t.get("dataset_id_job");if(n!=""){var r=this;e.request("PUT",config.root+"api/histories/none/contents/"+n,{deleted:!0},function(){r._refreshHdas()}),t.set("dataset_id_job","")}},submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=this.app.types.get(a);data={tool_id:"rkit",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:a,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request("POST",config.root+"api/tools",data,function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Job has been queued..."),t.set("dataset_id_job",n.id),o._loop(n.id,function(e){switch(e.state){case"ok":return t.state("wait","Job completed successfully..."),i(e),!0;case"error":return t.state("failed","Job has failed. Please check the history for details."),s&&s(),!0;case"running":return t.state("wait","Job is running..."),!1}})}},function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the R-kit. Please make sure it is installed. "+n),s&&s()})},_loop:function(t,n){var r=this;e.request("GET",config.root+"api/jobs/"+t,{},function(e){n(e)||setTimeout(function(){r._loop(t,n)},r.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshHdas()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(t,n,r){var i=this;if(t.groups)this._fetch(t,n);else{var s=this.list[t.id];if(s){n(s);return}e.request("GET",config.root+"api/datasets/"+t.id,{},function(e){switch(e.state){case"error":r&&r(e);break;default:i.list[t.id]=e,n(e)}})}},_fetch:function(t,n){var r=t.start?t.start:0,i=Math.abs(t.end-t.start),s=this.app.config.get("query_limit");if(!i||i>s)i=s;var o="",u={},a=0;for(var f in t.groups){var l=t.groups[f];for(var c in l.columns){var h=l.columns[c];o+=h+",",u[h]=a,a++}}if(a==0){n({});return}o=o.substring(0,o.length-1);var p=t.groups.slice(0);for(var f in p)p[f].values=[];var d=this;e.request("GET",config.root+"api/datasets/"+t.id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},function(e){for(var i in e.data){var s=e.data[i];for(var o in t.groups){var a=t.groups[o],f={x:parseInt(i)+r};for(var l in a.columns){var c=a.columns[l],h=u[c],d=s[h];if(isNaN(d)||!d)d=0;f[l]=d}p[o].values.push(f)}}n(p)})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/library/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.counter==0)for(var e in this.queue)this.queue[e](),this.queue.splice(e,1)})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh")},ready:function(){return this.counter==0?!0:!1}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/models/chart",["plugin/models/groups","plugin/library/deferred","mvc/visualization/visualization-model"],function(e,t){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(n){this.groups=new e,this.settings=new Backbone.Model,this.deferred=new t},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var t in e.groups)this.chart.groups.add(new n(e.groups[t]));return this.chart.set("modified",!1),!0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._create_svg();var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=e.find("#icon");t.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var n=r.chart.get("state");switch(n){case"ok":e.hide();break;case"failed":t.addClass("fa fa-warning");break;default:t.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_create_svg:function(){this.svg&&this.svg.remove(),this.$el.append($(this._template_svg())),this.svg=d3.select(this.$el.find("svg")[0])},_draw:function(e){var t=this;this._create_svg(),e.state("wait","Please wait...");var n=e.deferred.register(),r=e.get("type"),i=this.app.types.get(r);if(!i.execute||i.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+r+"/"+r],function(r){var s=new r(t.app,{svg:t.svg});i.execute?e.get("dataset_id_job")==""?t.app.jobs.submit(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){this.app.storage.save(),s.draw(n,e,t._defaultRequestDictionary(e))},function(){e.deferred.done(n)}):s.draw(n,e,t._defaultRequestDictionary(e)):s.draw(n,e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t=this.app.types.get(e.get("type")),n="",r=0;return e.groups.each(function(e){for(var i in t.columns)n+=i+"_"+ ++r+":"+(parseInt(e.get(i))+1)+", "}),n.substring(0,n.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t=this.app.types.get(e.get("type")),n={groups:[]};t.execute?n.id=e.get("dataset_id_job"):n.id=e.get("dataset_id");var r=0;return e.groups.each(function(e){var i={};for(var s in t.columns)i[s]=e.get(s);n.groups.push({key:++r+":"+e.get("key"),columns:i})}),n},_template:function(){return'<div style="height: 100%; min-height: 50px;"><div id="info" style="position: absolute; margin-left: 10px; margin-top: 10px; margin-bottom: 50px;"><span id="icon" style="font-size: 1.2em; display: inline-block;"/><span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/></div></div>'},_template_svg:function(){return'<svg style="height: calc(100% - 80px)"/>'}})}),define("plugin/views/viewer",["utils/utils","plugin/library/ui","mvc/ui/ui-portlet","plugin/models/group","plugin/views/viewport"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,r){this.app=e,this.chart=this.app.chart,this.viewport_view=new i(e);var s=this;this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",operations:{edit_button:new t.ButtonIcon({icon:"fa-gear",tooltip:"Customize Chart",title:"Customize",onclick:function(){s._wait(s.chart,function(){s.app.go("editor")})}})}}),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var s=this;this.chart.on("change:title",function(){s._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){if(e.deferred.ready())t();else{var n=this;this.app.modal.show({title:"Please wait!",body:"Your chart is currently being processed. Please wait and try again.",buttons:{Close:function(){n.app.modal.hide()},Retry:function(){n.app.modal.hide(),setTimeout(function(){n._wait(e,t)},n.app.config.get("query_timeout"))}}})}}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},add:function(e){var t=e.id,n={$title:$(this._template_tab(e)),$content:$(this._template_tab_content(e)),removable:e.ondel?!0:!1};this.list[t]=n,this.options.onnew?this.$nav.find("#new-tab").before(n.$title):this.$nav.append(n.$title),n.$content.append(e.$el),this.$content.append(n.$content),_.size(this.list)==1&&(n.$title.addClass("active"),n.$content.addClass("active"),this.first_tab=t);if(e.ondel){var r=this,i=n.$title.find("#delete");i.tooltip({title:"Delete this tab",placement:"bottom",container:r.$el}),i.on("click",function(){return i.tooltip("destroy"),r.$el.find(".tooltip").remove(),e.ondel(),!1})}e.onclick&&n.$title.on("click",function(){e.onclick()})},del:function(e){var t=this.list[e];t.$title.remove(),t.$content.remove(),delete t,this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab)},delRemovable:function(){for(var e in this.list){var t=this.list[e];t.removable&&this.del(e)}},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&this.list[e].$title.find("a").tab("show")},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.list[e].$title.find("#text");return t&&n.html(t),n.html()},_template:function(e){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="title-'+e.id+'">'+'<a title="" href="#tab-'+e.id+'" data-toggle="tab" data-original-title="">'+'<span id="text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="tab-'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("plugin/library/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null},events:{click:"_onclick",dblclick:"_ondblclick"},first:!0,initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(t));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=$("<tr></tr>")},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t){var n=$("<td></td>");t&&n.css("width",t),n.append(e),this.row.append(n)},append:function(e){this._commit(e)},prepend:function(e){this._commit(e,!0)},remove:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},removeAll:function(){this.$tbody.html(""),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t){this.remove(e),this.row.attr("id",e),t?this.$tbody.prepend(this.row):this.$tbody.append(this.row),this.row=$("<tr></tr>"),this.row_count++,this._refresh()},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="grid"><thead></thead><tbody style="cursor: pointer;"></tbody></table><tmessage>'+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({columns:[],initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(){s.group.set("key",s.group_key.value())}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.app.types.get(n);this.table.removeAll();var s={};for(var o in i.columns){var u=this.group.get(o);u||this.group.set(o,0);var a=i.columns[o],f=new t.Select.View({id:"select_"+o,gid:o,onchange:function(e){r.group.set(this.gid,e),r.chart.set("modified",!0)},value:u,wait:!0});this.table.add(a.title,"25%"),this.table.add(f.$el),this.table.append(o),s[o]=f}this.chart.state("wait","Loading metadata...");var l=this.chart.deferred.register();this.app.datasets.request({id:e},function(e){r.columns=[];var t=e.metadata_column_types;for(var n in t)(t[n]=="int"||t[n]=="float")&&r.columns.push({label:"Column: "+(parseInt(n)+1)+" ["+t[n]+"]",value:n});for(var n in s)s[n].update(r.columns),s[n].show();r.chart.state("wait","Metadata initialized..."),r.chart.deferred.done(l)})},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){var r=Backbone.View.extend({initialize:function(r){this.table_title=new t.Label({title:r.title}),this.table=new e.View({content:r.content});var i=$("<div/>");i.append(n.wrap(this.table_title.$el)),i.append(n.wrap(this.table.$el)),this.setElement(i)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.removeAll();for(var n in e)this._add(n,e[n],t)},_add:function(e,n,r){var i=null,s=n.type;switch(s){case"text":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"select":i=new t.Select.View({data:n.data,onchange:function(){r.set(e,i.value())}});break;case"slider":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"separator":i=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(s!="separator"){r.get(e)||r.set(e,n.init),i.value(r.get(e));var o=$("<div/>");o.append(i.$el),o.append('<div class="toolParamHelp" style="font-size: 0.9em;">'+n.info+"</div>"),this.table.add('<span style="white-space: nowrap;">'+n.title+"</span>","25%"),this.table.add(o)}else this.table.add('<h6 style="white-space: nowrap;">'+n.title+":<h6/>"),this.table.add($("<div/>"));this.table.append(e)}});return{View:r}}),define("plugin/views/settings",["plugin/library/ui","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View({title:"Chart options:",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refreshTable()})},_refreshTable:function(){var e=this.chart.get("type");if(!e)return;var t=this.app.types.get(e);this.form.title(t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui-table","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(s,o){var u=this;this.app=s,this.chart=this.app.chart,this.options=i.merge(o,this.optionsDefault),this.portlet=new r.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new n.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){u.app.go("viewer"),u._saveChart()}}),back:new n.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){u.app.go("viewer"),u.app.storage.load()}})}}),this.table=new t.View({header:!1,onconfirm:function(e){u.chart.groups.length>0?u.app.modal.show({title:"Switching to another chart type?",body:"If you continue your settings and selections will be cleared.",buttons:{Cancel:function(){u.app.modal.hide()},Continue:function(){u.app.modal.hide(),u.table.value(e)}}}):u.table.value(e)},onchange:function(e){u.chart.groups.reset(),u.chart.settings.clear(),u.chart.set({type:e})},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"});var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),h.execute?this.table.add(h.title+" (requires processing)"):this.table.add(h.title),this.table.append(c)}this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=u._addGroupModel();u.tabs.show(e.id)}}),this.title=new n.Input({placeholder:"Chart title",onchange:function(){u.chart.set("title",u.title.value())}});var p=$("<div/>");p.append(i.wrap((new n.Label({title:"Provide a chart title:"})).$el)),p.append(i.wrap(this.title.$el)),p.append(i.wrap((new n.Label({title:"Select a chart type:"})).$el)),p.append(i.wrap(this.table.$el)),this.tabs.add({id:"main",title:"Start",$el:p}),this.settings=new a(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var u=this;this.chart.on("change:title",function(e){u._refreshTitle()}),this.chart.on("change:type",function(e){u.table.value(e.get("type"))}),this.chart.on("reset",function(e){u._resetChart()}),this.app.chart.on("redraw",function(e){u.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){u._addGroup(e)}),this.app.chart.groups.on("remove",function(e){u._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){u._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){u._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Chart data"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new o({id:i.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new u(this.app,{group:e}),r=t.chart.groups.length;this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey()},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",i.uuid()),this.chart.set("type","bardiagram"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.table.value(),title:this.title.value(),date:i.time()}),this.chart.groups.length==0&&this._addGroupModel();var e=this;this.chart.deferred.execute(function(){e.app.storage.save(),e.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e3,query_timeout:500}})}),define("plugin/charts/_nvd3/config",[],function(){return{title:"",columns:{y:{title:"Values for y-axis"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},x_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},y_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/bardiagram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/histogram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:!0,columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_tick:{init:".3"}}})}),define("plugin/charts/horizontal/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram (horizontal)",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/line/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/linewithfocus/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/piechart/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Pie chart"})}),define("plugin/charts/scatterplot/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/stackedarea/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/types",["plugin/charts/bardiagram/config","plugin/charts/histogram/config","plugin/charts/horizontal/config","plugin/charts/line/config","plugin/charts/linewithfocus/config","plugin/charts/piechart/config","plugin/charts/scatterplot/config","plugin/charts/stackedarea/config"],function(e,t,n,r,i,s,o,u){return Backbone.Model.extend({defaults:{bardiagram:e,horizontal:n,histogram:t,line:r,linewithfocus:i,piechart:s,scatterplot:o,stackedarea:u}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","plugin/library/ui","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new f,this.types=new c,this.chart=new l,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.viewer_view=new u(this),this.editor_view=new a(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.chart.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},execute:function(e){},onunload:function(){},log:function(e,t){console.log(e+" "+t)}})});
\ No newline at end of file
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/_nvd3/nvd3.js
--- a/config/plugins/visualizations/charts/static/charts/_nvd3/nvd3.js
+++ b/config/plugins/visualizations/charts/static/charts/_nvd3/nvd3.js
@@ -11,7 +11,7 @@
},
// render
- draw : function(nvd3_model, chart, request_dictionary, callback)
+ draw : function(process_id, nvd3_model, chart, request_dictionary, callback)
{
// request data
var self = this;
@@ -66,6 +66,9 @@
// set chart state
chart.state('ok', 'Chart has been drawn.');
+
+ // unregister process
+ chart.deferred.done(process_id);
});
});
}
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/bardiagram/bardiagram.js
--- a/config/plugins/visualizations/charts/static/charts/bardiagram/bardiagram.js
+++ b/config/plugins/visualizations/charts/static/charts/bardiagram/bardiagram.js
@@ -11,10 +11,10 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.multiBarChart(), chart, request_dictionary);
+ nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary);
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/histogram/histogram.js
--- a/config/plugins/visualizations/charts/static/charts/histogram/histogram.js
+++ b/config/plugins/visualizations/charts/static/charts/histogram/histogram.js
@@ -11,7 +11,7 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
// configure request
var index = 0;
@@ -24,7 +24,7 @@
}
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.multiBarChart(), chart, request_dictionary);
+ nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary);
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/horizontal/horizontal.js
--- a/config/plugins/visualizations/charts/static/charts/horizontal/horizontal.js
+++ b/config/plugins/visualizations/charts/static/charts/horizontal/horizontal.js
@@ -11,10 +11,10 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.multiBarHorizontalChart(), chart, request_dictionary);
+ nvd3.draw(process_id, nv.models.multiBarHorizontalChart(), chart, request_dictionary);
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/line/line.js
--- a/config/plugins/visualizations/charts/static/charts/line/line.js
+++ b/config/plugins/visualizations/charts/static/charts/line/line.js
@@ -11,10 +11,10 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.lineChart(), chart, request_dictionary);
+ nvd3.draw(process_id, nv.models.lineChart(), chart, request_dictionary);
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/linewithfocus/linewithfocus.js
--- a/config/plugins/visualizations/charts/static/charts/linewithfocus/linewithfocus.js
+++ b/config/plugins/visualizations/charts/static/charts/linewithfocus/linewithfocus.js
@@ -11,10 +11,10 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.lineWithFocusChart(), chart, request_dictionary);
+ nvd3.draw(process_id, nv.models.lineWithFocusChart(), chart, request_dictionary);
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/piechart/piechart.js
--- a/config/plugins/visualizations/charts/static/charts/piechart/piechart.js
+++ b/config/plugins/visualizations/charts/static/charts/piechart/piechart.js
@@ -11,7 +11,7 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
// request data
var self = this;
@@ -45,6 +45,9 @@
// set chart state
chart.set('state', 'ok');
+
+ // unregister process
+ chart.deferred.done(process_id);
});
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/scatterplot/scatterplot.js
--- a/config/plugins/visualizations/charts/static/charts/scatterplot/scatterplot.js
+++ b/config/plugins/visualizations/charts/static/charts/scatterplot/scatterplot.js
@@ -11,10 +11,10 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.scatterChart(), chart, request_dictionary, function(nvd3_model) {
+ nvd3.draw(process_id, nv.models.scatterChart(), chart, request_dictionary, function(nvd3_model) {
nvd3_model.showDistX(true)
.showDistY(true)
.color(d3.scale.category10().range());
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/charts/stackedarea/stackedarea.js
--- a/config/plugins/visualizations/charts/static/charts/stackedarea/stackedarea.js
+++ b/config/plugins/visualizations/charts/static/charts/stackedarea/stackedarea.js
@@ -11,10 +11,10 @@
},
// render
- draw : function(chart, request_dictionary)
+ draw : function(process_id, chart, request_dictionary)
{
var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(nv.models.stackedAreaChart(), chart, request_dictionary, function(nvd3_model) {
+ nvd3.draw(process_id, nv.models.stackedAreaChart(), chart, request_dictionary, function(nvd3_model) {
// make plot
nvd3_model.x(function(d) { return d.x })
.y(function(d) { return d.y })
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/library/deferred.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/deferred.js
@@ -0,0 +1,85 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// deferred process handler
+return Backbone.Model.extend(
+{
+ // queue
+ queue: [],
+
+ // list of currently registered processes
+ process: {},
+
+ // process counter
+ counter: 0,
+
+ // initialize
+ initialize: function()
+ {
+ // loop through queue and check states
+ this.on('refresh', function() {
+ if (this.counter == 0) {
+ for (var index in this.queue) {
+ // execute callback
+ this.queue[index]();
+
+ // remove callback
+ this.queue.splice(index, 1);
+ }
+ }
+ });
+ },
+
+ // executes callback once all processes are unregistered
+ execute: function(callback) {
+ // add wrapper to queue
+ this.queue.push(callback);
+
+ // trigger change
+ this.trigger('refresh');
+ },
+
+ // register process
+ register: function() {
+ // create unique id
+ var id = Utils.uuid();
+
+ // add process to queue
+ this.process[id] = true;
+
+ // increase process counter
+ this.counter++;
+
+ // log
+ console.debug('Deferred:register() - Registering ' + id);
+
+ // return unique id
+ return id;
+ },
+
+ // unregister process
+ done: function(id) {
+ // delete tag
+ delete this.process[id];
+
+ // decrease process counter
+ this.counter--;
+
+ // log
+ console.debug('Deferred:done() - Unregistering ' + id);
+
+ // trigger change
+ this.trigger('refresh');
+ },
+
+ // ready
+ ready: function() {
+ if (this.counter == 0) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+});
+
+});
\ No newline at end of file
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/library/jobs.js
--- a/config/plugins/visualizations/charts/static/library/jobs.js
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -27,11 +27,10 @@
// reset id
chart.set('dataset_id_job', '');
}
-
},
// create job
- submit: function(chart, settings_string, columns_string, callback) {
+ submit: function(chart, settings_string, columns_string, success, error) {
// link this
var self = this;
@@ -57,7 +56,7 @@
}
// set chart state
- chart.state('submit', 'Sending job request...');
+ chart.state('wait', 'Sending job request...');
// post job
Utils.request('POST', config.root + 'api/tools', data,
@@ -65,6 +64,9 @@
function(response) {
if (!response.outputs || response.outputs.length == 0) {
chart.state('failed', 'Job submission failed. No response.');
+
+ // call error
+ error && error();
} else {
// update galaxy history
self._refreshHdas();
@@ -73,7 +75,7 @@
var job = response.outputs[0];
// check dataset
- chart.state('queued', 'Job has been queued...');
+ chart.state('wait', 'Job has been queued...');
// backup resulting dataset id
chart.set('dataset_id_job', job.id);
@@ -82,14 +84,28 @@
self._loop(job.id, function(job) {
switch (job.state) {
case 'ok':
- chart.state('success', 'Job completed successfully...');
- callback(job);
+ // update state
+ chart.state('wait', 'Job completed successfully...');
+
+ // execute success
+ success(job);
+
+ // stop loop
return true;
case 'error':
+ // update state
chart.state('failed', 'Job has failed. Please check the history for details.');
+
+ // call error
+ error && error();
+
+ // stop loop
return true;
case 'running':
- chart.state('running', 'Job is running...');
+ // wait
+ chart.state('wait', 'Job is running...');
+
+ // continue loop
return false;
}
});
@@ -101,7 +117,12 @@
if (response && response.message && response.message.data && response.message.data.input) {
message = response.message.data.input + '.';
}
+ // update state
chart.state('failed', 'This visualization requires the R-kit. Please make sure it is installed. ' + message);
+
+ // call error
+ error && error();
+
}
);
},
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/library/storage.js
--- a/config/plugins/visualizations/charts/static/library/storage.js
+++ b/config/plugins/visualizations/charts/static/library/storage.js
@@ -98,6 +98,9 @@
// main
this.chart.set(chart_dict.attributes);
+ // set state
+ this.chart.state('ok', 'Loading saved visualization...');
+
// get settings
this.chart.settings.set(chart_dict.settings);
@@ -106,9 +109,6 @@
this.chart.groups.add(new Group(chart_dict.groups[j]));
}
- // reset status
- this.chart.state('ok', 'Loaded previously saved visualization...');
-
// reset modified flag
this.chart.set('modified', false);
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -1,5 +1,6 @@
// dependencies
-define(['plugin/models/groups', 'mvc/visualization/visualization-model'], function(Groups) {
+define(['plugin/models/groups', 'plugin/library/deferred', 'mvc/visualization/visualization-model'],
+ function(Groups, Deferred) {
// model
@@ -22,19 +23,7 @@
initialize: function(options) {
this.groups = new Groups();
this.settings = new Backbone.Model();
-
- // link status handler
- var self = this;
- this.on('change:state', function() {
- // check status
- var state = self.get('state');
- if (self.ready(state)) {
- self.trigger('ready');
- }
-
- // log
- console.debug(state + ' : ' + self.get('state_info'));
- });
+ this.deferred = new Deferred();
},
// reset
@@ -66,29 +55,15 @@
},
state: function(value, info) {
+ // set status
+ this.set('state', value);
this.set('state_info', info);
- this.set('state', value);
- },
-
- ready: function() {
- return (this.get('state') == 'ok') ||
- (this.get('state') == 'failed') ||
- (this.get('state') == 'initialized');
- },
-
- editable: function() {
- return (this.get('state') == 'ok') ||
- (this.get('state') == 'failed');
- },
-
- deferred: function(callback) {
- if (!this.ready()) {
- this.once('ready', function() {
- callback();
- });
- } else {
- callback();
- }
+
+ // trigger set state
+ this.trigger('set:state');
+
+ // log status
+ console.debug('Chart:state() - ' + info + ' (' + value + ')');
}
});
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/views/editor.js
--- a/config/plugins/visualizations/charts/static/views/editor.js
+++ b/config/plugins/visualizations/charts/static/views/editor.js
@@ -318,7 +318,7 @@
// wait until chart is ready
var self = this;
- this.chart.deferred(function() {
+ this.chart.deferred.execute(function() {
// save
self.app.storage.save();
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/views/group.js
--- a/config/plugins/visualizations/charts/static/views/group.js
+++ b/config/plugins/visualizations/charts/static/views/group.js
@@ -116,6 +116,9 @@
// loading
this.chart.state('wait', 'Loading metadata...');
+ // register process
+ var process_id = this.chart.deferred.register();
+
// get dataset
this.app.datasets.request({id : dataset_id}, function(dataset) {
// configure columns
@@ -139,7 +142,10 @@
}
// loading
- self.chart.state('initialized', 'Metadata initialized...');
+ self.chart.state('wait', 'Metadata initialized...');
+
+ // unregister
+ self.chart.deferred.done(process_id);
});
},
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/views/viewer.js
--- a/config/plugins/visualizations/charts/static/views/viewer.js
+++ b/config/plugins/visualizations/charts/static/views/viewer.js
@@ -77,7 +77,7 @@
// wait for chart to be ready
_wait: function(chart, callback) {
// get chart
- if (chart.editable()) {
+ if (chart.deferred.ready()) {
callback();
} else {
// show modal
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/static/views/viewport.js
--- a/config/plugins/visualizations/charts/static/views/viewport.js
+++ b/config/plugins/visualizations/charts/static/views/viewport.js
@@ -30,7 +30,7 @@
});
// link status handler
- this.chart.on('change:state', function() {
+ this.chart.on('set:state', function() {
// get info element
var $info = self.$el.find('#info');
@@ -93,6 +93,9 @@
// set chart state
chart.state('wait', 'Please wait...');
+
+ // register process
+ var process_id = chart.deferred.register();
// identify chart type
var chart_type = chart.get('type');
@@ -118,20 +121,24 @@
if (chart_settings.execute) {
if (chart.get('dataset_id_job') == '') {
// submit job
- self.app.jobs.submit(chart, self._defaultSettingsString(chart), self._defaultRequestString(chart), function() {
- // save
- this.app.storage.save();
+ self.app.jobs.submit(chart, self._defaultSettingsString(chart), self._defaultRequestString(chart),
+ function() {
+ // save
+ this.app.storage.save();
- // draw
- view.draw(chart, self._defaultRequestDictionary(chart));
- });
+ // draw
+ view.draw(process_id, chart, self._defaultRequestDictionary(chart));
+ },
+ function() {
+ chart.deferred.done(process_id);
+ });
} else {
// load data into view
- view.draw(chart, self._defaultRequestDictionary(chart));
+ view.draw(process_id, chart, self._defaultRequestDictionary(chart));
}
} else {
// load data into view
- view.draw(chart, self._defaultRequestDictionary(chart));
+ view.draw(process_id, chart, self._defaultRequestDictionary(chart));
}
});
},
diff -r f55491936510cfa9efe3a9324a6762081f89825e -r b1110a8e67c3b93da294eb3068d04b9249d914a9 config/plugins/visualizations/charts/templates/charts.mako
--- a/config/plugins/visualizations/charts/templates/charts.mako
+++ b/config/plugins/visualizations/charts/templates/charts.mako
@@ -36,8 +36,7 @@
// get configuration
var config = {
- root : '${root}',
- debug : false
+ root : '${root}'
};
// link galaxy
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: martenson: libraries storage prefs: name default prefs for libraries
by commits-noreply@bitbucket.org 28 Mar '14
by commits-noreply@bitbucket.org 28 Mar '14
28 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f55491936510/
Changeset: f55491936510
User: martenson
Date: 2014-03-28 19:33:27
Summary: libraries storage prefs: name default prefs for libraries
Affected #: 4 files
diff -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 -r f55491936510cfa9efe3a9324a6762081f89825e static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -53,7 +53,6 @@
*/
var SessionStorageModel = Backbone.Model.extend({
initialize : function( initialAttrs ){
- initialAttrs = initialAttrs || {};
// create unique id if none provided
initialAttrs.id = ( !_.isString( initialAttrs.id ) )?( _.uniqueId() ):( initialAttrs.id );
this.id = initialAttrs.id;
diff -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 -r f55491936510cfa9efe3a9324a6762081f89825e static/scripts/mvc/library/library-librarylist-view.js
--- a/static/scripts/mvc/library/library-librarylist-view.js
+++ b/static/scripts/mvc/library/library-librarylist-view.js
@@ -49,7 +49,7 @@
this.rowViews = {};
- this.preferences = new LibraryPrefs();
+ this.preferences = new LibraryPrefs({id: 'global-lib-prefs'});
this.collection = new mod_library_model.Libraries();
diff -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 -r f55491936510cfa9efe3a9324a6762081f89825e 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 @@
-define([],function(){var c={logger:null,log:function(){if(this.logger){var d=this.logger.log;if(typeof this.logger.log==="object"){d=Function.prototype.bind.call(this.logger.log,this.logger)}return d.apply(this.logger,arguments)}return undefined}};var a=Backbone.Model.extend({initialize:function(e){e=e||{};e.id=(!_.isString(e.id))?(_.uniqueId()):(e.id);this.id=e.id;var d=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,d,e),{silent:true});this.on("change",function(){this.save()})},sync:function(g,e,d){if(!d.silent){e.trigger("request",e,{},d)}var f;switch(g){case"create":f=this._create(e);break;case"read":f=this._read(e);break;case"update":f=this._update(e);break;case"delete":f=this._delete(e);break}if(f!==undefined||f!==null){if(d.success){d.success()}}else{if(d.error){d.error()}}return f},_create:function(d){var e=d.toJSON(),f=sessionStorage.setItem(d.id,JSON.stringify(e));return(f===null)?(f):(e)},_read:function(d){return JSON.parse(sessionStorage.getItem(d.id))},_update:function(d){return d._create(d)},_delete:function(d){return sessionStorage.removeItem(d.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){a.prototype=_.omit(a.prototype,"url","urlRoot")}());var b={hiddenUntilActivated:function(d,f){f=f||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,f||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");this.hidden=this.isHidden();if(d){var e=this;d.on("click",function(g){e.toggle(e.HUAVOptions.showSpeed)})}},isHidden:function(){return(this.HUAVOptions.$elementShown.is(":hidden"))},toggle:function(){if(this.hidden){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this);this.trigger("hiddenUntilActivated:shown",this)}this.hidden=false}else{if(_.isFunction(this.HUAVOptions.onhide)){this.HUAVOptions.onhide.call(this);this.trigger("hiddenUntilActivated:hidden",this)}this.hidden=true}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};return{LoggableMixin:c,SessionStorageModel:a,HiddenUntilActivatedViewMixin:b}});
\ No newline at end of file
+define([],function(){var c={logger:null,log:function(){if(this.logger){var d=this.logger.log;if(typeof this.logger.log==="object"){d=Function.prototype.bind.call(this.logger.log,this.logger)}return d.apply(this.logger,arguments)}return undefined}};var a=Backbone.Model.extend({initialize:function(e){e.id=(!_.isString(e.id))?(_.uniqueId()):(e.id);this.id=e.id;var d=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,d,e),{silent:true});this.on("change",function(){this.save()})},sync:function(g,e,d){if(!d.silent){e.trigger("request",e,{},d)}var f;switch(g){case"create":f=this._create(e);break;case"read":f=this._read(e);break;case"update":f=this._update(e);break;case"delete":f=this._delete(e);break}if(f!==undefined||f!==null){if(d.success){d.success()}}else{if(d.error){d.error()}}return f},_create:function(d){var e=d.toJSON(),f=sessionStorage.setItem(d.id,JSON.stringify(e));return(f===null)?(f):(e)},_read:function(d){return JSON.parse(sessionStorage.getItem(d.id))},_update:function(d){return d._create(d)},_delete:function(d){return sessionStorage.removeItem(d.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){a.prototype=_.omit(a.prototype,"url","urlRoot")}());var b={hiddenUntilActivated:function(d,f){f=f||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,f||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");this.hidden=this.isHidden();if(d){var e=this;d.on("click",function(g){e.toggle(e.HUAVOptions.showSpeed)})}},isHidden:function(){return(this.HUAVOptions.$elementShown.is(":hidden"))},toggle:function(){if(this.hidden){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this);this.trigger("hiddenUntilActivated:shown",this)}this.hidden=false}else{if(_.isFunction(this.HUAVOptions.onhide)){this.HUAVOptions.onhide.call(this);this.trigger("hiddenUntilActivated:hidden",this)}this.hidden=true}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};return{LoggableMixin:c,SessionStorageModel:a,HiddenUntilActivatedViewMixin:b}});
\ No newline at end of file
diff -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 -r f55491936510cfa9efe3a9324a6762081f89825e static/scripts/packed/mvc/library/library-librarylist-view.js
--- a/static/scripts/packed/mvc/library/library-librarylist-view.js
+++ b/static/scripts/packed/mvc/library/library-librarylist-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","mvc/base-mvc","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-libraryrow-view"],function(c,h,e,f,d,a){var b=h.SessionStorageModel.extend({defaults:{with_deleted:false}});var g=Backbone.View.extend({el:"#libraries_element",events:{"click .edit_library_btn":"edit_button_event","click .save_library_btn":"save_library_modification","click .cancel_library_btn":"cancel_library_modification","click .delete_library_btn":"delete_library","click .undelete_library_btn":"undelete_library","click .sort-libraries-link":"sort_clicked"},modal:null,collection:null,preferences:null,rowViews:{},initialize:function(){var i=this;this.rowViews={};this.preferences=new b();this.collection=new d.Libraries();this.collection.fetch({success:function(j){i.render()},error:function(k,j){f.error("An error occured. Please try again.")}})},render:function(j){var k=this.templateLibraryList();var l=null;var i=this.preferences.get("with_deleted");var m=null;if(typeof j!=="undefined"){i=typeof j.with_deleted!=="undefined"?j.with_deleted:false;m=typeof j.models!=="undefined"?j.models:null}if(this.collection!==null&&m===null){if(i){l=this.collection.models}else{l=this.collection.where({deleted:false})}}else{if(m!==null){l=m}else{l=[]}}this.$el.html(k({length:l.length,order:this.collection.sort_order}));this.renderRows(l);$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(n){for(var m=0;m<n.length;m++){var l=n[m];var k=_.findWhere(this.rowViews,{id:l.get("id")});if(k!==undefined){this.$el.find("#library_list_body").append(k.el)}else{var j=new a.LibraryRowView(l);this.$el.find("#library_list_body").append(j.el);this.rowViews[l.get("id")]=j}}},sort_clicked:function(){if(this.collection.sort_order=="asc"){this.sortLibraries("name","desc")}else{this.sortLibraries("name","asc")}this.render()},sortLibraries:function(j,i){if(j==="name"){if(i==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(l,k){if(l.get("name").toLowerCase()>k.get("name").toLowerCase()){return 1}if(k.get("name").toLowerCase()>l.get("name").toLowerCase()){return -1}return 0}}else{if(i==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(l,k){if(l.get("name").toLowerCase()>k.get("name").toLowerCase()){return -1}if(k.get("name").toLowerCase()>l.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container table-responsive">');tmpl_array.push("<% if(length === 0) { %>");tmpl_array.push("<div>I see no libraries. Why don't you create one?</div>");tmpl_array.push("<% } else{ %>");tmpl_array.push('<table class="grid table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th style="width:30%;"><a class="sort-libraries-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(' <th style="width:22%;">description</th>');tmpl_array.push(' <th style="width:22%;">synopsis</th> ');tmpl_array.push(' <th style="width:26%;"></th> ');tmpl_array.push(" </thead>");tmpl_array.push(' <tbody id="library_list_body">');tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("<% }%>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},save_library_modification:function(l){var k=$(l.target).closest("tr");var i=this.collection.get(k.data("id"));var j=false;var n=k.find(".input_library_name").val();if(typeof n!=="undefined"&&n!==i.get("name")){if(n.length>2){i.set("name",n);j=true}else{f.warning("Library name has to be at least 3 characters long");return}}var m=k.find(".input_library_description").val();if(typeof m!=="undefined"&&m!==i.get("description")){i.set("description",m);j=true}var o=k.find(".input_library_synopsis").val();if(typeof o!=="undefined"&&o!==i.get("synopsis")){i.set("synopsis",o);j=true}if(j){i.save(null,{patch:true,success:function(p){f.success("Changes to library saved");galaxyLibraryview.toggle_library_modification(k)},error:function(q,p){f.error("An error occured during updating the library :(")}})}},edit_button_event:function(i){this.toggle_library_modification($(i.target).closest("tr"))},toggle_library_modification:function(l){var i=this.collection.get(l.data("id"));l.find(".public_lib_ico").toggle();l.find(".deleted_lib_ico").toggle();l.find(".edit_library_btn").toggle();l.find(".upload_library_btn").toggle();l.find(".permission_library_btn").toggle();l.find(".save_library_btn").toggle();l.find(".cancel_library_btn").toggle();if(i.get("deleted")){}else{l.find(".delete_library_btn").toggle()}if(l.find(".edit_library_btn").is(":hidden")){var j=i.get("name");var n='<input type="text" class="form-control input_library_name" placeholder="name">';l.children("td").eq(0).html(n);if(typeof j!==undefined){l.find(".input_library_name").val(j)}var k=i.get("description");var n='<input type="text" class="form-control input_library_description" placeholder="description">';l.children("td").eq(1).html(n);if(typeof k!==undefined){l.find(".input_library_description").val(k)}var m=i.get("synopsis");var n='<input type="text" class="form-control input_library_synopsis" placeholder="synopsis">';l.children("td").eq(2).html(n);if(typeof m!==undefined){l.find(".input_library_synopsis").val(m)}}else{l.children("td").eq(0).html(i.get("name"));l.children("td").eq(1).html(i.get("description"));l.children("td").eq(2).html(i.get("synopsis"))}},cancel_library_modification:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);j.children("td").eq(0).html(i.get("name"));j.children("td").eq(1).html(i.get("description"));j.children("td").eq(2).html(i.get("synopsis"))},undelete_library:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);i.url=i.urlRoot+i.id+"?undelete=true";i.destroy({success:function(l){l.set("deleted",false);galaxyLibraryview.collection.add(l);j.removeClass("active");f.success("Library has been undeleted")},error:function(){f.error("An error occured while undeleting the library :(")}})},delete_library:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);i.destroy({success:function(l){j.remove();l.set("deleted",true);galaxyLibraryview.collection.add(l);f.success("Library has been marked deleted")},error:function(){f.error("An error occured during deleting the library :(")}})},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(j){j.preventDefault();j.stopPropagation();var i=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){i.create_new_library_event()},Close:function(){i.modal.hide()}}})},create_new_library_event:function(){var k=this.serialize_new_library();if(this.validate_new_library(k)){var j=new d.Library();var i=this;j.save(k,{success:function(l){i.collection.add(l);i.modal.hide();i.clear_library_modal();i.render();f.success("Library created")},error:function(){f.error("An error occured :(")}})}else{f.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(i){return i.name!==""}});return{LibraryListView:g}});
\ No newline at end of file
+define(["galaxy.masthead","mvc/base-mvc","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-libraryrow-view"],function(c,h,e,f,d,a){var b=h.SessionStorageModel.extend({defaults:{with_deleted:false}});var g=Backbone.View.extend({el:"#libraries_element",events:{"click .edit_library_btn":"edit_button_event","click .save_library_btn":"save_library_modification","click .cancel_library_btn":"cancel_library_modification","click .delete_library_btn":"delete_library","click .undelete_library_btn":"undelete_library","click .sort-libraries-link":"sort_clicked"},modal:null,collection:null,preferences:null,rowViews:{},initialize:function(){var i=this;this.rowViews={};this.preferences=new b({id:"global-lib-prefs"});this.collection=new d.Libraries();this.collection.fetch({success:function(j){i.render()},error:function(k,j){f.error("An error occured. Please try again.")}})},render:function(j){var k=this.templateLibraryList();var l=null;var i=this.preferences.get("with_deleted");var m=null;if(typeof j!=="undefined"){i=typeof j.with_deleted!=="undefined"?j.with_deleted:false;m=typeof j.models!=="undefined"?j.models:null}if(this.collection!==null&&m===null){if(i){l=this.collection.models}else{l=this.collection.where({deleted:false})}}else{if(m!==null){l=m}else{l=[]}}this.$el.html(k({length:l.length,order:this.collection.sort_order}));this.renderRows(l);$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(n){for(var m=0;m<n.length;m++){var l=n[m];var k=_.findWhere(this.rowViews,{id:l.get("id")});if(k!==undefined){this.$el.find("#library_list_body").append(k.el)}else{var j=new a.LibraryRowView(l);this.$el.find("#library_list_body").append(j.el);this.rowViews[l.get("id")]=j}}},sort_clicked:function(){if(this.collection.sort_order=="asc"){this.sortLibraries("name","desc")}else{this.sortLibraries("name","asc")}this.render()},sortLibraries:function(j,i){if(j==="name"){if(i==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(l,k){if(l.get("name").toLowerCase()>k.get("name").toLowerCase()){return 1}if(k.get("name").toLowerCase()>l.get("name").toLowerCase()){return -1}return 0}}else{if(i==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(l,k){if(l.get("name").toLowerCase()>k.get("name").toLowerCase()){return -1}if(k.get("name").toLowerCase()>l.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container table-responsive">');tmpl_array.push("<% if(length === 0) { %>");tmpl_array.push("<div>I see no libraries. Why don't you create one?</div>");tmpl_array.push("<% } else{ %>");tmpl_array.push('<table class="grid table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th style="width:30%;"><a class="sort-libraries-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(' <th style="width:22%;">description</th>');tmpl_array.push(' <th style="width:22%;">synopsis</th> ');tmpl_array.push(' <th style="width:26%;"></th> ');tmpl_array.push(" </thead>");tmpl_array.push(' <tbody id="library_list_body">');tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("<% }%>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},save_library_modification:function(l){var k=$(l.target).closest("tr");var i=this.collection.get(k.data("id"));var j=false;var n=k.find(".input_library_name").val();if(typeof n!=="undefined"&&n!==i.get("name")){if(n.length>2){i.set("name",n);j=true}else{f.warning("Library name has to be at least 3 characters long");return}}var m=k.find(".input_library_description").val();if(typeof m!=="undefined"&&m!==i.get("description")){i.set("description",m);j=true}var o=k.find(".input_library_synopsis").val();if(typeof o!=="undefined"&&o!==i.get("synopsis")){i.set("synopsis",o);j=true}if(j){i.save(null,{patch:true,success:function(p){f.success("Changes to library saved");galaxyLibraryview.toggle_library_modification(k)},error:function(q,p){f.error("An error occured during updating the library :(")}})}},edit_button_event:function(i){this.toggle_library_modification($(i.target).closest("tr"))},toggle_library_modification:function(l){var i=this.collection.get(l.data("id"));l.find(".public_lib_ico").toggle();l.find(".deleted_lib_ico").toggle();l.find(".edit_library_btn").toggle();l.find(".upload_library_btn").toggle();l.find(".permission_library_btn").toggle();l.find(".save_library_btn").toggle();l.find(".cancel_library_btn").toggle();if(i.get("deleted")){}else{l.find(".delete_library_btn").toggle()}if(l.find(".edit_library_btn").is(":hidden")){var j=i.get("name");var n='<input type="text" class="form-control input_library_name" placeholder="name">';l.children("td").eq(0).html(n);if(typeof j!==undefined){l.find(".input_library_name").val(j)}var k=i.get("description");var n='<input type="text" class="form-control input_library_description" placeholder="description">';l.children("td").eq(1).html(n);if(typeof k!==undefined){l.find(".input_library_description").val(k)}var m=i.get("synopsis");var n='<input type="text" class="form-control input_library_synopsis" placeholder="synopsis">';l.children("td").eq(2).html(n);if(typeof m!==undefined){l.find(".input_library_synopsis").val(m)}}else{l.children("td").eq(0).html(i.get("name"));l.children("td").eq(1).html(i.get("description"));l.children("td").eq(2).html(i.get("synopsis"))}},cancel_library_modification:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);j.children("td").eq(0).html(i.get("name"));j.children("td").eq(1).html(i.get("description"));j.children("td").eq(2).html(i.get("synopsis"))},undelete_library:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);i.url=i.urlRoot+i.id+"?undelete=true";i.destroy({success:function(l){l.set("deleted",false);galaxyLibraryview.collection.add(l);j.removeClass("active");f.success("Library has been undeleted")},error:function(){f.error("An error occured while undeleting the library :(")}})},delete_library:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);i.destroy({success:function(l){j.remove();l.set("deleted",true);galaxyLibraryview.collection.add(l);f.success("Library has been marked deleted")},error:function(){f.error("An error occured during deleting the library :(")}})},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(j){j.preventDefault();j.stopPropagation();var i=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){i.create_new_library_event()},Close:function(){i.modal.hide()}}})},create_new_library_event:function(){var k=this.serialize_new_library();if(this.validate_new_library(k)){var j=new d.Library();var i=this;j.save(k,{success:function(l){i.collection.add(l);i.modal.hide();i.clear_library_modal();i.render();f.success("Library created")},error:function(){f.error("An error occured :(")}})}else{f.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(i){return i.name!==""}});return{LibraryListView:g}});
\ 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
commit/galaxy-central: martenson: libraries: some serious refactoring, caching of subviews; base-mvc initialAttrs default setting (empty object)
by commits-noreply@bitbucket.org 28 Mar '14
by commits-noreply@bitbucket.org 28 Mar '14
28 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/813a11e7b98a/
Changeset: 813a11e7b98a
User: martenson
Date: 2014-03-28 19:17:57
Summary: libraries: some serious refactoring, caching of subviews; base-mvc initialAttrs default setting (empty object)
Affected #: 12 files
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -36,23 +36,19 @@
var GalaxyLibrary = Backbone.View.extend({
initialize : function(){
- toolbarView = new mod_librarytoolbar_view.ToolbarView();
- galaxyLibraryview = new mod_librarylist_view.GalaxyLibraryview();
+ // toolbarView = new mod_librarytoolbar_view.ToolbarView();
+ toolbarView = null;
+ // libraryListView = new mod_librarylist_view.LibraryListView();
+ libraryListView = null;
library_router = new LibraryRouter();
-
+
folderContentView = null;
library_router.on('route:libraries', function() {
// initialize and render the toolbar first
toolbarView = new mod_librarytoolbar_view.ToolbarView();
// initialize and render libraries second
- galaxyLibraryview = new mod_librarylist_view.GalaxyLibraryview();
- });
-
- library_router.on('route:sort_libraries', function(sort_by, order) {
- // sort libraries list
- galaxyLibraryview.sortLibraries(sort_by, order);
- galaxyLibraryview.render();
+ libraryListView = new mod_librarylist_view.LibraryListView();
});
library_router.on('route:folder_content', function(id) {
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/mvc/base-mvc.js
--- a/static/scripts/mvc/base-mvc.js
+++ b/static/scripts/mvc/base-mvc.js
@@ -53,6 +53,7 @@
*/
var SessionStorageModel = Backbone.Model.extend({
initialize : function( initialAttrs ){
+ initialAttrs = initialAttrs || {};
// create unique id if none provided
initialAttrs.id = ( !_.isString( initialAttrs.id ) )?( _.uniqueId() ):( initialAttrs.id );
this.id = initialAttrs.id;
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/mvc/library/library-librarylist-view.js
--- a/static/scripts/mvc/library/library-librarylist-view.js
+++ b/static/scripts/mvc/library/library-librarylist-view.js
@@ -1,42 +1,61 @@
// dependencies
define([
- "galaxy.masthead",
+ "galaxy.masthead",
+ "mvc/base-mvc",
"utils/utils",
"libs/toastr",
- "mvc/library/library-model"],
-function(mod_masthead,
+ "mvc/library/library-model",
+ "mvc/library/library-libraryrow-view"],
+function(mod_masthead,
+ mod_baseMVC,
mod_utils,
mod_toastr,
- mod_library_model) {
+ mod_library_model,
+ mod_library_libraryrow_view) {
+
+// ============================================================================
+/** session storage for library preferences */
+var LibraryPrefs = mod_baseMVC.SessionStorageModel.extend({
+ defaults : {
+ with_deleted : false
+ }
+});
// galaxy library view
-var GalaxyLibraryview = Backbone.View.extend({
+var LibraryListView = Backbone.View.extend({
el: '#libraries_element',
events: {
- 'click .edit_library_btn' : 'edit_button_event',
- 'click .save_library_btn' : 'save_library_modification',
- 'click .cancel_library_btn' : 'cancel_library_modification',
- 'click .delete_library_btn' : 'delete_library',
- 'click .undelete_library_btn' : 'undelete_library'
+ 'click .edit_library_btn' : 'edit_button_event',
+ 'click .save_library_btn' : 'save_library_modification',
+ 'click .cancel_library_btn' : 'cancel_library_modification',
+ 'click .delete_library_btn' : 'delete_library',
+ 'click .undelete_library_btn' : 'undelete_library',
+ 'click .sort-libraries-link' : 'sort_clicked'
},
modal: null,
collection: null,
+ preferences: null,
+
+ // map of library model ids to library views = cache
+ rowViews: {},
+
// initialize
initialize : function(){
var viewContext = this;
+
+ this.rowViews = {};
+
+ this.preferences = new LibraryPrefs();
+
this.collection = new mod_library_model.Libraries();
this.collection.fetch({
success: function(libraries){
viewContext.render();
- // initialize the library tooltips
- $("#center [data-toggle]").tooltip();
- // modification of upper DOM element to show scrollbars due to the #center element inheritance
- $("#center").css('overflow','auto');
},
error: function(model, response){
mod_toastr.error('An error occured. Please try again.');
@@ -50,7 +69,7 @@
render: function (options) {
var template = this.templateLibraryList();
var libraries_to_render = null;
- var include_deleted = false;
+ var include_deleted = this.preferences.get('with_deleted');
var models = null
if (typeof options !== 'undefined'){
include_deleted = typeof options.with_deleted !== 'undefined' ? options.with_deleted : false;
@@ -69,10 +88,52 @@
libraries_to_render = [];
}
- this.$el.html(template({libraries: libraries_to_render, order: this.collection.sort_order}));
+ this.$el.html(template({length: libraries_to_render.length, order: this.collection.sort_order}));
+
+ this.renderRows(libraries_to_render);
+ // initialize the library tooltips
+ $("#center [data-toggle]").tooltip();
+ // modification of upper DOM element to show scrollbars due to the #center element inheritance
+ $("#center").css('overflow','auto');
},
- /** Sorts the underlying collection according to the parameters received through URL.
+ renderRows: function(libraries_to_render){
+ for (var i = 0; i < libraries_to_render.length; i++) {
+ var library = libraries_to_render[i];
+ var cachedView = _.findWhere(this.rowViews, {id: library.get('id')});
+ if (cachedView !== undefined){
+ this.$el.find('#library_list_body').append(cachedView.el);
+ } else {
+ var rowView = new mod_library_libraryrow_view.LibraryRowView(library);
+ this.$el.find('#library_list_body').append(rowView.el);
+ // save new rowView to cache
+ this.rowViews[library.get('id')] = rowView;
+ }
+ };
+ },
+
+ /** Handle the user toggling the deleted visibility by:
+ * (1) storing the new value in the persistent storage
+ * (2) re-rendering the list
+ * @returns {Boolean} new show_hidden setting
+ */
+ // toggleShowHidden : function( show ){
+ // show = ( show !== undefined )?( show ):( !this.storage.get( 'show_hidden' ) );
+ // this.storage.set( 'show_hidden', show );
+ // this.renderRows();
+ // return this.storage.get( 'show_hidden' );
+ // },
+
+ sort_clicked : function(){
+ if (this.collection.sort_order == 'asc'){
+ this.sortLibraries('name','desc');
+ } else {
+ this.sortLibraries('name','asc');
+ }
+ this.render();
+ },
+
+ /** Sorts the underlying collection according to the parameters received.
Currently supports only sorting by name. */
sortLibraries: function(sort_by, order){
if (sort_by === 'name'){
@@ -104,31 +165,18 @@
tmpl_array = [];
tmpl_array.push('<div class="library_container table-responsive">');
- tmpl_array.push('<% if(libraries.length === 0) { %>');
+ tmpl_array.push('<% if(length === 0) { %>');
tmpl_array.push("<div>I see no libraries. Why don't you create one?</div>");
tmpl_array.push('<% } else{ %>');
tmpl_array.push('<table class="grid table table-condensed">');
tmpl_array.push(' <thead>');
- tmpl_array.push(' <th style="width:30%;"><a title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');
+ tmpl_array.push(' <th style="width:30%;"><a class="sort-libraries-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');
tmpl_array.push(' <th style="width:22%;">description</th>');
tmpl_array.push(' <th style="width:22%;">synopsis</th> ');
tmpl_array.push(' <th style="width:26%;"></th> ');
tmpl_array.push(' </thead>');
- tmpl_array.push(' <tbody>');
- tmpl_array.push(' <% _.each(libraries, function(library) { %>');
- tmpl_array.push(' <tr class="<% if(library.get("deleted") === true){print("active");}%>" data-id="<%- library.get("id") %>">');
- tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Item is public" class="fa fa-globe fa-lg"></span><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');
- tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');
- tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');
- tmpl_array.push(' <td class="right-center">');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button"><span class="fa fa-pencil"></span></button>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save changes" class="primary-button btn-xs save_library_btn" type="button" style="display:none;"><span class="fa fa-floppy-o"> Save</span></button>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Discard changes" class="primary-button btn-xs cancel_library_btn" type="button" style="display:none;"><span class="fa fa-times"> Cancel</span></button>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Delete library (can be undeleted later)" class="primary-button btn-xs delete_library_btn" type="button" style="display:none;"><span class="fa fa-trash-o"> Delete</span></button>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Undelete library" class="primary-button btn-xs undelete_library_btn" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button>');
- tmpl_array.push(' </td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <% }); %>');
+ tmpl_array.push(' <tbody id="library_list_body">');
+ // library item views will attach here
tmpl_array.push(' </tbody>');
tmpl_array.push('</table>');
tmpl_array.push('<% }%>');
@@ -202,11 +250,15 @@
toggle_library_modification: function($library_row){
var library = this.collection.get($library_row.data('id'));
+ $library_row.find('.public_lib_ico').toggle();
+ $library_row.find('.deleted_lib_ico').toggle();
$library_row.find('.edit_library_btn').toggle();
+ $library_row.find('.upload_library_btn').toggle();
+ $library_row.find('.permission_library_btn').toggle();
$library_row.find('.save_library_btn').toggle();
$library_row.find('.cancel_library_btn').toggle();
if (library.get('deleted')){
- $library_row.find('.undelete_library_btn').toggle();
+ // $library_row.find('.undelete_library_btn').toggle();
} else {
$library_row.find('.delete_library_btn').toggle();
}
@@ -369,7 +421,7 @@
// return
return {
- GalaxyLibraryview: GalaxyLibraryview
+ LibraryListView: LibraryListView
};
});
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/mvc/library/library-libraryrow-view.js
--- /dev/null
+++ b/static/scripts/mvc/library/library-libraryrow-view.js
@@ -0,0 +1,65 @@
+// dependencies
+define([
+ "galaxy.masthead",
+ "utils/utils",
+ "libs/toastr",
+ "mvc/library/library-model"],
+function(mod_masthead,
+ mod_utils,
+ mod_toastr,
+ mod_library_model) {
+
+// galaxy library row view
+var LibraryRowView = Backbone.View.extend({
+
+ initialize : function(library){
+ this.render(library);
+ },
+
+ render: function(library){
+ var tmpl = this.templateRow();
+ this.setElement(tmpl({library:library}));
+ this.set_up_visual_features(library);
+ },
+
+ set_up_visual_features: function(library){
+ if (library.get('deleted') === true){
+ this.$el.addClass('active');
+ }
+ this.$el.show();
+ },
+
+ templateRow: function() {
+ tmpl_array = [];
+
+ tmpl_array.push(' <tr style="display:none;" data-id="<%- library.get("id") %>">');
+ tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');
+ tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');
+ tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');
+ tmpl_array.push(' <td class="right-center">');
+ tmpl_array.push(' <% if(library.get("deleted") === true) { %>');
+ tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg deleted_lib_ico"></span>');
+ tmpl_array.push(' <% } else if(library.get("public") === true) { %>');
+ tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Public" style="color:grey;" class="fa fa-globe fa-lg public_lib_ico"></span>');
+ tmpl_array.push(' <% }%>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Upload to library" class="primary-button btn-xs upload_library_btn" type="button"><span class="fa fa-upload"></span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button"><span class="fa fa-pencil"></span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify permissions" class="primary-button btn-xs permission_library_btn" type="button"><span class="fa fa-group"></span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save changes" class="primary-button btn-xs save_library_btn" type="button" style="display:none;"><span class="fa fa-floppy-o"> Save</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Discard changes" class="primary-button btn-xs cancel_library_btn" type="button" style="display:none;"><span class="fa fa-times"> Cancel</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Delete library (can be undeleted later)" class="primary-button btn-xs delete_library_btn" type="button" style="display:none;"><span class="fa fa-trash-o"> Delete</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Undelete library" class="primary-button btn-xs undelete_library_btn" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button>');
+ tmpl_array.push(' </td>');
+ tmpl_array.push(' </tr>');
+
+ return _.template(tmpl_array.join(''));
+ }
+
+});
+
+ // return
+return {
+ LibraryRowView: LibraryRowView
+};
+
+});
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/mvc/library/library-librarytoolbar-view.js
--- a/static/scripts/mvc/library/library-librarytoolbar-view.js
+++ b/static/scripts/mvc/library/library-librarytoolbar-view.js
@@ -23,15 +23,17 @@
delegate_modal: function(event){
// probably should refactor to have this functionality in this view, not in the library view
- galaxyLibraryview.show_library_modal(event);
+ libraryListView.show_library_modal(event);
},
// include or exclude deleted libraries from the view
check_include_deleted: function(event){
if (event.target.checked){
- galaxyLibraryview.render( {'with_deleted': true} );
+ libraryListView.preferences.set({'with_deleted': true});
+ libraryListView.render();
} else{
- galaxyLibraryview.render({'with_deleted': false});
+ libraryListView.preferences.set({'with_deleted': false});
+ libraryListView.render();
}
},
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/mvc/library/library-model.js
--- a/static/scripts/mvc/library/library-model.js
+++ b/static/scripts/mvc/library/library-model.js
@@ -3,7 +3,19 @@
// LIBRARY
var Library = Backbone.Model.extend({
- urlRoot: '/api/libraries/'
+ urlRoot: '/api/libraries/',
+
+ /** based on show_deleted
+ * would this lib show in the list of lib's?
+ * @param {Boolean} show_deleted are we showing deleted libraries?
+ */
+ isVisible : function(show_deleted){
+ var isVisible = true;
+ if( (!show_delete) && (this.get('deleted')) ){
+ isVisible = false;
+ }
+ return isVisible;
+ }
});
// FOLDER AS MODEL
@@ -19,8 +31,25 @@
sort_key: 'name', // default
- sort_order: null // default
+ sort_order: null, // default
+ initialize : function(options){
+ options = options || {};
+ },
+
+ /** Get every 'shown' library in this collection based on deleted filter
+ * @param {Boolean} show_deleted are we showing deleted libraries?
+ * @returns array of library models
+ */
+ getVisible : function(show_deleted, filters){
+ filters = filters || [];
+ // always filter by show deleted first
+ var filteredLibraries = new Libraries( this.filter( function( item ){
+ return item.isVisible(show_deleted);
+ }));
+
+ return filteredLibraries;
+ }
});
// ITEM
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/packed/galaxy.library.js
--- a/static/scripts/packed/galaxy.library.js
+++ b/static/scripts/packed/galaxy.library.js
@@ -1,1 +1,1 @@
-var library_router=null;define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view"],function(e,c,g,h,a,f,d){var i=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var b=Backbone.View.extend({initialize:function(){toolbarView=new d.ToolbarView();galaxyLibraryview=new f.GalaxyLibraryview();library_router=new i();folderContentView=null;library_router.on("route:libraries",function(){toolbarView=new d.ToolbarView();galaxyLibraryview=new f.GalaxyLibraryview()});library_router.on("route:sort_libraries",function(k,j){galaxyLibraryview.sortLibraries(k,j);galaxyLibraryview.render()});library_router.on("route:folder_content",function(j){if(!folderContentView){folderContentView=new a.FolderContentView()}folderContentView.render({id:j})});library_router.on("route:download",function(j,k){if($("#center").find(":checked").length===0){library_router.navigate("folders/"+j,{trigger:true,replace:true})}else{folderContentView.download(j,k);library_router.navigate("folders/"+j,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
+var library_router=null;define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view"],function(e,c,g,h,a,f,d){var i=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var b=Backbone.View.extend({initialize:function(){toolbarView=null;libraryListView=null;library_router=new i();folderContentView=null;library_router.on("route:libraries",function(){toolbarView=new d.ToolbarView();libraryListView=new f.LibraryListView()});library_router.on("route:folder_content",function(j){if(!folderContentView){folderContentView=new a.FolderContentView()}folderContentView.render({id:j})});library_router.on("route:download",function(j,k){if($("#center").find(":checked").length===0){library_router.navigate("folders/"+j,{trigger:true,replace:true})}else{folderContentView.download(j,k);library_router.navigate("folders/"+j,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 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 @@
-define([],function(){var c={logger:null,log:function(){if(this.logger){var d=this.logger.log;if(typeof this.logger.log==="object"){d=Function.prototype.bind.call(this.logger.log,this.logger)}return d.apply(this.logger,arguments)}return undefined}};var a=Backbone.Model.extend({initialize:function(e){e.id=(!_.isString(e.id))?(_.uniqueId()):(e.id);this.id=e.id;var d=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,d,e),{silent:true});this.on("change",function(){this.save()})},sync:function(g,e,d){if(!d.silent){e.trigger("request",e,{},d)}var f;switch(g){case"create":f=this._create(e);break;case"read":f=this._read(e);break;case"update":f=this._update(e);break;case"delete":f=this._delete(e);break}if(f!==undefined||f!==null){if(d.success){d.success()}}else{if(d.error){d.error()}}return f},_create:function(d){var e=d.toJSON(),f=sessionStorage.setItem(d.id,JSON.stringify(e));return(f===null)?(f):(e)},_read:function(d){return JSON.parse(sessionStorage.getItem(d.id))},_update:function(d){return d._create(d)},_delete:function(d){return sessionStorage.removeItem(d.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){a.prototype=_.omit(a.prototype,"url","urlRoot")}());var b={hiddenUntilActivated:function(d,f){f=f||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,f||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");this.hidden=this.isHidden();if(d){var e=this;d.on("click",function(g){e.toggle(e.HUAVOptions.showSpeed)})}},isHidden:function(){return(this.HUAVOptions.$elementShown.is(":hidden"))},toggle:function(){if(this.hidden){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this);this.trigger("hiddenUntilActivated:shown",this)}this.hidden=false}else{if(_.isFunction(this.HUAVOptions.onhide)){this.HUAVOptions.onhide.call(this);this.trigger("hiddenUntilActivated:hidden",this)}this.hidden=true}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};return{LoggableMixin:c,SessionStorageModel:a,HiddenUntilActivatedViewMixin:b}});
\ No newline at end of file
+define([],function(){var c={logger:null,log:function(){if(this.logger){var d=this.logger.log;if(typeof this.logger.log==="object"){d=Function.prototype.bind.call(this.logger.log,this.logger)}return d.apply(this.logger,arguments)}return undefined}};var a=Backbone.Model.extend({initialize:function(e){e=e||{};e.id=(!_.isString(e.id))?(_.uniqueId()):(e.id);this.id=e.id;var d=(!this.isNew())?(this._read(this)):({});this.clear({silent:true});this.save(_.extend({},this.defaults,d,e),{silent:true});this.on("change",function(){this.save()})},sync:function(g,e,d){if(!d.silent){e.trigger("request",e,{},d)}var f;switch(g){case"create":f=this._create(e);break;case"read":f=this._read(e);break;case"update":f=this._update(e);break;case"delete":f=this._delete(e);break}if(f!==undefined||f!==null){if(d.success){d.success()}}else{if(d.error){d.error()}}return f},_create:function(d){var e=d.toJSON(),f=sessionStorage.setItem(d.id,JSON.stringify(e));return(f===null)?(f):(e)},_read:function(d){return JSON.parse(sessionStorage.getItem(d.id))},_update:function(d){return d._create(d)},_delete:function(d){return sessionStorage.removeItem(d.id)},isNew:function(){return !sessionStorage.hasOwnProperty(this.id)},_log:function(){return JSON.stringify(this.toJSON(),null," ")},toString:function(){return"SessionStorageModel("+this.id+")"}});(function(){a.prototype=_.omit(a.prototype,"url","urlRoot")}());var b={hiddenUntilActivated:function(d,f){f=f||{};this.HUAVOptions={$elementShown:this.$el,showFn:jQuery.prototype.toggle,showSpeed:"fast"};_.extend(this.HUAVOptions,f||{});this.HUAVOptions.hasBeenShown=this.HUAVOptions.$elementShown.is(":visible");this.hidden=this.isHidden();if(d){var e=this;d.on("click",function(g){e.toggle(e.HUAVOptions.showSpeed)})}},isHidden:function(){return(this.HUAVOptions.$elementShown.is(":hidden"))},toggle:function(){if(this.hidden){if(!this.HUAVOptions.hasBeenShown){if(_.isFunction(this.HUAVOptions.onshowFirstTime)){this.HUAVOptions.hasBeenShown=true;this.HUAVOptions.onshowFirstTime.call(this)}}if(_.isFunction(this.HUAVOptions.onshow)){this.HUAVOptions.onshow.call(this);this.trigger("hiddenUntilActivated:shown",this)}this.hidden=false}else{if(_.isFunction(this.HUAVOptions.onhide)){this.HUAVOptions.onhide.call(this);this.trigger("hiddenUntilActivated:hidden",this)}this.hidden=true}return this.HUAVOptions.showFn.apply(this.HUAVOptions.$elementShown,arguments)}};return{LoggableMixin:c,SessionStorageModel:a,HiddenUntilActivatedViewMixin:b}});
\ No newline at end of file
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/packed/mvc/library/library-librarylist-view.js
--- a/static/scripts/packed/mvc/library/library-librarylist-view.js
+++ b/static/scripts/packed/mvc/library/library-librarylist-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(a,c,e,b){var d=Backbone.View.extend({el:"#libraries_element",events:{"click .edit_library_btn":"edit_button_event","click .save_library_btn":"save_library_modification","click .cancel_library_btn":"cancel_library_modification","click .delete_library_btn":"delete_library","click .undelete_library_btn":"undelete_library"},modal:null,collection:null,initialize:function(){var f=this;this.collection=new b.Libraries();this.collection.fetch({success:function(g){f.render();$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},error:function(h,g){e.error("An error occured. Please try again.")}})},render:function(g){var h=this.templateLibraryList();var i=null;var f=false;var j=null;if(typeof g!=="undefined"){f=typeof g.with_deleted!=="undefined"?g.with_deleted:false;j=typeof g.models!=="undefined"?g.models:null}if(this.collection!==null&&j===null){if(f){i=this.collection.models}else{i=this.collection.where({deleted:false})}}else{if(j!==null){i=j}else{i=[]}}this.$el.html(h({libraries:i,order:this.collection.sort_order}))},sortLibraries:function(g,f){if(g==="name"){if(f==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(i,h){if(i.get("name").toLowerCase()>h.get("name").toLowerCase()){return 1}if(h.get("name").toLowerCase()>i.get("name").toLowerCase()){return -1}return 0}}else{if(f==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(i,h){if(i.get("name").toLowerCase()>h.get("name").toLowerCase()){return -1}if(h.get("name").toLowerCase()>i.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container table-responsive">');tmpl_array.push("<% if(libraries.length === 0) { %>");tmpl_array.push("<div>I see no libraries. Why don't you create one?</div>");tmpl_array.push("<% } else{ %>");tmpl_array.push('<table class="grid table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th style="width:30%;"><a title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(' <th style="width:22%;">description</th>');tmpl_array.push(' <th style="width:22%;">synopsis</th> ');tmpl_array.push(' <th style="width:26%;"></th> ');tmpl_array.push(" </thead>");tmpl_array.push(" <tbody>");tmpl_array.push(" <% _.each(libraries, function(library) { %>");tmpl_array.push(' <tr class="<% if(library.get("deleted") === true){print("active");}%>" data-id="<%- library.get("id") %>">');tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Item is public" class="fa fa-globe fa-lg"></span><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(' <td class="right-center">');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button"><span class="fa fa-pencil"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save changes" class="primary-button btn-xs save_library_btn" type="button" style="display:none;"><span class="fa fa-floppy-o"> Save</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Discard changes" class="primary-button btn-xs cancel_library_btn" type="button" style="display:none;"><span class="fa fa-times"> Cancel</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Delete library (can be undeleted later)" class="primary-button btn-xs delete_library_btn" type="button" style="display:none;"><span class="fa fa-trash-o"> Delete</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Undelete library" class="primary-button btn-xs undelete_library_btn" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button>');tmpl_array.push(" </td>");tmpl_array.push(" </tr>");tmpl_array.push(" <% }); %>");tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("<% }%>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},save_library_modification:function(i){var h=$(i.target).closest("tr");var f=this.collection.get(h.data("id"));var g=false;var k=h.find(".input_library_name").val();if(typeof k!=="undefined"&&k!==f.get("name")){if(k.length>2){f.set("name",k);g=true}else{e.warning("Library name has to be at least 3 characters long");return}}var j=h.find(".input_library_description").val();if(typeof j!=="undefined"&&j!==f.get("description")){f.set("description",j);g=true}var l=h.find(".input_library_synopsis").val();if(typeof l!=="undefined"&&l!==f.get("synopsis")){f.set("synopsis",l);g=true}if(g){f.save(null,{patch:true,success:function(m){e.success("Changes to library saved");galaxyLibraryview.toggle_library_modification(h)},error:function(n,m){e.error("An error occured during updating the library :(")}})}},edit_button_event:function(f){this.toggle_library_modification($(f.target).closest("tr"))},toggle_library_modification:function(i){var f=this.collection.get(i.data("id"));i.find(".edit_library_btn").toggle();i.find(".save_library_btn").toggle();i.find(".cancel_library_btn").toggle();if(f.get("deleted")){i.find(".undelete_library_btn").toggle()}else{i.find(".delete_library_btn").toggle()}if(i.find(".edit_library_btn").is(":hidden")){var g=f.get("name");var k='<input type="text" class="form-control input_library_name" placeholder="name">';i.children("td").eq(0).html(k);if(typeof g!==undefined){i.find(".input_library_name").val(g)}var h=f.get("description");var k='<input type="text" class="form-control input_library_description" placeholder="description">';i.children("td").eq(1).html(k);if(typeof h!==undefined){i.find(".input_library_description").val(h)}var j=f.get("synopsis");var k='<input type="text" class="form-control input_library_synopsis" placeholder="synopsis">';i.children("td").eq(2).html(k);if(typeof j!==undefined){i.find(".input_library_synopsis").val(j)}}else{i.children("td").eq(0).html(f.get("name"));i.children("td").eq(1).html(f.get("description"));i.children("td").eq(2).html(f.get("synopsis"))}},cancel_library_modification:function(h){var g=$(h.target).closest("tr");var f=this.collection.get(g.data("id"));this.toggle_library_modification(g);g.children("td").eq(0).html(f.get("name"));g.children("td").eq(1).html(f.get("description"));g.children("td").eq(2).html(f.get("synopsis"))},undelete_library:function(h){var g=$(h.target).closest("tr");var f=this.collection.get(g.data("id"));this.toggle_library_modification(g);f.url=f.urlRoot+f.id+"?undelete=true";f.destroy({success:function(i){i.set("deleted",false);galaxyLibraryview.collection.add(i);g.removeClass("active");e.success("Library has been undeleted")},error:function(){e.error("An error occured while undeleting the library :(")}})},delete_library:function(h){var g=$(h.target).closest("tr");var f=this.collection.get(g.data("id"));this.toggle_library_modification(g);f.destroy({success:function(i){g.remove();i.set("deleted",true);galaxyLibraryview.collection.add(i);e.success("Library has been marked deleted")},error:function(){e.error("An error occured during deleting the library :(")}})},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(g){g.preventDefault();g.stopPropagation();var f=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){f.create_new_library_event()},Close:function(){f.modal.hide()}}})},create_new_library_event:function(){var h=this.serialize_new_library();if(this.validate_new_library(h)){var g=new b.Library();var f=this;g.save(h,{success:function(i){f.collection.add(i);f.modal.hide();f.clear_library_modal();f.render();e.success("Library created")},error:function(){e.error("An error occured :(")}})}else{e.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(f){return f.name!==""}});return{GalaxyLibraryview:d}});
\ No newline at end of file
+define(["galaxy.masthead","mvc/base-mvc","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-libraryrow-view"],function(c,h,e,f,d,a){var b=h.SessionStorageModel.extend({defaults:{with_deleted:false}});var g=Backbone.View.extend({el:"#libraries_element",events:{"click .edit_library_btn":"edit_button_event","click .save_library_btn":"save_library_modification","click .cancel_library_btn":"cancel_library_modification","click .delete_library_btn":"delete_library","click .undelete_library_btn":"undelete_library","click .sort-libraries-link":"sort_clicked"},modal:null,collection:null,preferences:null,rowViews:{},initialize:function(){var i=this;this.rowViews={};this.preferences=new b();this.collection=new d.Libraries();this.collection.fetch({success:function(j){i.render()},error:function(k,j){f.error("An error occured. Please try again.")}})},render:function(j){var k=this.templateLibraryList();var l=null;var i=this.preferences.get("with_deleted");var m=null;if(typeof j!=="undefined"){i=typeof j.with_deleted!=="undefined"?j.with_deleted:false;m=typeof j.models!=="undefined"?j.models:null}if(this.collection!==null&&m===null){if(i){l=this.collection.models}else{l=this.collection.where({deleted:false})}}else{if(m!==null){l=m}else{l=[]}}this.$el.html(k({length:l.length,order:this.collection.sort_order}));this.renderRows(l);$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(n){for(var m=0;m<n.length;m++){var l=n[m];var k=_.findWhere(this.rowViews,{id:l.get("id")});if(k!==undefined){this.$el.find("#library_list_body").append(k.el)}else{var j=new a.LibraryRowView(l);this.$el.find("#library_list_body").append(j.el);this.rowViews[l.get("id")]=j}}},sort_clicked:function(){if(this.collection.sort_order=="asc"){this.sortLibraries("name","desc")}else{this.sortLibraries("name","asc")}this.render()},sortLibraries:function(j,i){if(j==="name"){if(i==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(l,k){if(l.get("name").toLowerCase()>k.get("name").toLowerCase()){return 1}if(k.get("name").toLowerCase()>l.get("name").toLowerCase()){return -1}return 0}}else{if(i==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(l,k){if(l.get("name").toLowerCase()>k.get("name").toLowerCase()){return -1}if(k.get("name").toLowerCase()>l.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container table-responsive">');tmpl_array.push("<% if(length === 0) { %>");tmpl_array.push("<div>I see no libraries. Why don't you create one?</div>");tmpl_array.push("<% } else{ %>");tmpl_array.push('<table class="grid table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th style="width:30%;"><a class="sort-libraries-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(' <th style="width:22%;">description</th>');tmpl_array.push(' <th style="width:22%;">synopsis</th> ');tmpl_array.push(' <th style="width:26%;"></th> ');tmpl_array.push(" </thead>");tmpl_array.push(' <tbody id="library_list_body">');tmpl_array.push(" </tbody>");tmpl_array.push("</table>");tmpl_array.push("<% }%>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewLibraryInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_library_modal">');tmpl_array.push(" <form>");tmpl_array.push(' <input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push(' <input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push(' <input type="text" name="Synopsis" value="" placeholder="Synopsis">');tmpl_array.push(" </form>");tmpl_array.push("</div>");return tmpl_array.join("")},save_library_modification:function(l){var k=$(l.target).closest("tr");var i=this.collection.get(k.data("id"));var j=false;var n=k.find(".input_library_name").val();if(typeof n!=="undefined"&&n!==i.get("name")){if(n.length>2){i.set("name",n);j=true}else{f.warning("Library name has to be at least 3 characters long");return}}var m=k.find(".input_library_description").val();if(typeof m!=="undefined"&&m!==i.get("description")){i.set("description",m);j=true}var o=k.find(".input_library_synopsis").val();if(typeof o!=="undefined"&&o!==i.get("synopsis")){i.set("synopsis",o);j=true}if(j){i.save(null,{patch:true,success:function(p){f.success("Changes to library saved");galaxyLibraryview.toggle_library_modification(k)},error:function(q,p){f.error("An error occured during updating the library :(")}})}},edit_button_event:function(i){this.toggle_library_modification($(i.target).closest("tr"))},toggle_library_modification:function(l){var i=this.collection.get(l.data("id"));l.find(".public_lib_ico").toggle();l.find(".deleted_lib_ico").toggle();l.find(".edit_library_btn").toggle();l.find(".upload_library_btn").toggle();l.find(".permission_library_btn").toggle();l.find(".save_library_btn").toggle();l.find(".cancel_library_btn").toggle();if(i.get("deleted")){}else{l.find(".delete_library_btn").toggle()}if(l.find(".edit_library_btn").is(":hidden")){var j=i.get("name");var n='<input type="text" class="form-control input_library_name" placeholder="name">';l.children("td").eq(0).html(n);if(typeof j!==undefined){l.find(".input_library_name").val(j)}var k=i.get("description");var n='<input type="text" class="form-control input_library_description" placeholder="description">';l.children("td").eq(1).html(n);if(typeof k!==undefined){l.find(".input_library_description").val(k)}var m=i.get("synopsis");var n='<input type="text" class="form-control input_library_synopsis" placeholder="synopsis">';l.children("td").eq(2).html(n);if(typeof m!==undefined){l.find(".input_library_synopsis").val(m)}}else{l.children("td").eq(0).html(i.get("name"));l.children("td").eq(1).html(i.get("description"));l.children("td").eq(2).html(i.get("synopsis"))}},cancel_library_modification:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);j.children("td").eq(0).html(i.get("name"));j.children("td").eq(1).html(i.get("description"));j.children("td").eq(2).html(i.get("synopsis"))},undelete_library:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);i.url=i.urlRoot+i.id+"?undelete=true";i.destroy({success:function(l){l.set("deleted",false);galaxyLibraryview.collection.add(l);j.removeClass("active");f.success("Library has been undeleted")},error:function(){f.error("An error occured while undeleting the library :(")}})},delete_library:function(k){var j=$(k.target).closest("tr");var i=this.collection.get(j.data("id"));this.toggle_library_modification(j);i.destroy({success:function(l){j.remove();l.set("deleted",true);galaxyLibraryview.collection.add(l);f.success("Library has been marked deleted")},error:function(){f.error("An error occured during deleting the library :(")}})},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(j){j.preventDefault();j.stopPropagation();var i=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){i.create_new_library_event()},Close:function(){i.modal.hide()}}})},create_new_library_event:function(){var k=this.serialize_new_library();if(this.validate_new_library(k)){var j=new d.Library();var i=this;j.save(k,{success:function(l){i.collection.add(l);i.modal.hide();i.clear_library_modal();i.render();f.success("Library created")},error:function(){f.error("An error occured :(")}})}else{f.error("Library's name is missing")}return false},clear_library_modal:function(){$("input[name='Name']").val("");$("input[name='Description']").val("");$("input[name='Synopsis']").val("")},serialize_new_library:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val(),synopsis:$("input[name='Synopsis']").val()}},validate_new_library:function(i){return i.name!==""}});return{LibraryListView:g}});
\ No newline at end of file
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/packed/mvc/library/library-libraryrow-view.js
--- /dev/null
+++ b/static/scripts/packed/mvc/library/library-libraryrow-view.js
@@ -0,0 +1,1 @@
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({initialize:function(f){this.render(f)},render:function(g){var f=this.templateRow();this.setElement(f({library:g}));this.set_up_visual_features(g)},set_up_visual_features:function(f){if(f.get("deleted")===true){this.$el.addClass("active")}this.$el.show()},templateRow:function(){tmpl_array=[];tmpl_array.push(' <tr style="display:none;" data-id="<%- library.get("id") %>">');tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(' <td class="right-center">');tmpl_array.push(' <% if(library.get("deleted") === true) { %>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg deleted_lib_ico"></span>');tmpl_array.push(' <% } else if(library.get("public") === true) { %>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Public" style="color:grey;" class="fa fa-globe fa-lg public_lib_ico"></span>');tmpl_array.push(" <% }%>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Upload to library" class="primary-button btn-xs upload_library_btn" type="button"><span class="fa fa-upload"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify library" class="primary-button btn-xs edit_library_btn" type="button"><span class="fa fa-pencil"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify permissions" class="primary-button btn-xs permission_library_btn" type="button"><span class="fa fa-group"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save changes" class="primary-button btn-xs save_library_btn" type="button" style="display:none;"><span class="fa fa-floppy-o"> Save</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Discard changes" class="primary-button btn-xs cancel_library_btn" type="button" style="display:none;"><span class="fa fa-times"> Cancel</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Delete library (can be undeleted later)" class="primary-button btn-xs delete_library_btn" type="button" style="display:none;"><span class="fa fa-trash-o"> Delete</span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Undelete library" class="primary-button btn-xs undelete_library_btn" type="button" style="display:none;"><span class="fa fa-unlock"> Undelete</span></button>');tmpl_array.push(" </td>");tmpl_array.push(" </tr>");return _.template(tmpl_array.join(""))}});return{LibraryRowView:a}});
\ No newline at end of file
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/packed/mvc/library/library-librarytoolbar-view.js
--- a/static/scripts/packed/mvc/library/library-librarytoolbar-view.js
+++ b/static/scripts/packed/mvc/library/library-librarytoolbar-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(a,d,e,c){var b=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"delegate_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},delegate_modal:function(f){galaxyLibraryview.show_library_modal(f)},check_include_deleted:function(f){if(f.target.checked){galaxyLibraryview.render({with_deleted:true})}else{galaxyLibraryview.render({with_deleted:false})}},render:function(){var f=this.templateToolBar();this.$el.html(f())},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div id="libraries_container" style="width: 90%; margin: auto; margin-top:2em; overflow: auto !important; ">');tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');tmpl_array.push(' <h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push(' <div id="library_toolbar">');tmpl_array.push(' <input id="include_deleted_chk" style="margin: 0;" type="checkbox">include deleted</input>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Library" id="create_new_library_btn" class="primary-button" type="button"><span class="fa fa-plus"></span> New Library</button>');tmpl_array.push(" </div>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="libraries_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))}});return{ToolbarView:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(a,d,e,c){var b=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"delegate_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},delegate_modal:function(f){libraryListView.show_library_modal(f)},check_include_deleted:function(f){if(f.target.checked){libraryListView.preferences.set({with_deleted:true});libraryListView.render()}else{libraryListView.preferences.set({with_deleted:false});libraryListView.render()}},render:function(){var f=this.templateToolBar();this.$el.html(f())},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div id="libraries_container" style="width: 90%; margin: auto; margin-top:2em; overflow: auto !important; ">');tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');tmpl_array.push(' <h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push(' <div id="library_toolbar">');tmpl_array.push(' <input id="include_deleted_chk" style="margin: 0;" type="checkbox">include deleted</input>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Library" id="create_new_library_btn" class="primary-button" type="button"><span class="fa fa-plus"></span> New Library</button>');tmpl_array.push(" </div>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="libraries_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))}});return{ToolbarView:b}});
\ No newline at end of file
diff -r 876bc02f522fa636fd42c91b22e6588be8833176 -r 813a11e7b98ac4a20abf3a185a7233a6a947a3c4 static/scripts/packed/mvc/library/library-model.js
--- a/static/scripts/packed/mvc/library/library-model.js
+++ b/static/scripts/packed/mvc/library/library-model.js
@@ -1,1 +1,1 @@
-define([],function(){var e=Backbone.Model.extend({urlRoot:"/api/libraries/"});var a=Backbone.Model.extend({urlRoot:"/api/folders"});var h=Backbone.Collection.extend({url:"/api/libraries",model:e,sort_key:"name",sort_order:null});var f=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var c=Backbone.Collection.extend({model:f});var d=Backbone.Model.extend({defaults:{folder:new c(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(j){this.full_path=j[0].full_path;this.get("folder").reset(j[1].folder_contents);return j}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var g=Backbone.Model.extend({url:"/api/histories/"});var i=Backbone.Collection.extend({url:"/api/histories",model:g});return{Library:e,FolderAsModel:a,Libraries:h,Item:f,Folder:c,FolderContainer:d,HistoryItem:b,GalaxyHistory:g,GalaxyHistories:i}});
\ No newline at end of file
+define([],function(){var e=Backbone.Model.extend({urlRoot:"/api/libraries/",isVisible:function(k){var j=true;if((!show_delete)&&(this.get("deleted"))){j=false}return j}});var a=Backbone.Model.extend({urlRoot:"/api/folders"});var h=Backbone.Collection.extend({url:"/api/libraries",model:e,sort_key:"name",sort_order:null,initialize:function(j){j=j||{}},getVisible:function(k,l){l=l||[];var j=new h(this.filter(function(m){return m.isVisible(k)}));return j}});var f=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var c=Backbone.Collection.extend({model:f});var d=Backbone.Model.extend({defaults:{folder:new c(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(j){this.full_path=j[0].full_path;this.get("folder").reset(j[1].folder_contents);return j}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var g=Backbone.Model.extend({url:"/api/histories/"});var i=Backbone.Collection.extend({url:"/api/histories",model:g});return{Library:e,FolderAsModel:a,Libraries:h,Item:f,Folder:c,FolderContainer:d,HistoryItem:b,GalaxyHistory:g,GalaxyHistories:i}});
\ 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
commit/galaxy-central: davebgx: Correctly detect when a mercurial request is a fresh checkout of a tool shed repository.
by commits-noreply@bitbucket.org 28 Mar '14
by commits-noreply@bitbucket.org 28 Mar '14
28 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/876bc02f522f/
Changeset: 876bc02f522f
User: davebgx
Date: 2014-03-28 18:42:08
Summary: Correctly detect when a mercurial request is a fresh checkout of a tool shed repository.
Affected #: 1 file
diff -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 -r 876bc02f522fa636fd42c91b22e6588be8833176 lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
--- a/lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
+++ b/lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
@@ -40,27 +40,30 @@
def __call__( self, environ, start_response ):
cmd = self.__get_hg_command( **environ )
- if cmd == 'changegroup':
- # This is an hg clone from the command line. When doing this, the following 5 commands, in order,
- # will be retrieved from environ:
- # between -> heads -> changegroup -> capabilities -> listkeys
- #
- # Increment the value of the times_downloaded column in the repository table for the cloned repository.
- if 'PATH_INFO' in environ:
- # Instantiate a database connection
- engine = sqlalchemy.create_engine( self.db_url )
- connection = engine.connect()
- path_info = environ[ 'PATH_INFO' ].lstrip( '/' )
- user_id, repository_name = self.__get_user_id_repository_name_from_path_info( connection, path_info )
- sql_cmd = "SELECT times_downloaded FROM repository WHERE user_id = %d AND name = '%s'" % ( user_id, repository_name.lower() )
- result_set = connection.execute( sql_cmd )
- for row in result_set:
- # Should only be 1 row...
- times_downloaded = row[ 'times_downloaded' ]
- times_downloaded += 1
- sql_cmd = "UPDATE repository SET times_downloaded = %d WHERE user_id = %d AND name = '%s'" % ( times_downloaded, user_id, repository_name.lower() )
- connection.execute( sql_cmd )
- connection.close()
+ # The 'getbundle' command indicates that a mercurial client is getting a bundle of one or more changesets, indicating
+ # a clone or a pull.
+ if cmd == 'getbundle':
+ common, _ = environ[ 'HTTP_X_HGARG_1' ].split( '&' )
+ # The 'common' parameter indicates the full sha-1 hash of the changeset the client currently has checked out. If
+ # this is 0000000000000000000000000000000000000000, then the client is performing a fresh checkout. If it has any
+ # other value, the client is getting updates to an existing checkout.
+ if common == 'common=0000000000000000000000000000000000000000':
+ # Increment the value of the times_downloaded column in the repository table for the cloned repository.
+ if 'PATH_INFO' in environ:
+ # Instantiate a database connection
+ engine = sqlalchemy.create_engine( self.db_url )
+ connection = engine.connect()
+ path_info = environ[ 'PATH_INFO' ].lstrip( '/' )
+ user_id, repository_name = self.__get_user_id_repository_name_from_path_info( connection, path_info )
+ sql_cmd = "SELECT times_downloaded FROM repository WHERE user_id = %d AND name = '%s'" % ( user_id, repository_name.lower() )
+ result_set = connection.execute( sql_cmd )
+ for row in result_set:
+ # Should only be 1 row...
+ times_downloaded = row[ 'times_downloaded' ]
+ times_downloaded += 1
+ sql_cmd = "UPDATE repository SET times_downloaded = %d WHERE user_id = %d AND name = '%s'" % ( times_downloaded, user_id, repository_name.lower() )
+ connection.execute( sql_cmd )
+ connection.close()
elif cmd in [ 'unbundle', 'pushkey' ]:
# This is an hg push from the command line. When doing this, the following commands, in order,
# will be retrieved from environ (see the docs at http://mercurial.selenic.com/wiki/WireProtocol)
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: guerler: Charts: Improve event deferral
by commits-noreply@bitbucket.org 28 Mar '14
by commits-noreply@bitbucket.org 28 Mar '14
28 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/37fa3f5a47f8/
Changeset: 37fa3f5a47f8
User: guerler
Date: 2014-03-28 07:16:57
Summary: Charts: Improve event deferral
Affected #: 7 files
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -13,6 +13,9 @@
// initialize
initialize: function(options)
{
+ // deactivate all debugs outputs
+ window.console.debug = function() {};
+
// link options
this.options = options;
@@ -55,7 +58,7 @@
// show viewport
this.go('viewer');
- // redraw chart
+ // draw chart
this.chart.trigger('redraw');
}
},
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/static/build-app.js
--- a/config/plugins/visualizations/charts/static/build-app.js
+++ b/config/plugins/visualizations/charts/static/build-app.js
@@ -3,4 +3,4 @@
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore may be freely distributed under the MIT license.
-(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,t,r){n("GET",e,{},t,r)}function n(e,t,n,r,i){if(e=="GET"||e=="DELETE")t.indexOf("?")==-1?t+="?":t+="&",t+=$.param(n);var s=new XMLHttpRequest;s.open(e,t,!0),s.setRequestHeader("Accept","application/json"),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-Type","application/json"),s.onloadend=function(){var e=s.status;try{response=jQuery.parseJSON(s.responseText)}catch(t){response=s.responseText}e==200?r&&r(response):i&&i(response)},e=="GET"||e=="DELETE"?s.send():s.send(JSON.stringify(n))}function r(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function i(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function s(t,n){return t?e.defaults(t,n):n}function o(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function u(){return(new Date).getTime().toString(36)}function a(e){var t=$("<p></p>");return t.append(e),t}function f(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:i,cssGetAttribute:r,get:t,merge:s,bytesToString:o,uuid:u,time:f,wrap:a,request:n}}),define("mvc/ui/ui-modal",["utils/utils"],function(e){var t=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#title-text"),this.options.height&&(this.$el.find("#body").css("height",this.options.height),this.$el.find("#content").css("overflow",this.options.overflow)),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var n=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),n.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var n=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),n.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t){this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div class="toolForm portlet-view no-highlight">';if(e.title||e.icon)t+='<div id="title" class="toolFormTitle portlet-title"><div id="operations" class="portlet-operations"/><div style="overflow: hidden;">',e.icon&&(t+='<div class="portlet-title-icon fa '+e.icon+'"> </div>'),t+='<div id="title-text" class="portlet-title-text">'+e.title+"</div>",t+="</div></div>";return t+='<div id="body" class="toolFormBody portlet-body">',e.placement=="top"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+='<div id="content" class="portlet-content"/>',e.placement=="bottom"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+="</div></div>",t}});return{View:t}}),define("plugin/library/ui-select",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",empty:"No data available",visible:!0,wait:!1},selected:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find("#select"),this.$icon=this.$el.find("#icon"),this.selected=this.options.value;var n=this;this.options.onchange&&this.$select.on("change",function(){n.value(n.$select.val())}),this._refresh(),this.options.visible||this.hide(),this.options.wait?this.wait():this.show()},value:function(e){var t=this.selected;e!==undefined&&(this.selected=e,this.$select.val(e));var n=this.selected;return n&&n!=t&&this.options.onchange&&this.options.onchange(n),n},text:function(){return this.$select.find("option:selected").text()},show:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down"),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin"),this.$select.hide()},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){this.$select.find("option").remove();for(var t in e)this.$select.append(this._templateOption(e[t]));!this.selected&&e.length>0&&this.value(e[0].value),this._refresh()},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.$select.append(this._templateOption({value:"null",label:this.options.empty})),this.disable()):(this.enable(),this.selected&&this.$select.val(this.selected))},_exists:function(e){return 0!=this.$select.find("option[value="+e+"]").length},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){var t='<div id="'+e.id+'" class="styled-select">'+'<div class="button">'+'<i id="icon"/>'+"</div>"+'<select id="select" class="select '+e.cls+" "+e.id+'">';for(key in e.data){var n=e.data[key],r="";if(n.value==e.value||n.value=="")r="selected";t+='<option value="'+n.value+'" '+r+">"+n.label+"</option>"}return t+="</select></div>",t}});return{View:t}}),define("plugin/library/ui",["utils/utils","plugin/library/ui-select"],function(e,t){var n=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.find("b").html(e)},_template:function(e){return"<label><b>"+e.title+"</b></label>"},value:function(){return options.title}}),r=Backbone.View.extend({optionsDefault:{id:null,title:"","float":"right",cls:"btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="margin-right: 5px; float: '+e.float+';" type="button" class="btn '+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),i=Backbone.View.extend({optionsDefault:{"float":"right",icon:"",tooltip:"",placement:"bottom",title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" style="font-size: 1.2em;"/> '+e.title+"</div>"}}),s=Backbone.View.extend({optionsDefault:{title:"",id:null,"float":"right",cls:"icon-btn",icon:"",tooltip:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="margin-right: 5px; float: '+e.float+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div style="margin-right: 5px; margin-left: 5px;"><i class="icon fa '+e.icon+'"/> '+'<span style="position: relative; font-size: 0.8em; font-weight: normal; top: -1px;">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),o=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)">'+e.title+"</a></div>"}}),u=Backbone.View.extend({optionsDefault:{message:"",status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>")},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.fadeIn();if(!t.persistent){var n=this;window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="alert alert-'+e.status+'" style="padding: 2px 2px 2px 10px;">'+e.message+"</div>"}}),a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),f=Backbone.View.extend({optionsDefault:{title:"Unlabeled",body:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.body&&this.$el.find(".body").append(this.options.body)},_template:function(e){return'<div id="title" class="title">'+e.title+":"+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:"",title:"",target:"",href:"",onunload:null,onclick:null,visible:!0,icon:null,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide()},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t='<div id="'+e.id+'" class="button-menu btn-group">'+'<button type="button" class="root btn btn-default dropdown-toggle" data-toggle="dropdown">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),"</button></div>",t}}),c=Backbone.View.extend({optionsDefault:{value:"",type:"text",placeholder:"",disabled:!1,visible:!0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.options.onchange&&this.$el.on("input",function(){n.options.onchange()})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="form-control">'}});return{Label:n,Button:r,Icon:i,ButtonIcon:s,Input:c,Anchor:o,Message:u,Searchbox:a,Title:f,Select:t,ButtonMenu:l}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},cleanup:function(t){var n=t.get("dataset_id_job");if(n!=""){var r=this;e.request("PUT",config.root+"api/histories/none/contents/"+n,{deleted:!0},function(){r._refreshHdas()}),t.set("dataset_id_job","")}},submit:function(t,n,r,i){var s=this,o=t.id,u=t.get("type"),a=this.app.types.get(u);data={tool_id:"rkit",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:u,columns:r,settings:n}},t.state("submit","Sending job request..."),e.request("POST",config.root+"api/tools",data,function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response.");else{s._refreshHdas();var n=e.outputs[0];t.state("queued","Job has been queued..."),t.set("dataset_id_job",n.id),s._loop(n.id,function(e){switch(e.state){case"ok":return t.state("success","Job completed successfully..."),i(e),!0;case"error":return t.state("failed","Job has failed. Please check the history for details."),!0;case"running":return t.state("running","Job is running..."),!1}})}},function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the R-kit. Please make sure it is installed. "+n)})},_loop:function(t,n){var r=this;e.request("GET",config.root+"api/jobs/"+t,{},function(e){n(e)||setTimeout(function(){r._loop(t,n)},r.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshHdas()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(t,n,r){var i=this;if(t.groups)this._fetch(t,n);else{var s=this.list[t.id];if(s){n(s);return}e.request("GET",config.root+"api/datasets/"+t.id,{},function(e){switch(e.state){case"error":r&&r(e);break;default:i.list[t.id]=e,n(e)}})}},_fetch:function(t,n){var r=t.start?t.start:0,i=Math.abs(t.end-t.start),s=this.app.config.get("query_limit");if(!i||i>s)i=s;var o="",u={},a=0;for(var f in t.groups){var l=t.groups[f];for(var c in l.columns){var h=l.columns[c];o+=h+",",u[h]=a,a++}}if(a==0){n({});return}o=o.substring(0,o.length-1);var p=t.groups.slice(0);for(var f in p)p[f].values=[];var d=this;e.request("GET",config.root+"api/datasets/"+t.id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},function(e){for(var i in e.data){var s=e.data[i];for(var o in t.groups){var a=t.groups[o],f={x:parseInt(i)+r};for(var l in a.columns){var c=a.columns[l],h=u[c],d=s[h];if(isNaN(d)||!d)d=0;f[l]=d}p[o].values.push(f)}}n(p)})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/models/chart",["plugin/models/groups","mvc/visualization/visualization-model"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state_info",t),this.set("state",e)},drawable:function(){return this.get("state")=="ok"||this.get("state")=="failed"||this.get("state")=="initialized"},editable:function(){return this.get("state")=="ok"||this.get("state")=="failed"}})}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;this.chart.set(e.attributes),this.chart.settings.set(e.settings);for(var t in e.groups)this.chart.groups.add(new n(e.groups[t]));return this.chart.state("ok","Loaded previously saved visualization."),this.chart.set("modified",!1),!0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template()));var r=this;this.chart.on("redraw",function(){r._create_svg(),r._draw(r.chart)}),this.chart.on("change:state",function(){var e=r.$el.find("#info"),t=e.find("#icon");t.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var n=r.chart.get("state");switch(n){case"ok":r.chart.trigger("drawable"),e.hide();break;case"failed":r.chart.trigger("drawable"),t.addClass("fa fa-warning");break;case"initialized":r.chart.trigger("drawable");default:t.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_create_svg:function(){this.svg&&this.svg.remove(),this.$el.append($(this._template_svg())),this.svg=d3.select(this.$el.find("svg")[0])},_draw:function(e){var t=this;if(!e.drawable()){e.off("drawable"),e.on("drawable",function(){t.chart.off("drawable"),e.drawable()&&t._draw(e)});return}e.state("wait","Please wait...");var n=e.get("type"),r=this.app.types.get(n);if(!r.execute||r.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+n+"/"+n],function(n){var i=new n(t.app,{svg:t.svg});r.execute?e.get("dataset_id_job")==""?t.app.jobs.submit(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){this.app.storage.save(),i.draw(e,t._defaultRequestDictionary(e))}):i.draw(e,t._defaultRequestDictionary(e)):i.draw(e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t=this.app.types.get(e.get("type")),n="",r=0;return e.groups.each(function(e){for(var i in t.columns)n+=i+"_"+ ++r+":"+(parseInt(e.get(i))+1)+", "}),n.substring(0,n.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t=this.app.types.get(e.get("type")),n={groups:[]};t.execute?n.id=e.get("dataset_id_job"):n.id=e.get("dataset_id");var r=0;return e.groups.each(function(e){var i={};for(var s in t.columns)i[s]=e.get(s);n.groups.push({key:++r+":"+e.get("key"),columns:i})}),n},_template:function(){return'<div style="height: 100%; min-height: 50px;"><div id="info" style="position: absolute; margin-left: 10px; margin-top: 10px; margin-bottom: 50px;"><span id="icon" style="font-size: 1.2em; display: inline-block;"/><span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/></div></div>'},_template_svg:function(){return'<svg style="height: calc(100% - 80px)"/>'}})}),define("plugin/views/viewer",["utils/utils","plugin/library/ui","mvc/ui/ui-portlet","plugin/models/group","plugin/views/viewport"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,r){this.app=e,this.chart=this.app.chart,this.viewport_view=new i(e);var s=this;this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",operations:{edit_button:new t.ButtonIcon({icon:"fa-gear",tooltip:"Customize Chart",title:"Customize",onclick:function(){s._wait(s.chart,function(){s.app.go("editor")})}})}}),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var s=this;this.chart.on("change:title",function(){s._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){if(e.editable())t();else{var n=this;this.app.modal.show({title:"Please wait!",body:"Your chart is currently being processed. Please wait and try again.",buttons:{Close:function(){n.app.modal.hide()},Retry:function(){n.app.modal.hide(),setTimeout(function(){n._wait(e,t)},n.app.config.get("query_timeout"))}}})}}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},add:function(e){var t=e.id,n={$title:$(this._template_tab(e)),$content:$(this._template_tab_content(e)),removable:e.ondel?!0:!1};this.list[t]=n,this.options.onnew?this.$nav.find("#new-tab").before(n.$title):this.$nav.append(n.$title),n.$content.append(e.$el),this.$content.append(n.$content),_.size(this.list)==1&&(n.$title.addClass("active"),n.$content.addClass("active"),this.first_tab=t);if(e.ondel){var r=this,i=n.$title.find("#delete");i.tooltip({title:"Delete this tab",placement:"bottom",container:r.$el}),i.on("click",function(){return i.tooltip("destroy"),r.$el.find(".tooltip").remove(),e.ondel(),!1})}e.onclick&&n.$title.on("click",function(){e.onclick()})},del:function(e){var t=this.list[e];t.$title.remove(),t.$content.remove(),delete t,this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab)},delRemovable:function(){for(var e in this.list){var t=this.list[e];t.removable&&this.del(e)}},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&this.list[e].$title.find("a").tab("show")},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.list[e].$title.find("#text");return t&&n.html(t),n.html()},_template:function(e){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="title-'+e.id+'">'+'<a title="" href="#tab-'+e.id+'" data-toggle="tab" data-original-title="">'+'<span id="text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="tab-'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("plugin/library/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null},events:{click:"_onclick",dblclick:"_ondblclick"},first:!0,initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(t));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=$("<tr></tr>")},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t){var n=$("<td></td>");t&&n.css("width",t),n.append(e),this.row.append(n)},append:function(e){this._commit(e)},prepend:function(e){this._commit(e,!0)},remove:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},removeAll:function(){this.$tbody.html(""),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t){this.remove(e),this.row.attr("id",e),t?this.$tbody.prepend(this.row):this.$tbody.append(this.row),this.row=$("<tr></tr>"),this.row_count++,this._refresh()},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="grid"><thead></thead><tbody style="cursor: pointer;"></tbody></table><tmessage>'+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({columns:[],initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(){s.group.set("key",s.group_key.value())}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.app.types.get(n);this.table.removeAll();var s={};for(var o in i.columns){var u=this.group.get(o);u||this.group.set(o,0);var a=i.columns[o],f=new t.Select.View({id:"select_"+o,gid:o,onchange:function(e){r.group.set(this.gid,e),r.chart.set("modified",!0)},value:u,wait:!0});this.table.add(a.title,"25%"),this.table.add(f.$el),this.table.append(o),s[o]=f}this.chart.state("wait","Loading metadata..."),this.app.datasets.request({id:e},function(e){r.columns=[];var t=e.metadata_column_types;for(var n in t)(t[n]=="int"||t[n]=="float")&&r.columns.push({label:"Column: "+(parseInt(n)+1)+" ["+t[n]+"]",value:n});for(var n in s)s[n].update(r.columns),s[n].show();r.chart.state("initialized","Metadata initialized...")})},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){var r=Backbone.View.extend({initialize:function(r){this.table_title=new t.Label({title:r.title}),this.table=new e.View({content:r.content});var i=$("<div/>");i.append(n.wrap(this.table_title.$el)),i.append(n.wrap(this.table.$el)),this.setElement(i)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.removeAll();for(var n in e)this._add(n,e[n],t)},_add:function(e,n,r){var i=null,s=n.type;switch(s){case"text":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"select":i=new t.Select.View({data:n.data,onchange:function(){r.set(e,i.value())}});break;case"slider":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"separator":i=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(s!="separator"){r.get(e)||r.set(e,n.init),i.value(r.get(e));var o=$("<div/>");o.append(i.$el),o.append('<div class="toolParamHelp" style="font-size: 0.9em;">'+n.info+"</div>"),this.table.add('<span style="white-space: nowrap;">'+n.title+"</span>","25%"),this.table.add(o)}else this.table.add('<h6 style="white-space: nowrap;">'+n.title+":<h6/>"),this.table.add($("<div/>"));this.table.append(e)}});return{View:r}}),define("plugin/views/settings",["plugin/library/ui","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View({title:"Chart options:",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refreshTable()})},_refreshTable:function(){var e=this.chart.get("type");if(!e)return;var t=this.app.types.get(e);this.form.title(t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui-table","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(s,o){this.app=s,this.chart=this.app.chart,this.options=i.merge(o,this.optionsDefault),this.portlet=new r.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new n.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){u.app.go("viewer"),u._saveChart()}}),back:new n.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){u.app.go("viewer"),u.app.storage.load()}})}});var u=this;this.table=new t.View({header:!1,onconfirm:function(e){u.chart.groups.length>0?u.app.modal.show({title:"Switching to another chart type?",body:"If you continue your settings and selections will be cleared.",buttons:{Cancel:function(){u.app.modal.hide()},Continue:function(){u.app.modal.hide(),u.table.value(e)}}}):u.table.value(e)},onchange:function(e){u.chart.groups.reset(),u.chart.settings.clear(),u.chart.set({type:e})},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"});var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),h.execute?this.table.add(h.title+" (requires processing)"):this.table.add(h.title),this.table.append(c)}this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=u._addGroupModel();u.tabs.show(e.id)}}),this.title=new n.Input({placeholder:"Chart title",onchange:function(){u.chart.set("title",u.title.value())}});var p=$("<div/>");p.append(i.wrap((new n.Label({title:"Provide a chart title:"})).$el)),p.append(i.wrap(this.title.$el)),p.append(i.wrap((new n.Label({title:"Select a chart type:"})).$el)),p.append(i.wrap(this.table.$el)),this.tabs.add({id:"main",title:"Start",$el:p}),this.settings=new a(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var u=this;this.chart.on("change:title",function(e){u._refreshTitle()}),this.chart.on("change:type",function(e){u.table.value(e.get("type"))}),this.chart.on("reset",function(e){u._resetChart()}),this.app.chart.on("redraw",function(e){u.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){u._addGroup(e)}),this.app.chart.groups.on("remove",function(e){u._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){u._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){u._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Chart data"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new o({id:i.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new u(this.app,{group:e}),r=t.chart.groups.length;this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey()},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",i.uuid()),this.chart.set("type","bardiagram"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.table.value(),title:this.title.value(),date:i.time()}),this.chart.groups.length==0&&this._addGroupModel(),this.chart.trigger("redraw"),this.app.storage.save()}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e3,query_timeout:500}})}),define("plugin/charts/_nvd3/config",[],function(){return{title:"",columns:{y:{title:"Values for y-axis"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},x_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},y_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/bardiagram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/histogram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:!0,columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_tick:{init:".3"}}})}),define("plugin/charts/horizontal/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram (horizontal)",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/line/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/linewithfocus/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/piechart/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Pie chart"})}),define("plugin/charts/scatterplot/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/stackedarea/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/types",["plugin/charts/bardiagram/config","plugin/charts/histogram/config","plugin/charts/horizontal/config","plugin/charts/line/config","plugin/charts/linewithfocus/config","plugin/charts/piechart/config","plugin/charts/scatterplot/config","plugin/charts/stackedarea/config"],function(e,t,n,r,i,s,o,u){return Backbone.Model.extend({defaults:{bardiagram:e,horizontal:n,histogram:t,line:r,linewithfocus:i,piechart:s,scatterplot:o,stackedarea:u}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","plugin/library/ui","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new f,this.types=new c,this.chart=new l,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.viewer_view=new u(this),this.editor_view=new a(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el),this.storage.load()?(this.go("viewer"),this.chart.trigger("redraw")):this.go("editor")},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},execute:function(e){},onunload:function(){},log:function(e,t){console.log(e+" "+t)}})});
\ No newline at end of file
+(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,t,r){n("GET",e,{},t,r)}function n(e,t,n,r,i){if(e=="GET"||e=="DELETE")t.indexOf("?")==-1?t+="?":t+="&",t+=$.param(n);var s=new XMLHttpRequest;s.open(e,t,!0),s.setRequestHeader("Accept","application/json"),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-Type","application/json"),s.onloadend=function(){var e=s.status;try{response=jQuery.parseJSON(s.responseText)}catch(t){response=s.responseText}e==200?r&&r(response):i&&i(response)},e=="GET"||e=="DELETE"?s.send():s.send(JSON.stringify(n))}function r(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function i(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function s(t,n){return t?e.defaults(t,n):n}function o(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function u(){return(new Date).getTime().toString(36)}function a(e){var t=$("<p></p>");return t.append(e),t}function f(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:i,cssGetAttribute:r,get:t,merge:s,bytesToString:o,uuid:u,time:f,wrap:a,request:n}}),define("mvc/ui/ui-modal",["utils/utils"],function(e){var t=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#title-text"),this.options.height&&(this.$el.find("#body").css("height",this.options.height),this.$el.find("#content").css("overflow",this.options.overflow)),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var n=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),n.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var n=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),n.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t){this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div class="toolForm portlet-view no-highlight">';if(e.title||e.icon)t+='<div id="title" class="toolFormTitle portlet-title"><div id="operations" class="portlet-operations"/><div style="overflow: hidden;">',e.icon&&(t+='<div class="portlet-title-icon fa '+e.icon+'"> </div>'),t+='<div id="title-text" class="portlet-title-text">'+e.title+"</div>",t+="</div></div>";return t+='<div id="body" class="toolFormBody portlet-body">',e.placement=="top"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+='<div id="content" class="portlet-content"/>',e.placement=="bottom"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+="</div></div>",t}});return{View:t}}),define("plugin/library/ui-select",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",empty:"No data available",visible:!0,wait:!1},selected:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find("#select"),this.$icon=this.$el.find("#icon"),this.selected=this.options.value;var n=this;this.options.onchange&&this.$select.on("change",function(){n.value(n.$select.val())}),this._refresh(),this.options.visible||this.hide(),this.options.wait?this.wait():this.show()},value:function(e){var t=this.selected;e!==undefined&&(this.selected=e,this.$select.val(e));var n=this.selected;return n&&n!=t&&this.options.onchange&&this.options.onchange(n),n},text:function(){return this.$select.find("option:selected").text()},show:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down"),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin"),this.$select.hide()},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){this.$select.find("option").remove();for(var t in e)this.$select.append(this._templateOption(e[t]));!this.selected&&e.length>0&&this.value(e[0].value),this._refresh()},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.$select.append(this._templateOption({value:"null",label:this.options.empty})),this.disable()):(this.enable(),this.selected&&this.$select.val(this.selected))},_exists:function(e){return 0!=this.$select.find("option[value="+e+"]").length},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){var t='<div id="'+e.id+'" class="styled-select">'+'<div class="button">'+'<i id="icon"/>'+"</div>"+'<select id="select" class="select '+e.cls+" "+e.id+'">';for(key in e.data){var n=e.data[key],r="";if(n.value==e.value||n.value=="")r="selected";t+='<option value="'+n.value+'" '+r+">"+n.label+"</option>"}return t+="</select></div>",t}});return{View:t}}),define("plugin/library/ui",["utils/utils","plugin/library/ui-select"],function(e,t){var n=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.find("b").html(e)},_template:function(e){return"<label><b>"+e.title+"</b></label>"},value:function(){return options.title}}),r=Backbone.View.extend({optionsDefault:{id:null,title:"","float":"right",cls:"btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="margin-right: 5px; float: '+e.float+';" type="button" class="btn '+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),i=Backbone.View.extend({optionsDefault:{"float":"right",icon:"",tooltip:"",placement:"bottom",title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" style="font-size: 1.2em;"/> '+e.title+"</div>"}}),s=Backbone.View.extend({optionsDefault:{title:"",id:null,"float":"right",cls:"icon-btn",icon:"",tooltip:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="margin-right: 5px; float: '+e.float+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div style="margin-right: 5px; margin-left: 5px;"><i class="icon fa '+e.icon+'"/> '+'<span style="position: relative; font-size: 0.8em; font-weight: normal; top: -1px;">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),o=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)">'+e.title+"</a></div>"}}),u=Backbone.View.extend({optionsDefault:{message:"",status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>")},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.fadeIn();if(!t.persistent){var n=this;window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="alert alert-'+e.status+'" style="padding: 2px 2px 2px 10px;">'+e.message+"</div>"}}),a=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),f=Backbone.View.extend({optionsDefault:{title:"Unlabeled",body:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.body&&this.$el.find(".body").append(this.options.body)},_template:function(e){return'<div id="title" class="title">'+e.title+":"+"</div>"}}),l=Backbone.View.extend({optionsDefault:{id:"",title:"",target:"",href:"",onunload:null,onclick:null,visible:!0,icon:null,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide()},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t='<div id="'+e.id+'" class="button-menu btn-group">'+'<button type="button" class="root btn btn-default dropdown-toggle" data-toggle="dropdown">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),"</button></div>",t}}),c=Backbone.View.extend({optionsDefault:{value:"",type:"text",placeholder:"",disabled:!1,visible:!0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.options.onchange&&this.$el.on("input",function(){n.options.onchange()})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="form-control">'}});return{Label:n,Button:r,Icon:i,ButtonIcon:s,Input:c,Anchor:o,Message:u,Searchbox:a,Title:f,Select:t,ButtonMenu:l}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},cleanup:function(t){var n=t.get("dataset_id_job");if(n!=""){var r=this;e.request("PUT",config.root+"api/histories/none/contents/"+n,{deleted:!0},function(){r._refreshHdas()}),t.set("dataset_id_job","")}},submit:function(t,n,r,i){var s=this,o=t.id,u=t.get("type"),a=this.app.types.get(u);data={tool_id:"rkit",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:u,columns:r,settings:n}},t.state("submit","Sending job request..."),e.request("POST",config.root+"api/tools",data,function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response.");else{s._refreshHdas();var n=e.outputs[0];t.state("queued","Job has been queued..."),t.set("dataset_id_job",n.id),s._loop(n.id,function(e){switch(e.state){case"ok":return t.state("success","Job completed successfully..."),i(e),!0;case"error":return t.state("failed","Job has failed. Please check the history for details."),!0;case"running":return t.state("running","Job is running..."),!1}})}},function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the R-kit. Please make sure it is installed. "+n)})},_loop:function(t,n){var r=this;e.request("GET",config.root+"api/jobs/"+t,{},function(e){n(e)||setTimeout(function(){r._loop(t,n)},r.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshHdas()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(t,n,r){var i=this;if(t.groups)this._fetch(t,n);else{var s=this.list[t.id];if(s){n(s);return}e.request("GET",config.root+"api/datasets/"+t.id,{},function(e){switch(e.state){case"error":r&&r(e);break;default:i.list[t.id]=e,n(e)}})}},_fetch:function(t,n){var r=t.start?t.start:0,i=Math.abs(t.end-t.start),s=this.app.config.get("query_limit");if(!i||i>s)i=s;var o="",u={},a=0;for(var f in t.groups){var l=t.groups[f];for(var c in l.columns){var h=l.columns[c];o+=h+",",u[h]=a,a++}}if(a==0){n({});return}o=o.substring(0,o.length-1);var p=t.groups.slice(0);for(var f in p)p[f].values=[];var d=this;e.request("GET",config.root+"api/datasets/"+t.id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:o},function(e){for(var i in e.data){var s=e.data[i];for(var o in t.groups){var a=t.groups[o],f={x:parseInt(i)+r};for(var l in a.columns){var c=a.columns[l],h=u[c],d=s[h];if(isNaN(d)||!d)d=0;f[l]=d}p[o].values.push(f)}}n(p)})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/models/chart",["plugin/models/groups","mvc/visualization/visualization-model"],function(e){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(t){this.groups=new e,this.settings=new Backbone.Model;var n=this;this.on("change:state",function(){var e=n.get("state");n.ready(e)&&n.trigger("ready"),console.debug(e+" : "+n.get("state_info"))})},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state_info",t),this.set("state",e)},ready:function(){return this.get("state")=="ok"||this.get("state")=="failed"||this.get("state")=="initialized"},editable:function(){return this.get("state")=="ok"||this.get("state")=="failed"},deferred:function(e){this.ready()?e():this.once("ready",function(){e()})}})}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;this.chart.set(e.attributes),this.chart.settings.set(e.settings);for(var t in e.groups)this.chart.groups.add(new n(e.groups[t]));return this.chart.state("ok","Loaded previously saved visualization..."),this.chart.set("modified",!1),!0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._create_svg();var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("change:state",function(){var e=r.$el.find("#info"),t=e.find("#icon");t.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var n=r.chart.get("state");switch(n){case"ok":e.hide();break;case"failed":t.addClass("fa fa-warning");break;default:t.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_create_svg:function(){this.svg&&this.svg.remove(),this.$el.append($(this._template_svg())),this.svg=d3.select(this.$el.find("svg")[0])},_draw:function(e){var t=this;this._create_svg(),e.state("wait","Please wait...");var n=e.get("type"),r=this.app.types.get(n);if(!r.execute||r.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+n+"/"+n],function(n){var i=new n(t.app,{svg:t.svg});r.execute?e.get("dataset_id_job")==""?t.app.jobs.submit(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){this.app.storage.save(),i.draw(e,t._defaultRequestDictionary(e))}):i.draw(e,t._defaultRequestDictionary(e)):i.draw(e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t=this.app.types.get(e.get("type")),n="",r=0;return e.groups.each(function(e){for(var i in t.columns)n+=i+"_"+ ++r+":"+(parseInt(e.get(i))+1)+", "}),n.substring(0,n.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t=this.app.types.get(e.get("type")),n={groups:[]};t.execute?n.id=e.get("dataset_id_job"):n.id=e.get("dataset_id");var r=0;return e.groups.each(function(e){var i={};for(var s in t.columns)i[s]=e.get(s);n.groups.push({key:++r+":"+e.get("key"),columns:i})}),n},_template:function(){return'<div style="height: 100%; min-height: 50px;"><div id="info" style="position: absolute; margin-left: 10px; margin-top: 10px; margin-bottom: 50px;"><span id="icon" style="font-size: 1.2em; display: inline-block;"/><span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/></div></div>'},_template_svg:function(){return'<svg style="height: calc(100% - 80px)"/>'}})}),define("plugin/views/viewer",["utils/utils","plugin/library/ui","mvc/ui/ui-portlet","plugin/models/group","plugin/views/viewport"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,r){this.app=e,this.chart=this.app.chart,this.viewport_view=new i(e);var s=this;this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",operations:{edit_button:new t.ButtonIcon({icon:"fa-gear",tooltip:"Customize Chart",title:"Customize",onclick:function(){s._wait(s.chart,function(){s.app.go("editor")})}})}}),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var s=this;this.chart.on("change:title",function(){s._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_wait:function(e,t){if(e.editable())t();else{var n=this;this.app.modal.show({title:"Please wait!",body:"Your chart is currently being processed. Please wait and try again.",buttons:{Close:function(){n.app.modal.hide()},Retry:function(){n.app.modal.hide(),setTimeout(function(){n._wait(e,t)},n.app.config.get("query_timeout"))}}})}}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},add:function(e){var t=e.id,n={$title:$(this._template_tab(e)),$content:$(this._template_tab_content(e)),removable:e.ondel?!0:!1};this.list[t]=n,this.options.onnew?this.$nav.find("#new-tab").before(n.$title):this.$nav.append(n.$title),n.$content.append(e.$el),this.$content.append(n.$content),_.size(this.list)==1&&(n.$title.addClass("active"),n.$content.addClass("active"),this.first_tab=t);if(e.ondel){var r=this,i=n.$title.find("#delete");i.tooltip({title:"Delete this tab",placement:"bottom",container:r.$el}),i.on("click",function(){return i.tooltip("destroy"),r.$el.find(".tooltip").remove(),e.ondel(),!1})}e.onclick&&n.$title.on("click",function(){e.onclick()})},del:function(e){var t=this.list[e];t.$title.remove(),t.$content.remove(),delete t,this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab)},delRemovable:function(){for(var e in this.list){var t=this.list[e];t.removable&&this.del(e)}},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&this.list[e].$title.find("a").tab("show")},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.list[e].$title.find("#text");return t&&n.html(t),n.html()},_template:function(e){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="title-'+e.id+'">'+'<a title="" href="#tab-'+e.id+'" data-toggle="tab" data-original-title="">'+'<span id="text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="tab-'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("plugin/library/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null},events:{click:"_onclick",dblclick:"_ondblclick"},first:!0,initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(t));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=$("<tr></tr>")},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t){var n=$("<td></td>");t&&n.css("width",t),n.append(e),this.row.append(n)},append:function(e){this._commit(e)},prepend:function(e){this._commit(e,!0)},remove:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},removeAll:function(){this.$tbody.html(""),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t){this.remove(e),this.row.attr("id",e),t?this.$tbody.prepend(this.row):this.$tbody.append(this.row),this.row=$("<tr></tr>"),this.row_count++,this._refresh()},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="grid"><thead></thead><tbody style="cursor: pointer;"></tbody></table><tmessage>'+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({columns:[],initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(){s.group.set("key",s.group_key.value())}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.app.types.get(n);this.table.removeAll();var s={};for(var o in i.columns){var u=this.group.get(o);u||this.group.set(o,0);var a=i.columns[o],f=new t.Select.View({id:"select_"+o,gid:o,onchange:function(e){r.group.set(this.gid,e),r.chart.set("modified",!0)},value:u,wait:!0});this.table.add(a.title,"25%"),this.table.add(f.$el),this.table.append(o),s[o]=f}this.chart.state("wait","Loading metadata..."),this.app.datasets.request({id:e},function(e){r.columns=[];var t=e.metadata_column_types;for(var n in t)(t[n]=="int"||t[n]=="float")&&r.columns.push({label:"Column: "+(parseInt(n)+1)+" ["+t[n]+"]",value:n});for(var n in s)s[n].update(r.columns),s[n].show();r.chart.state("initialized","Metadata initialized...")})},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){var r=Backbone.View.extend({initialize:function(r){this.table_title=new t.Label({title:r.title}),this.table=new e.View({content:r.content});var i=$("<div/>");i.append(n.wrap(this.table_title.$el)),i.append(n.wrap(this.table.$el)),this.setElement(i)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.removeAll();for(var n in e)this._add(n,e[n],t)},_add:function(e,n,r){var i=null,s=n.type;switch(s){case"text":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"select":i=new t.Select.View({data:n.data,onchange:function(){r.set(e,i.value())}});break;case"slider":i=new t.Input({placeholder:n.placeholder,onchange:function(){r.set(e,i.value())}});break;case"separator":i=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(s!="separator"){r.get(e)||r.set(e,n.init),i.value(r.get(e));var o=$("<div/>");o.append(i.$el),o.append('<div class="toolParamHelp" style="font-size: 0.9em;">'+n.info+"</div>"),this.table.add('<span style="white-space: nowrap;">'+n.title+"</span>","25%"),this.table.add(o)}else this.table.add('<h6 style="white-space: nowrap;">'+n.title+":<h6/>"),this.table.add($("<div/>"));this.table.append(e)}});return{View:r}}),define("plugin/views/settings",["plugin/library/ui","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View({title:"Chart options:",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refreshTable()})},_refreshTable:function(){var e=this.chart.get("type");if(!e)return;var t=this.app.types.get(e);this.form.title(t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui-table","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(s,o){var u=this;this.app=s,this.chart=this.app.chart,this.options=i.merge(o,this.optionsDefault),this.portlet=new r.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new n.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){u.app.go("viewer"),u._saveChart()}}),back:new n.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){u.app.go("viewer"),u.app.storage.load()}})}}),this.table=new t.View({header:!1,onconfirm:function(e){u.chart.groups.length>0?u.app.modal.show({title:"Switching to another chart type?",body:"If you continue your settings and selections will be cleared.",buttons:{Cancel:function(){u.app.modal.hide()},Continue:function(){u.app.modal.hide(),u.table.value(e)}}}):u.table.value(e)},onchange:function(e){u.chart.groups.reset(),u.chart.settings.clear(),u.chart.set({type:e})},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"});var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),h.execute?this.table.add(h.title+" (requires processing)"):this.table.add(h.title),this.table.append(c)}this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=u._addGroupModel();u.tabs.show(e.id)}}),this.title=new n.Input({placeholder:"Chart title",onchange:function(){u.chart.set("title",u.title.value())}});var p=$("<div/>");p.append(i.wrap((new n.Label({title:"Provide a chart title:"})).$el)),p.append(i.wrap(this.title.$el)),p.append(i.wrap((new n.Label({title:"Select a chart type:"})).$el)),p.append(i.wrap(this.table.$el)),this.tabs.add({id:"main",title:"Start",$el:p}),this.settings=new a(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var u=this;this.chart.on("change:title",function(e){u._refreshTitle()}),this.chart.on("change:type",function(e){u.table.value(e.get("type"))}),this.chart.on("reset",function(e){u._resetChart()}),this.app.chart.on("redraw",function(e){u.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){u._addGroup(e)}),this.app.chart.groups.on("remove",function(e){u._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){u._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){u._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Chart data"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new o({id:i.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new u(this.app,{group:e}),r=t.chart.groups.length;this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey()},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",i.uuid()),this.chart.set("type","bardiagram"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.table.value(),title:this.title.value(),date:i.time()}),this.chart.groups.length==0&&this._addGroupModel();var e=this;this.chart.deferred(function(){e.app.storage.save(),e.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e3,query_timeout:500}})}),define("plugin/charts/_nvd3/config",[],function(){return{title:"",columns:{y:{title:"Values for y-axis"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},x_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"f",data:[{label:"-- Do not show values --",value:"hide"},{label:"Float",value:"f"},{label:"Exponent",value:"e"},{label:"Integer",value:"d"},{label:"Percentage",value:"p"},{label:"Rounded",value:"r"},{label:"SI-prefix",value:"s"}]},y_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/bardiagram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/histogram/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:!0,columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_tick:{init:".3"}}})}),define("plugin/charts/horizontal/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram (horizontal)",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/line/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/linewithfocus/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/piechart/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Pie chart"})}),define("plugin/charts/scatterplot/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/stackedarea/config",["plugin/charts/_nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/types",["plugin/charts/bardiagram/config","plugin/charts/histogram/config","plugin/charts/horizontal/config","plugin/charts/line/config","plugin/charts/linewithfocus/config","plugin/charts/piechart/config","plugin/charts/scatterplot/config","plugin/charts/stackedarea/config"],function(e,t,n,r,i,s,o,u){return Backbone.Model.extend({defaults:{bardiagram:e,horizontal:n,histogram:t,line:r,linewithfocus:i,piechart:s,scatterplot:o,stackedarea:u}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","plugin/library/ui","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c){return Backbone.View.extend({initialize:function(t){window.console.debug=function(){},this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new f,this.types=new c,this.chart=new l,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.viewer_view=new u(this),this.editor_view=new a(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el),this.storage.load()?(this.go("viewer"),this.chart.trigger("redraw")):this.go("editor")},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},execute:function(e){},onunload:function(){},log:function(e,t){console.log(e+" "+t)}})});
\ No newline at end of file
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/static/library/storage.js
--- a/config/plugins/visualizations/charts/static/library/storage.js
+++ b/config/plugins/visualizations/charts/static/library/storage.js
@@ -107,7 +107,7 @@
}
// reset status
- this.chart.state('ok', 'Loaded previously saved visualization.');
+ this.chart.state('ok', 'Loaded previously saved visualization...');
// reset modified flag
this.chart.set('modified', false);
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -19,15 +19,26 @@
},
// initialize
- initialize: function(options)
- {
+ initialize: function(options) {
this.groups = new Groups();
this.settings = new Backbone.Model();
+
+ // link status handler
+ var self = this;
+ this.on('change:state', function() {
+ // check status
+ var state = self.get('state');
+ if (self.ready(state)) {
+ self.trigger('ready');
+ }
+
+ // log
+ console.debug(state + ' : ' + self.get('state_info'));
+ });
},
// reset
- reset: function()
- {
+ reset: function() {
this.clear({silent: true}).set(this.defaults);
this.groups.reset();
this.settings.clear();
@@ -59,12 +70,25 @@
this.set('state', value);
},
- drawable: function() {
- return (this.get('state') == 'ok') || (this.get('state') == 'failed') || (this.get('state') == 'initialized');
+ ready: function() {
+ return (this.get('state') == 'ok') ||
+ (this.get('state') == 'failed') ||
+ (this.get('state') == 'initialized');
},
editable: function() {
- return (this.get('state') == 'ok') || (this.get('state') == 'failed');
+ return (this.get('state') == 'ok') ||
+ (this.get('state') == 'failed');
+ },
+
+ deferred: function(callback) {
+ if (!this.ready()) {
+ this.once('ready', function() {
+ callback();
+ });
+ } else {
+ callback();
+ }
}
});
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/static/views/editor.js
--- a/config/plugins/visualizations/charts/static/views/editor.js
+++ b/config/plugins/visualizations/charts/static/views/editor.js
@@ -16,6 +16,9 @@
// initialize
initialize: function(app, options)
{
+ // link this
+ var self = this;
+
// link application
this.app = app;
@@ -60,7 +63,6 @@
//
// table with chart types
//
- var self = this;
this.table = new Table.View({
header : false,
onconfirm : function(type) {
@@ -314,11 +316,15 @@
this._addGroupModel();
}
- // trigger redraw
- this.chart.trigger('redraw');
-
- // save
- this.app.storage.save();
+ // wait until chart is ready
+ var self = this;
+ this.chart.deferred(function() {
+ // save
+ self.app.storage.save();
+
+ // trigger redraw
+ self.chart.trigger('redraw');
+ });
}
});
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/static/views/viewport.js
--- a/config/plugins/visualizations/charts/static/views/viewport.js
+++ b/config/plugins/visualizations/charts/static/views/viewport.js
@@ -20,13 +20,12 @@
// create element
this.setElement($(this._template()));
+ // create svg element
+ this._create_svg();
+
// events
var self = this;
this.chart.on('redraw', function() {
- // create svg element
- self._create_svg();
-
- // initialize
self._draw(self.chart);
});
@@ -49,18 +48,13 @@
var state = self.chart.get('state');
switch (state) {
case 'ok':
- self.chart.trigger('drawable');
$info.hide();
break;
case 'failed':
- self.chart.trigger('drawable');
$icon.addClass('fa fa-warning');
break;
- case 'initialized':
- self.chart.trigger('drawable');
default:
$icon.addClass('fa fa-spinner fa-spin');
- break;
}
});
},
@@ -94,18 +88,9 @@
// link this
var self = this;
- // proceed once chart is drawable
- if (!chart.drawable()) {
- chart.off('drawable');
- chart.on('drawable', function() {
- self.chart.off('drawable');
- if (chart.drawable()) {
- self._draw(chart);
- }
- });
- return;
- }
-
+ // create svg element
+ this._create_svg();
+
// set chart state
chart.state('wait', 'Please wait...');
diff -r 20a8a71805a64f9718d03b986ae767c61f2cf035 -r 37fa3f5a47f8fc45755ac1ca758a852bb76ea999 config/plugins/visualizations/charts/templates/charts.mako
--- a/config/plugins/visualizations/charts/templates/charts.mako
+++ b/config/plugins/visualizations/charts/templates/charts.mako
@@ -36,7 +36,8 @@
// get configuration
var config = {
- root : '${root}'
+ root : '${root}',
+ debug : false
};
// link galaxy
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: Add the new repository type "Repository suite definition". This new type is associated with repositories that will contain a single file named repository_dependencies.xml that defines simple repository dependency relationships to a collection of repositories that contain related Galaxy utilities. The chemicaltoolbox repository is an example.
by commits-noreply@bitbucket.org 27 Mar '14
by commits-noreply@bitbucket.org 27 Mar '14
27 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/20a8a71805a6/
Changeset: 20a8a71805a6
User: greg
Date: 2014-03-27 21:03:53
Summary: Add the new repository type "Repository suite definition". This new type is associated with repositories that will contain a single file named repository_dependencies.xml that defines simple repository dependency relationships to a collection of repositories that contain related Galaxy utilities. The chemicaltoolbox repository is an example.
Affected #: 14 files
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -2346,9 +2346,15 @@
key_rd_dicts_to_be_processed=None,
all_repository_dependencies=None,
handled_key_rd_dicts=None )
- if str( repository.type ) != rt_util.TOOL_DEPENDENCY_DEFINITION:
+ if str( repository.type ) != rt_util.REPOSITORY_SUITE_DEFINITION:
# Handle messaging for resetting repository type to the optimal value.
- change_repository_type_message = tool_dependency_util.generate_message_for_repository_type_change( trans, repository )
+ change_repository_type_message = suc.generate_message_for_repository_type_change( trans, repository )
+ if change_repository_type_message:
+ message += change_repository_type_message
+ status = 'warning'
+ elif str( repository.type ) != rt_util.TOOL_DEPENDENCY_DEFINITION:
+ # Handle messaging for resetting repository type to the optimal value.
+ change_repository_type_message = suc.generate_message_for_repository_type_change( trans, repository )
if change_repository_type_message:
message += change_repository_type_message
status = 'warning'
@@ -2496,8 +2502,7 @@
"""
Handle a request from a Galaxy instance where the changeset_revision defined for a repository
in a dependency definition file is older than the changeset_revision associated with the installed
- repository. This will occur with repository's of type tool_dependency_definition, and this scenario
- will occur while repository dependency hierarchies are bing installed.
+ repository.
"""
name = kwd.get( 'name', None )
owner = kwd.get( 'owner', None )
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/galaxy/webapps/tool_shed/controllers/upload.py
--- a/lib/galaxy/webapps/tool_shed/controllers/upload.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/upload.py
@@ -123,16 +123,40 @@
istar = False
if istar:
ok, message, files_to_remove, content_alert_str, undesirable_dirs_removed, undesirable_files_removed = \
- self.upload_tar( trans, repository, tar, uploaded_file, upload_point, remove_repo_files_not_in_tar, commit_message, new_repo_alert )
+ self.upload_tar( trans,
+ repository,
+ tar,
+ uploaded_file,
+ upload_point,
+ remove_repo_files_not_in_tar,
+ commit_message,
+ new_repo_alert )
elif uploaded_directory:
ok, message, files_to_remove, content_alert_str, undesirable_dirs_removed, undesirable_files_removed = \
- self.upload_directory( trans, repository, uploaded_directory, upload_point, remove_repo_files_not_in_tar, commit_message, new_repo_alert )
+ self.upload_directory( trans,
+ repository,
+ uploaded_directory,
+ upload_point,
+ remove_repo_files_not_in_tar,
+ commit_message,
+ new_repo_alert )
else:
if ( isgzip or isbz2 ) and uncompress_file:
- uploaded_file_filename = commit_util.uncompress( repository, uploaded_file_name, uploaded_file_filename, isgzip=isgzip, isbz2=isbz2 )
- if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and uploaded_file_filename != suc.TOOL_DEPENDENCY_DEFINITION_FILENAME:
+ uploaded_file_filename = commit_util.uncompress( repository,
+ uploaded_file_name,
+ uploaded_file_filename,
+ isgzip=isgzip,
+ isbz2=isbz2 )
+ if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION and \
+ uploaded_file_filename != suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
ok = False
- message = 'Repositories of type <b>Tool dependency definition</b> can only contain a single file named <b>tool_dependencies.xml</b>.'
+ message = 'Repositories of type <b>Repository suite definition</b> can only contain a single file named '
+ message += '<b>repository_dependencies.xml</b>.'
+ elif repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and \
+ uploaded_file_filename != suc.TOOL_DEPENDENCY_DEFINITION_FILENAME:
+ ok = False
+ message = 'Repositories of type <b>Tool dependency definition</b> can only contain a single file named '
+ message += '<b>tool_dependencies.xml</b>.'
if ok:
if upload_point is not None:
full_path = os.path.abspath( os.path.join( repo_dir, upload_point, uploaded_file_filename ) )
@@ -140,10 +164,12 @@
full_path = os.path.abspath( os.path.join( repo_dir, uploaded_file_filename ) )
# Move some version of the uploaded file to the load_point within the repository hierarchy.
if uploaded_file_filename in [ suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME ]:
- # Inspect the contents of the file to see if changeset_revision values are missing and if so, set them appropriately.
- altered, root_elem, error_message = commit_util.handle_repository_dependencies_definition( trans,
- uploaded_file_name,
- unpopulate=False )
+ # Inspect the contents of the file to see if changeset_revision values are missing and if so,
+ # set them appropriately.
+ altered, root_elem, error_message = \
+ commit_util.handle_repository_dependencies_definition( trans,
+ uploaded_file_name,
+ unpopulate=False )
if error_message:
ok = False
message = error_message
@@ -153,10 +179,12 @@
shutil.move( tmp_filename, full_path )
else:
shutil.move( uploaded_file_name, full_path )
- elif uploaded_file_filename in [ suc.TOOL_DEPENDENCY_DEFINITION_FILENAME ]:
- # Inspect the contents of the file to see if it defines a complex repository dependency definition whose changeset_revision values
- # are missing and if so, set them appropriately.
- altered, root_elem, error_message = commit_util.handle_tool_dependencies_definition( trans, uploaded_file_name )
+ elif uploaded_file_filename in [ suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME,
+ suc.TOOL_DEPENDENCY_DEFINITION_FILENAME ]:
+ # Inspect the contents of the file to see if changeset_revision values are
+ # missing and if so, set them appropriately.
+ altered, root_elem, error_message = \
+ commit_util.handle_tool_dependencies_definition( trans, uploaded_file_name )
if error_message:
ok = False
message = error_message
@@ -170,8 +198,8 @@
else:
shutil.move( uploaded_file_name, full_path )
if ok:
- # See if any admin users have chosen to receive email alerts when a repository is updated. If so, check every uploaded file to ensure
- # content is appropriate.
+ # See if any admin users have chosen to receive email alerts when a repository is updated.
+ # If so, check every uploaded file to ensure content is appropriate.
check_contents = commit_util.check_file_contents_for_email_alerts( trans )
if check_contents and os.path.isfile( full_path ):
content_alert_str = commit_util.check_file_content_for_html_and_images( full_path )
@@ -182,8 +210,9 @@
full_path = full_path.encode( 'ascii', 'replace' )
commands.commit( repo.ui, repo, full_path, user=trans.user.username, message=commit_message )
if full_path.endswith( 'tool_data_table_conf.xml.sample' ):
- # Handle the special case where a tool_data_table_conf.xml.sample file is being uploaded by parsing the file and adding new entries
- # to the in-memory trans.app.tool_data_tables dictionary.
+ # Handle the special case where a tool_data_table_conf.xml.sample file is being uploaded
+ # by parsing the file and adding new entries to the in-memory trans.app.tool_data_tables
+ # dictionary.
error, error_message = tool_util.handle_sample_tool_data_table_conf_file( trans.app, full_path )
if error:
message = '%s<br/>%s' % ( message, error_message )
@@ -212,43 +241,54 @@
else:
source_type = "file"
source = uploaded_file_filename
- message = "The %s <b>%s</b> has been successfully%suploaded to the repository. " % ( source_type, source, uncompress_str )
+ message = "The %s <b>%s</b> has been successfully%suploaded to the repository. " % \
+ ( source_type, source, uncompress_str )
if istar and ( undesirable_dirs_removed or undesirable_files_removed ):
items_removed = undesirable_dirs_removed + undesirable_files_removed
- message += " %d undesirable items (.hg .svn .git directories, .DS_Store, hgrc files, etc) were removed from the archive. " % items_removed
+ message += " %d undesirable items (.hg .svn .git directories, .DS_Store, hgrc files, etc) " % items_removed
+ message += "were removed from the archive. "
if istar and remove_repo_files_not_in_tar and files_to_remove:
if upload_point is not None:
- message += " %d files were removed from the repository relative to the selected upload point '%s'. " % ( len( files_to_remove ), upload_point )
+ message += " %d files were removed from the repository relative to the selected upload point '%s'. " % \
+ ( len( files_to_remove ), upload_point )
else:
message += " %d files were removed from the repository root. " % len( files_to_remove )
kwd[ 'message' ] = message
metadata_util.set_repository_metadata_due_to_new_tip( trans, repository, content_alert_str=content_alert_str, **kwd )
if repository.metadata_revisions:
- # A repository's metadata revisions are order descending by update_time, so the zeroth revision will be the tip just after an upload.
- metadata_dict = repository.metadata_revisions[0].metadata
+ # A repository's metadata revisions are order descending by update_time, so the zeroth revision
+ # will be the tip just after an upload.
+ metadata_dict = repository.metadata_revisions[ 0 ].metadata
else:
metadata_dict = {}
- if str( repository.type ) != rt_util.TOOL_DEPENDENCY_DEFINITION:
- change_repository_type_message = tool_dependency_util.generate_message_for_repository_type_change( trans, repository )
+ if str( repository.type ) not in [ rt_util.REPOSITORY_SUITE_DEFINITION,
+ rt_util.TOOL_DEPENDENCY_DEFINITION ]:
+ change_repository_type_message = suc.generate_message_for_repository_type_change( trans, repository )
if change_repository_type_message:
message += change_repository_type_message
status = 'warning'
else:
- # Provide a warning message if a tool_dependencies.xml file is provided, but tool dependencies weren't loaded due to a requirement tag mismatch
- # or some other problem. Tool dependency definitions can define orphan tool dependencies (no relationship to any tools contained in the repository),
- # so warning messages are important because orphans are always valid. The repository owner must be warned in case they did not intend to define an
- # orphan dependency, but simply provided incorrect information (tool shed, name owner, changeset_revision) for the definition.
- orphan_message = tool_dependency_util.generate_message_for_orphan_tool_dependencies( trans, repository, metadata_dict )
+ # Provide a warning message if a tool_dependencies.xml file is provided, but tool dependencies
+ # weren't loaded due to a requirement tag mismatch or some other problem. Tool dependency
+ # definitions can define orphan tool dependencies (no relationship to any tools contained in the
+ # repository), so warning messages are important because orphans are always valid. The repository
+ # owner must be warned in case they did not intend to define an orphan dependency, but simply
+ # provided incorrect information (tool shed, name owner, changeset_revision) for the definition.
+ orphan_message = tool_dependency_util.generate_message_for_orphan_tool_dependencies( trans,
+ repository,
+ metadata_dict )
if orphan_message:
message += orphan_message
status = 'warning'
# Handle messaging for invalid tool dependencies.
- invalid_tool_dependencies_message = tool_dependency_util.generate_message_for_invalid_tool_dependencies( metadata_dict )
+ invalid_tool_dependencies_message = \
+ tool_dependency_util.generate_message_for_invalid_tool_dependencies( metadata_dict )
if invalid_tool_dependencies_message:
message += invalid_tool_dependencies_message
status = 'error'
# Handle messaging for invalid repository dependencies.
- invalid_repository_dependencies_message = repository_dependency_util.generate_message_for_invalid_repository_dependencies( metadata_dict )
+ invalid_repository_dependencies_message = \
+ repository_dependency_util.generate_message_for_invalid_repository_dependencies( metadata_dict )
if invalid_repository_dependencies_message:
message += invalid_repository_dependencies_message
status = 'error'
@@ -279,7 +319,8 @@
message=message,
status=status )
- def upload_directory( self, trans, repository, uploaded_directory, upload_point, remove_repo_files_not_in_tar, commit_message, new_repo_alert ):
+ def upload_directory( self, trans, repository, uploaded_directory, upload_point, remove_repo_files_not_in_tar,
+ commit_message, new_repo_alert ):
repo_dir = repository.repo_path( trans.app )
repo = hg.repository( suc.get_configured_ui(), repo_dir )
undesirable_dirs_removed = 0
@@ -292,7 +333,9 @@
for root, dirs, files in os.walk( uploaded_directory ):
for uploaded_file in files:
relative_path = os.path.normpath( os.path.join( os.path.relpath( root, uploaded_directory ), uploaded_file ) )
- if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION:
+ if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION:
+ ok = os.path.basename( uploaded_file ) == suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME
+ elif repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION:
ok = os.path.basename( uploaded_file ) == suc.TOOL_DEPENDENCY_DEFINITION_FILENAME
else:
ok = os.path.basename( uploaded_file ) not in commit_util.UNDESIRABLE_FILES
@@ -307,10 +350,12 @@
if ok:
uploaded_file_name = os.path.abspath( os.path.join( root, uploaded_file ) )
if os.path.split( uploaded_file_name )[ -1 ] == suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
- # Inspect the contents of the file to see if changeset_revision values are missing and if so, set them appropriately.
- altered, root_elem, error_message = commit_util.handle_repository_dependencies_definition( trans,
- uploaded_file_name,
- unpopulate=False )
+ # Inspect the contents of the file to see if changeset_revision values are missing and
+ # if so, set them appropriately.
+ altered, root_elem, error_message = \
+ commit_util.handle_repository_dependencies_definition( trans,
+ uploaded_file_name,
+ unpopulate=False )
if error_message:
return False, error_message, [], '', [], []
elif altered:
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
--- a/lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
+++ b/lib/galaxy/webapps/tool_shed/framework/middleware/hg.py
@@ -120,8 +120,28 @@
for row in result_set:
# Should only be 1 row...
repository_type = str( row[ 'type' ] )
- if repository_type == rt_util.TOOL_DEPENDENCY_DEFINITION:
- # Handle repositories of type tool_dependency_definition, which can only contain a single file named tool_dependencies.xml.
+ if repository_type == rt_util.REPOSITORY_SUITE_DEFINITION:
+ # Handle repositories of type repository_suite_definition, which can only contain a single
+ # file named repository_dependencies.xml.
+ for entry in changeset_groups:
+ if len( entry ) == 2:
+ # We possibly found an altered file entry.
+ filename, change_list = entry
+ if filename and isinstance( filename, str ):
+ if filename == suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
+ # Make sure the any complex repository dependency definitions contain valid <repository> tags.
+ is_valid, error_msg = commit_util.repository_tags_are_valid( filename, change_list )
+ if not is_valid:
+ log.debug( error_msg )
+ return self.__display_exception_remotely( start_response, error_msg )
+ else:
+ msg = "Only a single file named repository_dependencies.xml can be pushed to a repository "
+ msg += "of type 'Repository suite definition'."
+ log.debug( msg )
+ return self.__display_exception_remotely( start_response, msg )
+ elif repository_type == rt_util.TOOL_DEPENDENCY_DEFINITION:
+ # Handle repositories of type tool_dependency_definition, which can only contain a single
+ # file named tool_dependencies.xml.
for entry in changeset_groups:
if len( entry ) == 2:
# We possibly found an altered file entry.
@@ -134,20 +154,24 @@
log.debug( error_msg )
return self.__display_exception_remotely( start_response, error_msg )
else:
- msg = "Only a single file named tool_dependencies.xml can be pushed to a repository of type 'Tool dependency definition'."
+ msg = "Only a single file named tool_dependencies.xml can be pushed to a repository "
+ msg += "of type 'Tool dependency definition'."
log.debug( msg )
return self.__display_exception_remotely( start_response, msg )
else:
- # If the changeset includes changes to dependency definition files, make sure tag sets are not missing "toolshed" or
- # "changeset_revision" attributes since automatically populating them is not supported when pushing from the command line.
- # These attributes are automatically populated only when using the tool shed upload utility.
+ # If the changeset includes changes to dependency definition files, make sure tag sets
+ # are not missing "toolshed" or "changeset_revision" attributes since automatically populating
+ # them is not supported when pushing from the command line. These attributes are automatically
+ # populated only when using the tool shed upload utility.
for entry in changeset_groups:
if len( entry ) == 2:
# We possibly found an altered file entry.
filename, change_list = entry
if filename and isinstance( filename, str ):
- if filename in [ suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME, suc.TOOL_DEPENDENCY_DEFINITION_FILENAME ]:
- # We check both files since tool dependency definitions files can contain complex repository dependency definitions.
+ if filename in [ suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME,
+ suc.TOOL_DEPENDENCY_DEFINITION_FILENAME ]:
+ # We check both files since tool dependency definitions files can contain complex
+ # repository dependency definitions.
is_valid, error_msg = commit_util.repository_tags_are_valid( filename, change_list )
if not is_valid:
log.debug( error_msg )
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/galaxy/webapps/tool_shed/model/__init__.py
--- a/lib/galaxy/webapps/tool_shed/model/__init__.py
+++ b/lib/galaxy/webapps/tool_shed/model/__init__.py
@@ -194,6 +194,8 @@
return False
def can_change_type_to( self, app, new_type_label ):
+ if self.type == new_type_label:
+ return False
if self.can_change_type( app ):
new_type = app.repository_types_registry.get_class_by_label( new_type_label )
if new_type.is_valid_for_type( app, self ):
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/galaxy_install/repository_util.py
--- a/lib/tool_shed/galaxy_install/repository_util.py
+++ b/lib/tool_shed/galaxy_install/repository_util.py
@@ -194,7 +194,7 @@
if not repository_metadata:
# The received changeset_revision is no longer installable, so get the next changeset_revision
# in the repository's changelog. This generally occurs only with repositories of type
- # tool_dependency_definition.
+ # repository_suite_definition or tool_dependency_definition.
next_downloadable_changeset_revision = \
suc.get_next_downloadable_changeset_revision( repository,repo, changeset_revision )
if next_downloadable_changeset_revision:
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -211,12 +211,13 @@
tool_dependency_name=package_name,
tool_dependency_version=package_version )
if os.path.exists( dependent_install_dir ):
- # The install manager handles tool migration stages and the sync_database_with_file_system() method handles two
- # scenarios: (1) where a Galaxy file system environment related to installed tool shed repositories and tool dependencies
- # has somehow (over time )gotten out of sync with the Galaxy database tables associated with these installed items, and
- # (2) the Tool Shed's install and test framework which installs repositories in 2 stages, those of type
- # tool_dependency_definition followed by those containing valid tools and tool functional test components. Neither of
- # these scenarios apply when the install manager is running.
+ # The install manager handles tool migration stages and the sync_database_with_file_system()
+ # method handles two scenarios: (1) where a Galaxy file system environment related to installed
+ # Tool Shed repositories and tool dependencies has somehow gotten out of sync with the Galaxy
+ # database tables associated with these installed items, and (2) the Tool Shed's install and test
+ # framework which installs repositories in 2 stages, those of type tool_dependency_definition
+ # followed by those containing valid tools and tool functional test components. Neither of these
+ # scenarios apply when the install manager is running.
if from_install_manager:
can_install_tool_dependency = True
else:
@@ -334,12 +335,13 @@
tool_dependency_name=package_name,
tool_dependency_version=package_version )
if os.path.exists( install_dir ):
- # The install manager handles tool migration stages and the sync_database_with_file_system() method handles two
- # scenarios: (1) where a Galaxy file system environment related to installed tool shed repositories and tool dependencies
- # has somehow (over time )gotten out of sync with the Galaxy database tables associated with these installed items, and
- # (2) the Tool Shed's install and test framework which installs repositories in 2 stages, those of type
- # tool_dependency_definition followed by those containing valid tools and tool functional test components. Neither of
- # these scenarios apply when the install manager is running.
+ # The install manager handles tool migration stages and the sync_database_with_file_system()
+ # method handles two scenarios: (1) where a Galaxy file system environment related to installed
+ # Tool Shed repositories and tool dependencies has somehow gotten out of sync with the Galaxy
+ # database tables associated with these installed items, and (2) the Tool Shed's install and test
+ # framework which installs repositories in 2 stages, those of type tool_dependency_definition
+ # followed by those containing valid tools and tool functional test components. Neither of these
+ # scenarios apply when the install manager is running.
if from_install_manager:
can_install_tool_dependency = True
else:
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -175,7 +175,8 @@
log.exception( str( e ) )
return 'unknown'
else:
- # Here repository.type must be rt_util.TOOL_DEPENDENCY_DEFINITION.
+ # Here repository.type must be either rt_util.REPOSITORY_SUITE_DEFINITION or
+ # rt_util.TOOL_DEPENDENCY_DEFINITION.
try:
if len( repository.metadata_revisions ) > 0:
displayed_metadata_revision = repository.metadata_revisions[ -1 ]
@@ -1771,7 +1772,7 @@
"""
Inspect the latest downloadable changeset revision for the received repository to see if it
includes at least 1 tool that has at least 1 failing test. This will filter out repositories
- of type tool_dependency_definition.
+ of type repository_suite_definition and tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata_if_it_includes_tools( trans, repository )
if repository_metadata \
@@ -1787,7 +1788,8 @@
Inspect the latest downloadable changeset revision for the received repository to see if it
includes tools that are either missing functional tests or functional test data. If the
changset revision includes tools but is missing tool test components, return the changeset
- revision hash. This will filter out repositories of type tool_dependency_definition.
+ revision hash. This will filter out repositories of type repository_suite_definition and
+ tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata_if_it_includes_tools( trans, repository )
if repository_metadata and repository_metadata.missing_test_components:
@@ -1797,7 +1799,8 @@
def filter_by_latest_downloadable_changeset_revision_that_has_no_failing_tool_tests( trans, repository ):
"""
Inspect the latest downloadable changeset revision for the received repository to see if it
- includes tools with no failing tests. This will filter out repositories of type tool_dependency_definition.
+ includes tools with no failing tests. This will filter out repositories of type repository_suite_definition
+ and tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata_if_it_includes_tools( trans, repository )
if repository_metadata is not None and \
@@ -1809,7 +1812,8 @@
def filter_by_latest_metadata_changeset_revision_that_has_invalid_tools( trans, repository ):
"""
Inspect the latest changeset revision with associated metadata for the received repository
- to see if it has invalid tools. This will filter out repositories of type tool_dependency_definition.
+ to see if it has invalid tools. This will filter out repositories of type repository_suite_definition
+ and tool_dependency_definition.
"""
repository_metadata = get_latest_repository_metadata_if_it_includes_invalid_tools( trans, repository )
if repository_metadata is not None:
@@ -1820,7 +1824,7 @@
"""
Inspect the latest downloadable changeset revision for the received repository to see if
it has tool test installation errors. This will return repositories of type unrestricted
- as well as type tool_dependency_definition.
+ as well as types repository_suite_definition and tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata_if_it_has_test_install_errors( trans, repository )
# Filter further by eliminating repositories that are missing test components.
@@ -1831,7 +1835,8 @@
def filter_by_latest_downloadable_changeset_revision_with_skip_tests_checked( trans, repository ):
"""
Inspect the latest downloadable changeset revision for the received repository to see if skip tests
- is checked. This will return repositories of type unrestricted as well as type tool_dependency_definition.
+ is checked. This will return repositories of type unrestricted as well as types repository_suite_definition
+ and tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata( trans, repository )
# The skip_tool_tests attribute is a SkipToolTest table mapping backref to the RepositoryMetadata table.
@@ -1842,7 +1847,8 @@
def get_latest_downloadable_repository_metadata( trans, repository ):
"""
Return the latest downloadable repository_metadata record for the received repository. This will
- return repositories of type unrestricted as well as type tool_dependency_definition.
+ return repositories of type unrestricted as well as types repository_suite_definition and
+ tool_dependency_definition.
"""
encoded_repository_id = trans.security.encode_id( repository.id )
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
@@ -1867,7 +1873,8 @@
def get_latest_downloadable_repository_metadata_if_it_includes_tools( trans, repository ):
"""
Return the latest downloadable repository_metadata record for the received repository if its
- includes_tools attribute is True. This will filter out repositories of type tool_dependency_definition.
+ includes_tools attribute is True. This will filter out repositories of type repository_suite_definition
+ and tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata( trans, repository )
if repository_metadata is not None and repository_metadata.includes_tools:
@@ -1878,7 +1885,7 @@
"""
Return the latest downloadable repository_metadata record for the received repository if its
test_install_error attribute is True. This will return repositories of type unrestricted as
- well as type tool_dependency_definition.
+ well as types repository_suite_definition and tool_dependency_definition.
"""
repository_metadata = get_latest_downloadable_repository_metadata( trans, repository )
if repository_metadata is not None and repository_metadata.test_install_error:
@@ -1888,7 +1895,8 @@
def get_latest_repository_metadata( trans, repository ):
"""
Return the latest repository_metadata record for the received repository if it exists. This will
- return repositories of type unrestricted as well as type tool_dependency_definition.
+ return repositories of type unrestricted as well as types repository_suite_definition and
+ tool_dependency_definition.
"""
encoded_repository_id = trans.security.encode_id( repository.id )
repo = hg.repository( suc.get_configured_ui(), repository.repo_path( trans.app ) )
@@ -1908,7 +1916,8 @@
def get_latest_repository_metadata_if_it_includes_invalid_tools( trans, repository ):
"""
Return the latest repository_metadata record for the received repository that contains invalid
- tools if one exists. This will filter out repositories of type tool_dependency_definition.
+ tools if one exists. This will filter out repositories of type repository_suite_definition and
+ tool_dependency_definition.
"""
repository_metadata = get_latest_repository_metadata( trans, repository )
if repository_metadata is not None:
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/repository_types/registry.py
--- a/lib/tool_shed/repository_types/registry.py
+++ b/lib/tool_shed/repository_types/registry.py
@@ -1,5 +1,6 @@
import logging
import unrestricted
+import repository_suite_definition
import tool_dependency_definition
from galaxy.util.odict import odict
@@ -11,6 +12,7 @@
def __init__( self ):
self.repository_types_by_label = odict()
self.repository_types_by_label[ 'unrestricted' ] = unrestricted.Unrestricted()
+ self.repository_types_by_label[ 'repository_suite_definition' ] = repository_suite_definition.RepositorySuiteDefinition()
self.repository_types_by_label[ 'tool_dependency_definition' ] = tool_dependency_definition.ToolDependencyDefinition()
def get_class_by_label( self, label ):
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/repository_types/repository_suite_definition.py
--- /dev/null
+++ b/lib/tool_shed/repository_types/repository_suite_definition.py
@@ -0,0 +1,41 @@
+import logging
+from tool_shed.repository_types.metadata import TipOnly
+import tool_shed.repository_types.util as rt_util
+import tool_shed.util.shed_util_common as suc
+
+from galaxy import eggs
+eggs.require( 'mercurial' )
+from mercurial import hg
+from mercurial import ui
+
+log = logging.getLogger( __name__ )
+
+class RepositorySuiteDefinition( TipOnly ):
+
+ def __init__( self ):
+ self.type = rt_util.REPOSITORY_SUITE_DEFINITION
+ self.label = 'Repository suite definition'
+ self.valid_file_names = [ 'repository_dependencies.xml' ]
+
+ def is_valid_for_type( self, app, repository, revisions_to_check=None ):
+ """
+ Inspect the received repository's contents to determine if they abide by the rules defined for
+ the contents of this type. If the received revisions_to_check is a list of changeset revisions,
+ then inspection will be restricted to the revisions in the list.
+ """
+ repo = hg.repository( ui.ui(), repository.repo_path( app ) )
+ if revisions_to_check:
+ changeset_revisions = revisions_to_check
+ else:
+ changeset_revisions = repo.changelog
+ for changeset in changeset_revisions:
+ changeset_revision = str( repo.changectx( changeset ) )
+ ctx = repo.changectx( changeset )
+ # Inspect all files in the changeset (in sorted order) to make sure there is only one and it
+ # is named repository_dependencies.xml.
+ files_changed_in_changeset = ctx.files()
+ for file_path in files_changed_in_changeset:
+ file_name = suc.strip_path( file_path )
+ if file_name not in self.valid_file_names:
+ return False
+ return True
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/repository_types/util.py
--- a/lib/tool_shed/repository_types/util.py
+++ b/lib/tool_shed/repository_types/util.py
@@ -4,6 +4,7 @@
log = logging.getLogger( __name__ )
UNRESTRICTED = 'unrestricted'
+REPOSITORY_SUITE_DEFINITION = 'repository_suite_definition'
TOOL_DEPENDENCY_DEFINITION = 'tool_dependency_definition'
types = [ UNRESTRICTED, TOOL_DEPENDENCY_DEFINITION ]
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/util/commit_util.py
--- a/lib/tool_shed/util/commit_util.py
+++ b/lib/tool_shed/util/commit_util.py
@@ -50,6 +50,9 @@
if member.name in [ 'hgrc' ]:
message = "Uploaded archives cannot contain hgrc files."
return False, message
+ if repository.type == rt_util.REPOSITORY_SUITE_DEFINITION and member.name != suc.REPOSITORY_DEPENDENCY_DEFINITION_FILENAME:
+ message = 'Repositories of type <b>Repsoitory suite definition</b> can contain only a single file named <b>repository_dependencies.xml</b>.'
+ return False, message
if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION and member.name != suc.TOOL_DEPENDENCY_DEFINITION_FILENAME:
message = 'Repositories of type <b>Tool dependency definition</b> can contain only a single file named <b>tool_dependencies.xml</b>.'
return False, message
@@ -478,8 +481,8 @@
def repository_tag_is_valid( filename, line ):
"""
- Checks changes made to <repository> tags in a dependency definition file being pushed to the tool shed from the command line to ensure that
- all required attributes exist.
+ Checks changes made to <repository> tags in a dependency definition file being pushed to the
+ Tool Shed from the command line to ensure that all required attributes exist.
"""
required_attributes = [ 'toolshed', 'name', 'owner', 'changeset_revision' ]
defined_attributes = line.split()
@@ -490,15 +493,17 @@
defined = True
break
if not defined:
- error_msg = 'The %s file contains a <repository> tag that is missing the required attribute %s. ' % ( filename, required_attribute )
- error_msg += 'Automatically populating dependency definition attributes occurs only when using the tool shed upload utility. '
+ error_msg = 'The %s file contains a <repository> tag that is missing the required attribute %s. ' % \
+ ( filename, required_attribute )
+ error_msg += 'Automatically populating dependency definition attributes occurs only when using '
+ error_msg += 'the Tool Shed upload utility. '
return False, error_msg
return True, ''
def repository_tags_are_valid( filename, change_list ):
"""
- Make sure the any complex repository dependency definitions contain valid <repository> tags when pushing changes to the tool shed on the command
- line.
+ Make sure the any complex repository dependency definitions contain valid <repository> tags when pushing
+ changes to the tool shed on the command line.
"""
tag = '<repository'
for change_dict in change_list:
@@ -519,8 +524,9 @@
def unpack_chunks( hg_unbundle10_obj ):
"""
- This method provides a generator of parsed chunks of a "group" in a mercurial unbundle10 object which is created when a changeset that is pushed
- to a tool shed repository using hg push from the command line is read using readbundle.
+ This method provides a generator of parsed chunks of a "group" in a mercurial unbundle10 object which
+ is created when a changeset that is pushed to a Tool Shed repository using hg push from the command line
+ is read using readbundle.
"""
while True:
length, = struct.unpack( '>l', readexactly( hg_unbundle10_obj, 4 ) )
@@ -538,8 +544,9 @@
def unpack_groups( hg_unbundle10_obj ):
"""
- This method provides a generator of parsed groups from a mercurial unbundle10 object which is created when a changeset that is pushed
- to a tool shed repository using hg push from the command line is read using readbundle.
+ This method provides a generator of parsed groups from a mercurial unbundle10 object which is
+ created when a changeset that is pushed to a Tool Shed repository using hg push from the command
+ line is read using readbundle.
"""
# Process the changelog group.
yield [ chunk for chunk in unpack_chunks( hg_unbundle10_obj ) ]
@@ -556,8 +563,8 @@
def unpack_patches( hg_unbundle10_obj, remaining ):
"""
- This method provides a generator of patches from the data field in a chunk. As there is no delimiter for this data field, a length argument is
- required.
+ This method provides a generator of patches from the data field in a chunk. As there is no delimiter
+ for this data field, a length argument is required.
"""
while remaining >= 12:
start, end, blocklen = struct.unpack( '>lll', readexactly( hg_unbundle10_obj, 12 ) )
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -333,6 +333,25 @@
# Don't include the changeset_revision in clone urls.
return url_join( toolshed, 'repos', owner, name )
+def generate_message_for_repository_type_change( trans, repository ):
+ message = ''
+ if repository.can_change_type_to( trans.app, rt_util.REPOSITORY_SUITE_DEFINITION ):
+ repository_suite_definition_type_class = \
+ trans.app.repository_types_registry.get_class_by_label( rt_util.REPOSITORY_SUITE_DEFINITION )
+ message += "This repository currently contains a single file named <b>%s</b>. If the intent of this repository is " % \
+ REPOSITORY_DEPENDENCY_DEFINITION_FILENAME
+ message += "to define relationships to a collection of repositories that contain related Galaxy utilities with "
+ message += "no plans to add additional files, then consider setting its type to <b>%s</b>.<br/>" % \
+ repository_suite_definition_type_class.label
+ elif repository.can_change_type_to( trans.app, rt_util.TOOL_DEPENDENCY_DEFINITION ):
+ tool_dependency_definition_type_class = \
+ trans.app.repository_types_registry.get_class_by_label( rt_util.TOOL_DEPENDENCY_DEFINITION )
+ message += "This repository currently contains a single file named <b>%s</b>. If additional files will " % \
+ TOOL_DEPENDENCY_DEFINITION_FILENAME
+ message += "not be added to this repository, consider setting its type to <b>%s</b>.<br/>" % \
+ tool_dependency_definition_type_class.label
+ return message
+
def generate_repository_info_elem( tool_shed, repository_name, changeset_revision, owner, parent_elem=None, **kwd ):
"""Create and return an ElementTree repository info Element."""
if parent_elem is None:
@@ -880,15 +899,17 @@
a page. When called from either the Tool Shed or Galaxy API, order is False.
"""
if trans.webapp.name == 'tool_shed':
- # When called from the Tool Shed API, the metadata is reset on all repositories of type tool_dependency_definition in addition
- # to other selected repositories.
+ # When called from the Tool Shed API, the metadata is reset on all repositories of types
+ # repository_suite_definition and tool_dependency_definition in addition to other selected
+ # repositories.
if my_writable:
username = trans.user.username
clause_list = []
for repository in trans.sa_session.query( trans.model.Repository ) \
.filter( trans.model.Repository.table.c.deleted == False ):
- # Always reset metadata on all repositories of type tool_dependency_definition.
- if repository.type == rt_util.TOOL_DEPENDENCY_DEFINITION:
+ # Always reset metadata on all repositories of types repository_suite_definition and
+ # tool_dependency_definition.
+ if repository.type in [ rt_util.REPOSITORY_SUITE_DEFINITION, rt_util.TOOL_DEPENDENCY_DEFINITION ]:
clause_list.append( trans.model.Repository.table.c.id == repository.id )
else:
allow_push = repository.allow_push( trans.app )
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 lib/tool_shed/util/tool_dependency_util.py
--- a/lib/tool_shed/util/tool_dependency_util.py
+++ b/lib/tool_shed/util/tool_dependency_util.py
@@ -198,17 +198,6 @@
message += set_environment_orphans_str
return message
-def generate_message_for_repository_type_change( trans, repository ):
- message = ''
- if repository.can_change_type_to( trans.app, rt_util.TOOL_DEPENDENCY_DEFINITION ):
- tool_dependency_definition_type_class = \
- trans.app.repository_types_registry.get_class_by_label( rt_util.TOOL_DEPENDENCY_DEFINITION )
- message += "This repository currently contains a single file named <b>%s</b>. If additional files will " % \
- suc.TOOL_DEPENDENCY_DEFINITION_FILENAME
- message += "not be added to this repository, then it's type should be set to <b>%s</b>.<br/>" % \
- tool_dependency_definition_type_class.label
- return message
-
def get_download_url_for_platform( url_templates, platform_info_dict ):
'''
Compare the dict returned by get_platform_info() with the values specified in the url_template element. Return
@@ -583,7 +572,7 @@
"""
# This method should be reached very rarely. It implies that either the Galaxy environment became corrupted (i.e.,
# the database records for installed tool dependencies is not synchronized with tool dependencies on disk) or the Tool
- # Shed's install and test framework is running. The Tool Shed's install and test framework which installs repositories
+ # Shed's install and test framework is running. The Tool Shed's install and test framework installs repositories
# in 2 stages, those of type tool_dependency_definition followed by those containing valid tools and tool functional
# test components.
log.debug( "Synchronizing the database with the file system..." )
diff -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 -r 20a8a71805a64f9718d03b986ae767c61f2cf035 templates/webapps/tool_shed/repository/common.mako
--- a/templates/webapps/tool_shed/repository/common.mako
+++ b/templates/webapps/tool_shed/repository/common.mako
@@ -191,6 +191,9 @@
%if util.UNRESTRICTED in repository_types:
<li><b>Unrestricted</b> - contents can be any set of valid Galaxy utilities or files
%endif
+ %if util.REPOSITORY_SUITE_DEFINITION in repository_types:
+ <li><b>Repository suite definition</b> - contents will always be restricted to one file named repository_dependencies.xml
+ %endif
%if util.TOOL_DEPENDENCY_DEFINITION in repository_types:
<li><b>Tool dependency definition</b> - contents will always be restricted to one file named tool_dependencies.xml
%endif
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: Fix: use preventDefault when trying to add display or visualizations to galaxy.frame
by commits-noreply@bitbucket.org 27 Mar '14
by commits-noreply@bitbucket.org 27 Mar '14
27 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f4d81f13120a/
Changeset: f4d81f13120a
User: carlfeberhard
Date: 2014-03-27 18:19:11
Summary: Fix: use preventDefault when trying to add display or visualizations to galaxy.frame
Affected #: 4 files
diff -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 static/scripts/mvc/dataset/hda-base.js
--- a/static/scripts/mvc/dataset/hda-base.js
+++ b/static/scripts/mvc/dataset/hda-base.js
@@ -193,14 +193,17 @@
// add frame manager option onclick event
var self = this;
- displayBtnData.onclick = function(){
+ displayBtnData.onclick = function( ev ){
+ console.debug( 'displayBtn onclick', ev );
if( Galaxy.frame && Galaxy.frame.active ){
Galaxy.frame.add({
title : "Data Viewer: " + self.model.get('name'),
type : "url",
content : self.urls.display
});
+ ev.preventDefault();
}
+
};
}
displayBtnData.faIcon = 'fa-eye';
diff -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 static/scripts/mvc/dataset/hda-edit.js
--- a/static/scripts/mvc/dataset/hda-edit.js
+++ b/static/scripts/mvc/dataset/hda-edit.js
@@ -256,13 +256,14 @@
} else {
var popup_menu_options = [];
_.each( visualizations, function( linkData ) {
- linkData.func = function(){
- if( Galaxy.frame.active ){
+ linkData.func = function( ev ){
+ if( Galaxy.frame && Galaxy.frame.active ){
Galaxy.frame.add({
title : "Visualization",
type : "url",
content : linkData.href
});
+ ev.preventDefault();
return false;
}
return true;
diff -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 static/scripts/packed/mvc/dataset/hda-base.js
--- a/static/scripts/packed/mvc/dataset/hda-base.js
+++ b/static/scripts/packed/mvc/dataset/hda-base.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model","mvc/base-mvc"],function(d,b){var c=Backbone.View.extend(b.LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(f){if(f.logger){this.logger=this.model.logger=f.logger}this.log(this+".initialize:",f);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.linkTarget=f.linkTarget||"_blank";this.selectable=f.selectable||false;this.selected=f.selected||false;this.expanded=f.expanded||false;this.draggable=f.draggable||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(g,f){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(h){h=(h===undefined)?(true):(h);var f=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var g=this._buildNewRender();if(h){$(f).queue(function(i){this.$el.fadeOut(f.fxSpeed,i)})}$(f).queue(function(i){this.$el.empty().attr("class",f.className).addClass("state-"+f.model.get("state")).append(g.children());if(this.selectable){this.showSelector(0)}i()});if(h){$(f).queue(function(i){this.$el.fadeIn(f.fxSpeed,i)})}$(f).queue(function(i){this.trigger("rendered",f);if(this.model.inReadyState()){this.trigger("rendered:ready",f)}if(this.draggable){this.draggableOn()}i()});return this},_buildNewRender:function(){var f=$(c.templates.skeleton(this.model.toJSON()));f.find(".dataset-primary-actions").append(this._render_titleButtons());f.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(f);return f},_setUpBehaviors:function(f){f=f||this.$el;make_popup_menus(f);f.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var g={target:this.linkTarget,classes:"dataset-display"};if(this.model.get("purged")){g.disabled=true;g.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){g.disabled=true;g.title=_l("This dataset must finish uploading before it can be viewed")}else{g.title=_l("View data");g.href=this.urls.display;var f=this;g.onclick=function(){if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Data Viewer: "+f.model.get("name"),type:"url",content:f.urls.display})}}}}g.faIcon="fa-eye";return faIconButton(g)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var g=this.urls,h=this.model.get("meta_files");if(_.isEmpty(h)){return $(['<a href="'+g.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var i="dataset-"+this.model.get("id")+"-popup",f=['<div popupmenu="'+i+'">','<a href="'+g.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(h,function(j){return['<a class="action-button" href="',g.meta_download+j.file_type,'">',_l("Download")," ",j.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+g.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+i+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(f)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),classes:"dataset-params-btn",href:this.urls.show_params,target:this.linkTarget,faIcon:"fa-info-circle"})},_render_body:function(){var g=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),f=this["_render_body_"+this.model.get("state")];if(_.isFunction(f)){g=f.call(this)}this._setUpBehaviors(g);if(this.expanded){g.show()}return g},_render_stateBodyHelper:function(f,i){i=i||[];var g=this,h=$(c.templates.body(_.extend(this.model.toJSON(),{body:f})));h.find(".dataset-actions .left").append(_.map(i,function(j){return j.call(g)}));return h},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var f=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){f="<div>"+this.model.get("misc_blurb")+"</div>"+f}return this._render_stateBodyHelper(f,[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var f=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),g=this._render_body_ok();g.prepend(f);return g},_render_body_ok:function(){var f=this,h=$(c.templates.body(this.model.toJSON())),g=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);h.find(".dataset-actions .left").append(_.map(g,function(i){return i.call(f)}));if(this.model.isDeletedOrPurged()){return h}return h},events:{"click .dataset-title-bar":"toggleBodyVisibility","keydown .dataset-title-bar":"toggleBodyVisibility","click .dataset-selector":"toggleSelect"},toggleBodyVisibility:function(i,g){var f=32,h=13;if(i&&(i.type==="keydown")&&!(i.keyCode===f||i.keyCode===h)){return true}var j=this.$el.find(".dataset-body");g=(g===undefined)?(!j.is(":visible")):(g);if(g){this.expandBody()}else{this.collapseBody()}return false},expandBody:function(){var f=this;function g(){f.$el.children(".dataset-body").replaceWith(f._render_body());f.$el.children(".dataset-body").slideDown(f.fxSpeed,function(){f.expanded=true;f.trigger("body-expanded",f.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(h){f.urls=f.model.urls();g()})}else{g()}},collapseBody:function(){var f=this;this.$el.children(".dataset-body").slideUp(f.fxSpeed,function(){f.expanded=false;f.trigger("body-collapsed",f.model.get("id"))})},showSelector:function(){if(this.selected){this.select(null,true)}this.selectable=true;this.trigger("selectable",true,this);this.$(".dataset-primary-actions").hide();this.$(".dataset-selector").show()},hideSelector:function(){this.selectable=false;this.trigger("selectable",false,this);this.$(".dataset-selector").hide();this.$(".dataset-primary-actions").show()},toggleSelector:function(){if(!this.$el.find(".dataset-selector").is(":visible")){this.showSelector()}else{this.hideSelector()}},select:function(f){this.$el.find(".dataset-selector span").removeClass("fa-square-o").addClass("fa-check-square-o");if(!this.selected){this.trigger("selected",this);this.selected=true}return false},deselect:function(f){this.$el.find(".dataset-selector span").removeClass("fa-check-square-o").addClass("fa-square-o");if(this.selected){this.trigger("de-selected",this);this.selected=false}return false},toggleSelect:function(f){if(this.selected){this.deselect(f)}else{this.select(f)}},draggableOn:function(){this.draggable=true;this.dragStartHandler=_.bind(this._dragStartHandler,this);this.dragEndHandler=_.bind(this._dragEndHandler,this);var f=this.$el.find(".dataset-title-bar").attr("draggable",true).get(0);f.addEventListener("dragstart",this.dragStartHandler,false);f.addEventListener("dragend",this.dragEndHandler,false)},draggableOff:function(){this.draggable=false;var f=this.$el.find(".dataset-title-bar").attr("draggable",false).get(0);f.removeEventListener("dragstart",this.dragStartHandler,false);f.removeEventListener("dragend",this.dragEndHandler,false)},toggleDraggable:function(){if(this.draggable){this.draggableOff()}else{this.draggableOn()}},_dragStartHandler:function(f){this.trigger("dragstart",this);f.dataTransfer.effectAllowed="move";f.dataTransfer.setData("text",JSON.stringify(this.model.toJSON()));return false},_dragEndHandler:function(f){this.trigger("dragend",this);return false},remove:function(g){var f=this;this.$el.fadeOut(f.fxSpeed,function(){f.$el.remove();f.off();if(g){g()}})},toString:function(){var f=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+f+")"}});var a=['<div class="dataset hda">','<div class="dataset-warnings">',"<% if( hda.error ){ %>",'<div class="errormessagesmall">',_l("There was an error getting the data for this dataset"),":<%- hda.error %>","</div>","<% } %>","<% if( hda.deleted ){ %>","<% if( hda.purged ){ %>",'<div class="dataset-purged-msg warningmessagesmall"><strong>',_l("This dataset has been deleted and removed from disk."),"</strong></div>","<% } else { %>",'<div class="dataset-deleted-msg warningmessagesmall"><strong>',_l("This dataset has been deleted."),"</strong></div>","<% } %>","<% } %>","<% if( !hda.visible ){ %>",'<div class="dataset-hidden-msg warningmessagesmall"><strong>',_l("This dataset has been hidden."),"</strong></div>","<% } %>","</div>",'<div class="dataset-selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="dataset-primary-actions"></div>','<div class="dataset-title-bar clear" tabindex="0">','<span class="dataset-state-icon state-icon"></span>','<div class="dataset-title">','<span class="hda-hid"><%- hda.hid %></span> ','<span class="dataset-name"><%- hda.name %></span>',"</div>","</div>",'<div class="dataset-body"></div>',"</div>"].join("");var e=['<div class="dataset-body">',"<% if( hda.body ){ %>",'<div class="dataset-summary">',"<%= hda.body %>","</div>",'<div class="dataset-actions clear">','<div class="left"></div>','<div class="right"></div>',"</div>","<% } else { %>",'<div class="dataset-summary">',"<% if( hda.misc_blurb ){ %>",'<div class="dataset-blurb">','<span class="value"><%- hda.misc_blurb %></span>',"</div>","<% } %>","<% if( hda.data_type ){ %>",'<div class="dataset-datatype">','<label class="prompt">',_l("format"),"</label>",'<span class="value"><%- hda.data_type %></span>',"</div>","<% } %>","<% if( hda.metadata_dbkey ){ %>",'<div class="dataset-dbkey">','<label class="prompt">',_l("database"),"</label>",'<span class="value">',"<%- hda.metadata_dbkey %>","</span>","</div>","<% } %>","<% if( hda.misc_info ){ %>",'<div class="dataset-info">','<span class="value"><%- hda.misc_info %></span>',"</div>","<% } %>","</div>",'<div class="dataset-actions clear">','<div class="left"></div>','<div class="right"></div>',"</div>","<% if( !hda.deleted ){ %>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="dataset-display-applications">',"<% _.each( hda.display_apps, function( app ){ %>",'<div class="display-application">','<span class="display-application-location"><%- app.label %></span> ','<span class="display-application-links">',"<% _.each( app.links, function( link ){ %>",'<a target="<%= link.target %>" href="<%= link.href %>">',"<% print( _l( link.text ) ); %>","</a> ","<% }); %>","</span>","</div>","<% }); %>","<% _.each( hda.display_types, function( app ){ %>",'<div class="display-application">','<span class="display-application-location"><%- app.label %></span> ','<span class="display-application-links">',"<% _.each( app.links, function( link ){ %>",'<a target="<%= link.target %>" href="<%= link.href %>">',"<% print( _l( link.text ) ); %>","</a> ","<% }); %>","</span>","</div>","<% }); %>","</div>",'<div class="dataset-peek">',"<% if( hda.peek ){ %>",'<pre class="peek"><%= hda.peek %></pre>',"<% } %>","</div>","<% } %>","<% } %>","</div>"].join("");c.templates={skeleton:function(f){return _.template(a,f,{variable:"hda"})},body:function(f){return _.template(e,f,{variable:"hda"})}};return{HDABaseView:c}});
\ No newline at end of file
+define(["mvc/dataset/hda-model","mvc/base-mvc"],function(d,b){var c=Backbone.View.extend(b.LoggableMixin).extend({tagName:"div",className:"dataset hda history-panel-hda",id:function(){return"hda-"+this.model.get("id")},fxSpeed:"fast",initialize:function(f){if(f.logger){this.logger=this.model.logger=f.logger}this.log(this+".initialize:",f);this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton];this.linkTarget=f.linkTarget||"_blank";this.selectable=f.selectable||false;this.selected=f.selected||false;this.expanded=f.expanded||false;this.draggable=f.draggable||false;this._setUpListeners()},_setUpListeners:function(){this.model.on("change",function(g,f){if(this.model.changedAttributes().state&&this.model.inReadyState()&&this.expanded&&!this.model.hasDetails()){this.model.fetch()}else{this.render()}},this)},render:function(h){h=(h===undefined)?(true):(h);var f=this;this.$el.find("[title]").tooltip("destroy");this.urls=this.model.urls();var g=this._buildNewRender();if(h){$(f).queue(function(i){this.$el.fadeOut(f.fxSpeed,i)})}$(f).queue(function(i){this.$el.empty().attr("class",f.className).addClass("state-"+f.model.get("state")).append(g.children());if(this.selectable){this.showSelector(0)}i()});if(h){$(f).queue(function(i){this.$el.fadeIn(f.fxSpeed,i)})}$(f).queue(function(i){this.trigger("rendered",f);if(this.model.inReadyState()){this.trigger("rendered:ready",f)}if(this.draggable){this.draggableOn()}i()});return this},_buildNewRender:function(){var f=$(c.templates.skeleton(this.model.toJSON()));f.find(".dataset-primary-actions").append(this._render_titleButtons());f.children(".dataset-body").replaceWith(this._render_body());this._setUpBehaviors(f);return f},_setUpBehaviors:function(f){f=f||this.$el;make_popup_menus(f);f.find("[title]").tooltip({placement:"bottom"})},_render_titleButtons:function(){return[this._render_displayButton()]},_render_displayButton:function(){if((this.model.get("state")===d.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===d.HistoryDatasetAssociation.STATES.NEW)||(!this.model.get("accessible"))){return null}var g={target:this.linkTarget,classes:"dataset-display"};if(this.model.get("purged")){g.disabled=true;g.title=_l("Cannot display datasets removed from disk")}else{if(this.model.get("state")===d.HistoryDatasetAssociation.STATES.UPLOAD){g.disabled=true;g.title=_l("This dataset must finish uploading before it can be viewed")}else{g.title=_l("View data");g.href=this.urls.display;var f=this;g.onclick=function(h){console.debug("displayBtn onclick",h);if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Data Viewer: "+f.model.get("name"),type:"url",content:f.urls.display});h.preventDefault()}}}}g.faIcon="fa-eye";return faIconButton(g)},_render_downloadButton:function(){if(this.model.get("purged")||!this.model.hasData()){return null}var g=this.urls,h=this.model.get("meta_files");if(_.isEmpty(h)){return $(['<a href="'+g.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>',"</a>"].join(""))}var i="dataset-"+this.model.get("id")+"-popup",f=['<div popupmenu="'+i+'">','<a href="'+g.download+'">',_l("Download Dataset"),"</a>","<a>"+_l("Additional Files")+"</a>",_.map(h,function(j){return['<a class="action-button" href="',g.meta_download+j.file_type,'">',_l("Download")," ",j.file_type,"</a>"].join("")}).join("\n"),"</div>",'<div class="icon-btn-group">','<a href="'+g.download+'" title="'+_l("Download")+'" ','class="icon-btn dataset-download-btn">','<span class="fa fa-floppy-o"></span>','</a><a class="icon-btn popup" id="'+i+'">','<span class="fa fa-caret-down"></span>',"</a>","</div>"].join("\n");return $(f)},_render_showParamsButton:function(){return faIconButton({title:_l("View details"),classes:"dataset-params-btn",href:this.urls.show_params,target:this.linkTarget,faIcon:"fa-info-circle"})},_render_body:function(){var g=$('<div>Error: unknown dataset state "'+this.model.get("state")+'".</div>'),f=this["_render_body_"+this.model.get("state")];if(_.isFunction(f)){g=f.call(this)}this._setUpBehaviors(g);if(this.expanded){g.show()}return g},_render_stateBodyHelper:function(f,i){i=i||[];var g=this,h=$(c.templates.body(_.extend(this.model.toJSON(),{body:f})));h.find(".dataset-actions .left").append(_.map(i,function(j){return j.call(g)}));return h},_render_body_new:function(){return this._render_stateBodyHelper("<div>"+_l("This is a new dataset and not all of its data are available yet")+"</div>")},_render_body_noPermission:function(){return this._render_stateBodyHelper("<div>"+_l("You do not have permission to view this dataset")+"</div>")},_render_body_discarded:function(){return this._render_stateBodyHelper("<div>"+_l("The job creating this dataset was cancelled before completion")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_queued:function(){return this._render_stateBodyHelper("<div>"+_l("This job is waiting to run")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_upload:function(){return this._render_stateBodyHelper("<div>"+_l("This dataset is currently uploading")+"</div>")},_render_body_setting_metadata:function(){return this._render_stateBodyHelper("<div>"+_l("Metadata is being auto-detected")+"</div>")},_render_body_running:function(){return this._render_stateBodyHelper("<div>"+_l("This job is currently running")+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_paused:function(){return this._render_stateBodyHelper("<div>"+_l('This job is paused. Use the "Resume Paused Jobs" in the history menu to resume')+"</div>",this.defaultPrimaryActionButtonRenderers)},_render_body_error:function(){var f=['<span class="help-text">',_l("An error occurred with this dataset"),":</span>",'<div class="job-error-text">',$.trim(this.model.get("misc_info")),"</div>"].join("");if(!this.model.get("purged")){f="<div>"+this.model.get("misc_blurb")+"</div>"+f}return this._render_stateBodyHelper(f,[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers))},_render_body_empty:function(){return this._render_stateBodyHelper("<div>"+_l("No data")+": <i>"+this.model.get("misc_blurb")+"</i></div>",this.defaultPrimaryActionButtonRenderers)},_render_body_failed_metadata:function(){var f=$('<div class="warningmessagesmall"></div>').append($("<strong/>").text(_l("An error occurred setting the metadata for this dataset"))),g=this._render_body_ok();g.prepend(f);return g},_render_body_ok:function(){var f=this,h=$(c.templates.body(this.model.toJSON())),g=[this._render_downloadButton].concat(this.defaultPrimaryActionButtonRenderers);h.find(".dataset-actions .left").append(_.map(g,function(i){return i.call(f)}));if(this.model.isDeletedOrPurged()){return h}return h},events:{"click .dataset-title-bar":"toggleBodyVisibility","keydown .dataset-title-bar":"toggleBodyVisibility","click .dataset-selector":"toggleSelect"},toggleBodyVisibility:function(i,g){var f=32,h=13;if(i&&(i.type==="keydown")&&!(i.keyCode===f||i.keyCode===h)){return true}var j=this.$el.find(".dataset-body");g=(g===undefined)?(!j.is(":visible")):(g);if(g){this.expandBody()}else{this.collapseBody()}return false},expandBody:function(){var f=this;function g(){f.$el.children(".dataset-body").replaceWith(f._render_body());f.$el.children(".dataset-body").slideDown(f.fxSpeed,function(){f.expanded=true;f.trigger("body-expanded",f.model.get("id"))})}if(this.model.inReadyState()&&!this.model.hasDetails()){this.model.fetch({silent:true}).always(function(h){f.urls=f.model.urls();g()})}else{g()}},collapseBody:function(){var f=this;this.$el.children(".dataset-body").slideUp(f.fxSpeed,function(){f.expanded=false;f.trigger("body-collapsed",f.model.get("id"))})},showSelector:function(){if(this.selected){this.select(null,true)}this.selectable=true;this.trigger("selectable",true,this);this.$(".dataset-primary-actions").hide();this.$(".dataset-selector").show()},hideSelector:function(){this.selectable=false;this.trigger("selectable",false,this);this.$(".dataset-selector").hide();this.$(".dataset-primary-actions").show()},toggleSelector:function(){if(!this.$el.find(".dataset-selector").is(":visible")){this.showSelector()}else{this.hideSelector()}},select:function(f){this.$el.find(".dataset-selector span").removeClass("fa-square-o").addClass("fa-check-square-o");if(!this.selected){this.trigger("selected",this);this.selected=true}return false},deselect:function(f){this.$el.find(".dataset-selector span").removeClass("fa-check-square-o").addClass("fa-square-o");if(this.selected){this.trigger("de-selected",this);this.selected=false}return false},toggleSelect:function(f){if(this.selected){this.deselect(f)}else{this.select(f)}},draggableOn:function(){this.draggable=true;this.dragStartHandler=_.bind(this._dragStartHandler,this);this.dragEndHandler=_.bind(this._dragEndHandler,this);var f=this.$el.find(".dataset-title-bar").attr("draggable",true).get(0);f.addEventListener("dragstart",this.dragStartHandler,false);f.addEventListener("dragend",this.dragEndHandler,false)},draggableOff:function(){this.draggable=false;var f=this.$el.find(".dataset-title-bar").attr("draggable",false).get(0);f.removeEventListener("dragstart",this.dragStartHandler,false);f.removeEventListener("dragend",this.dragEndHandler,false)},toggleDraggable:function(){if(this.draggable){this.draggableOff()}else{this.draggableOn()}},_dragStartHandler:function(f){this.trigger("dragstart",this);f.dataTransfer.effectAllowed="move";f.dataTransfer.setData("text",JSON.stringify(this.model.toJSON()));return false},_dragEndHandler:function(f){this.trigger("dragend",this);return false},remove:function(g){var f=this;this.$el.fadeOut(f.fxSpeed,function(){f.$el.remove();f.off();if(g){g()}})},toString:function(){var f=(this.model)?(this.model+""):("(no model)");return"HDABaseView("+f+")"}});var a=['<div class="dataset hda">','<div class="dataset-warnings">',"<% if( hda.error ){ %>",'<div class="errormessagesmall">',_l("There was an error getting the data for this dataset"),":<%- hda.error %>","</div>","<% } %>","<% if( hda.deleted ){ %>","<% if( hda.purged ){ %>",'<div class="dataset-purged-msg warningmessagesmall"><strong>',_l("This dataset has been deleted and removed from disk."),"</strong></div>","<% } else { %>",'<div class="dataset-deleted-msg warningmessagesmall"><strong>',_l("This dataset has been deleted."),"</strong></div>","<% } %>","<% } %>","<% if( !hda.visible ){ %>",'<div class="dataset-hidden-msg warningmessagesmall"><strong>',_l("This dataset has been hidden."),"</strong></div>","<% } %>","</div>",'<div class="dataset-selector">','<span class="fa fa-2x fa-square-o"></span>',"</div>",'<div class="dataset-primary-actions"></div>','<div class="dataset-title-bar clear" tabindex="0">','<span class="dataset-state-icon state-icon"></span>','<div class="dataset-title">','<span class="hda-hid"><%- hda.hid %></span> ','<span class="dataset-name"><%- hda.name %></span>',"</div>","</div>",'<div class="dataset-body"></div>',"</div>"].join("");var e=['<div class="dataset-body">',"<% if( hda.body ){ %>",'<div class="dataset-summary">',"<%= hda.body %>","</div>",'<div class="dataset-actions clear">','<div class="left"></div>','<div class="right"></div>',"</div>","<% } else { %>",'<div class="dataset-summary">',"<% if( hda.misc_blurb ){ %>",'<div class="dataset-blurb">','<span class="value"><%- hda.misc_blurb %></span>',"</div>","<% } %>","<% if( hda.data_type ){ %>",'<div class="dataset-datatype">','<label class="prompt">',_l("format"),"</label>",'<span class="value"><%- hda.data_type %></span>',"</div>","<% } %>","<% if( hda.metadata_dbkey ){ %>",'<div class="dataset-dbkey">','<label class="prompt">',_l("database"),"</label>",'<span class="value">',"<%- hda.metadata_dbkey %>","</span>","</div>","<% } %>","<% if( hda.misc_info ){ %>",'<div class="dataset-info">','<span class="value"><%- hda.misc_info %></span>',"</div>","<% } %>","</div>",'<div class="dataset-actions clear">','<div class="left"></div>','<div class="right"></div>',"</div>","<% if( !hda.deleted ){ %>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="dataset-display-applications">',"<% _.each( hda.display_apps, function( app ){ %>",'<div class="display-application">','<span class="display-application-location"><%- app.label %></span> ','<span class="display-application-links">',"<% _.each( app.links, function( link ){ %>",'<a target="<%= link.target %>" href="<%= link.href %>">',"<% print( _l( link.text ) ); %>","</a> ","<% }); %>","</span>","</div>","<% }); %>","<% _.each( hda.display_types, function( app ){ %>",'<div class="display-application">','<span class="display-application-location"><%- app.label %></span> ','<span class="display-application-links">',"<% _.each( app.links, function( link ){ %>",'<a target="<%= link.target %>" href="<%= link.href %>">',"<% print( _l( link.text ) ); %>","</a> ","<% }); %>","</span>","</div>","<% }); %>","</div>",'<div class="dataset-peek">',"<% if( hda.peek ){ %>",'<pre class="peek"><%= hda.peek %></pre>',"<% } %>","</div>","<% } %>","<% } %>","</div>"].join("");c.templates={skeleton:function(f){return _.template(a,f,{variable:"hda"})},body:function(f){return _.template(e,f,{variable:"hda"})}};return{HDABaseView:c}});
\ No newline at end of file
diff -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 -r f4d81f13120a8995b3486bd05c00d0430f2d44c7 static/scripts/packed/mvc/dataset/hda-edit.js
--- a/static/scripts/packed/mvc/dataset/hda-edit.js
+++ b/static/scripts/packed/mvc/dataset/hda-edit.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/tags","mvc/annotations"],function(f,b,a,e){var g=b.HDABaseView.extend({initialize:function(h){b.HDABaseView.prototype.initialize.call(this,h);this.hasUser=h.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton];this.tagsEditorShown=h.tagsEditorShown||false;this.annotationEditorShown=h.annotationEditorShown||false},_render_titleButtons:function(){return b.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===f.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===f.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===f.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var j=this.model.get("purged"),h=this.model.get("deleted"),i={title:_l("Edit attributes"),href:this.urls.edit,target:this.linkTarget,classes:"dataset-edit"};if(h||j){i.disabled=true;if(j){i.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(h){i.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===f.HistoryDatasetAssociation.STATES.UPLOAD){i.disabled=true;i.title=_l("This dataset must finish uploading before it can be edited")}}i.faIcon="fa-pencil";return faIconButton(i)},_render_deleteButton:function(){if((this.model.get("state")===f.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===f.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var h=this,i={title:_l("Delete"),classes:"dataset-delete",onclick:function(){h.$el.find(".icon-btn.dataset-delete").trigger("mouseout");h.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){i={title:_l("Dataset is already deleted"),disabled:true}}i.faIcon="fa-times";return faIconButton(i)},_render_errButton:function(){if(this.model.get("state")!==f.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,classes:"dataset-report-error-btn",target:this.linkTarget,faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,classes:"dataset-rerun-btn",target:this.linkTarget,faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var h=this.model.get("visualizations");if((!this.hasUser)||(!this.model.hasData())||(_.isEmpty(h))){return null}if(_.isObject(h[0])){return this._render_visualizationsFrameworkButton(h)}if(!this.urls.visualization){return null}var j=this.model.get("dbkey"),n=this.urls.visualization,k={},o={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(j){o.dbkey=j}var i=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});function l(p){if(p==="trackster"){return c(n,o,j)}return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:n+"/"+p+"?"+$.param(o)})}}function m(p){return p.charAt(0).toUpperCase()+p.slice(1)}if(h.length===1){i.attr("data-original-title",_l("Visualize in ")+_l(m(h[0])));i.click(l(h[0]))}else{_.each(h,function(p){k[_l(m(p))]=l(p)});make_popupmenu(i,k)}return i},_render_visualizationsFrameworkButton:function(h){if(!(this.model.hasData())||!(h&&!_.isEmpty(h))){return null}var j=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});if(h.length===1){var i=h[0];j.attr("data-original-title",_l("Visualize in ")+i.html);j.attr("href",i.href)}else{var k=[];_.each(h,function(l){l.func=function(){if(Galaxy.frame.active){Galaxy.frame.add({title:"Visualization",type:"url",content:l.href});return false}return true};k.push(l);return false});PopupMenu.create(j,k)}return j},_buildNewRender:function(){var h=b.HDABaseView.prototype._buildNewRender.call(this);h.find(".dataset-deleted-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk'));h.find(".dataset-hidden-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it'));return h},_render_body_failed_metadata:function(){var i=$("<a/>").attr({href:this.urls.edit,target:this.linkTarget}).text(_l("set it manually or retry auto-detection")),h=$("<span/>").text(". "+_l("You may be able to")+" ").append(i),j=b.HDABaseView.prototype._render_body_failed_metadata.call(this);j.find(".warningmessagesmall strong").append(h);return j},_render_body_error:function(){var h=b.HDABaseView.prototype._render_body_error.call(this);h.find(".dataset-actions .left").prepend(this._render_errButton());return h},_render_body_ok:function(){var h=b.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return h}this.makeDbkeyEditLink(h);if(this.hasUser){h.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(h);this._renderAnnotation(h)}return h},_renderTags:function(h){var i=this;this.tagsEditor=new a.TagsEditor({model:this.model,el:h.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.tagsEditorShown=true},onhide:function(){i.tagsEditorShown=false},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(h.find(".dataset-actions .right"))});if(this.tagsEditorShown){this.tagsEditor.toggle(true)}},_renderAnnotation:function(h){var i=this;this.annotationEditor=new e.AnnotationEditor({model:this.model,el:h.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.annotationEditorShown=true},onhide:function(){i.annotationEditorShown=false},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(h.find(".dataset-actions .right"))});if(this.annotationEditorShown){this.annotationEditor.toggle(true)}},makeDbkeyEditLink:function(i){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){var h=$('<a class="value">?</a>').attr("href",this.urls.edit).attr("target",this.linkTarget);i.find(".dataset-dbkey .value").replaceWith(h)}},events:_.extend(_.clone(b.HDABaseView.prototype.events),{"click .dataset-undelete":function(h){this.model.undelete();return false},"click .dataset-unhide":function(h){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"}),confirmPurge:function d(h){this.model.purge();return false},toString:function(){var h=(this.model)?(this.model+""):("(no model)");return"HDAView("+h+")"}});function c(h,j,i){return function(){var k={};if(i){k["f-dbkey"]=i}$.ajax({url:h+"/list_tracks?"+$.param(k),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(l){var m=window.parent;m.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){m.Galaxy.modal.hide()},"View in saved visualization":function(){m.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:l,buttons:{Cancel:function(){m.Galaxy.modal.hide()},"Add to visualization":function(){$(m.document).find("input[name=id]:checked").each(function(){m.Galaxy.modal.hide();var n=$(this).val();j.id=n;m.Galaxy.frame.add({title:"Trackster",type:"url",content:h+"/trackster?"+$.param(j)})})}}})},"View in new visualization":function(){m.Galaxy.modal.hide();var n=h+"/trackster?"+$.param(j);m.Galaxy.frame.add({title:"Trackster",type:"url",content:n})}}})}});return false}}return{HDAEditView:g}});
\ No newline at end of file
+define(["mvc/dataset/hda-model","mvc/dataset/hda-base","mvc/tags","mvc/annotations"],function(f,b,a,e){var g=b.HDABaseView.extend({initialize:function(h){b.HDABaseView.prototype.initialize.call(this,h);this.hasUser=h.hasUser;this.defaultPrimaryActionButtonRenderers=[this._render_showParamsButton,this._render_rerunButton];this.tagsEditorShown=h.tagsEditorShown||false;this.annotationEditorShown=h.annotationEditorShown||false},_render_titleButtons:function(){return b.HDABaseView.prototype._render_titleButtons.call(this).concat([this._render_editButton(),this._render_deleteButton()])},_render_editButton:function(){if((this.model.get("state")===f.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===f.HistoryDatasetAssociation.STATES.DISCARDED)||(this.model.get("state")===f.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var j=this.model.get("purged"),h=this.model.get("deleted"),i={title:_l("Edit attributes"),href:this.urls.edit,target:this.linkTarget,classes:"dataset-edit"};if(h||j){i.disabled=true;if(j){i.title=_l("Cannot edit attributes of datasets removed from disk")}else{if(h){i.title=_l("Undelete dataset to edit attributes")}}}else{if(this.model.get("state")===f.HistoryDatasetAssociation.STATES.UPLOAD){i.disabled=true;i.title=_l("This dataset must finish uploading before it can be edited")}}i.faIcon="fa-pencil";return faIconButton(i)},_render_deleteButton:function(){if((this.model.get("state")===f.HistoryDatasetAssociation.STATES.NEW)||(this.model.get("state")===f.HistoryDatasetAssociation.STATES.NOT_VIEWABLE)||(!this.model.get("accessible"))){return null}var h=this,i={title:_l("Delete"),classes:"dataset-delete",onclick:function(){h.$el.find(".icon-btn.dataset-delete").trigger("mouseout");h.model["delete"]()}};if(this.model.get("deleted")||this.model.get("purged")){i={title:_l("Dataset is already deleted"),disabled:true}}i.faIcon="fa-times";return faIconButton(i)},_render_errButton:function(){if(this.model.get("state")!==f.HistoryDatasetAssociation.STATES.ERROR){return null}return faIconButton({title:_l("View or report this error"),href:this.urls.report_error,classes:"dataset-report-error-btn",target:this.linkTarget,faIcon:"fa-bug"})},_render_rerunButton:function(){return faIconButton({title:_l("Run this job again"),href:this.urls.rerun,classes:"dataset-rerun-btn",target:this.linkTarget,faIcon:"fa-refresh"})},_render_visualizationsButton:function(){var h=this.model.get("visualizations");if((!this.hasUser)||(!this.model.hasData())||(_.isEmpty(h))){return null}if(_.isObject(h[0])){return this._render_visualizationsFrameworkButton(h)}if(!this.urls.visualization){return null}var j=this.model.get("dbkey"),n=this.urls.visualization,k={},o={dataset_id:this.model.get("id"),hda_ldda:"hda"};if(j){o.dbkey=j}var i=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});function l(p){if(p==="trackster"){return c(n,o,j)}return function(){Galaxy.frame.add({title:"Visualization",type:"url",content:n+"/"+p+"?"+$.param(o)})}}function m(p){return p.charAt(0).toUpperCase()+p.slice(1)}if(h.length===1){i.attr("data-original-title",_l("Visualize in ")+_l(m(h[0])));i.click(l(h[0]))}else{_.each(h,function(p){k[_l(m(p))]=l(p)});make_popupmenu(i,k)}return i},_render_visualizationsFrameworkButton:function(h){if(!(this.model.hasData())||!(h&&!_.isEmpty(h))){return null}var j=faIconButton({title:_l("Visualize"),classes:"dataset-visualize-btn",faIcon:"fa-bar-chart-o"});if(h.length===1){var i=h[0];j.attr("data-original-title",_l("Visualize in ")+i.html);j.attr("href",i.href)}else{var k=[];_.each(h,function(l){l.func=function(m){if(Galaxy.frame&&Galaxy.frame.active){Galaxy.frame.add({title:"Visualization",type:"url",content:l.href});m.preventDefault();return false}return true};k.push(l);return false});PopupMenu.create(j,k)}return j},_buildNewRender:function(){var h=b.HDABaseView.prototype._buildNewRender.call(this);h.find(".dataset-deleted-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-undelete">here</a> to undelete it or <a href="javascript:void(0);" class="dataset-purge">here</a> to immediately remove it from disk'));h.find(".dataset-hidden-msg").append(_l('Click <a href="javascript:void(0);" class="dataset-unhide">here</a> to unhide it'));return h},_render_body_failed_metadata:function(){var i=$("<a/>").attr({href:this.urls.edit,target:this.linkTarget}).text(_l("set it manually or retry auto-detection")),h=$("<span/>").text(". "+_l("You may be able to")+" ").append(i),j=b.HDABaseView.prototype._render_body_failed_metadata.call(this);j.find(".warningmessagesmall strong").append(h);return j},_render_body_error:function(){var h=b.HDABaseView.prototype._render_body_error.call(this);h.find(".dataset-actions .left").prepend(this._render_errButton());return h},_render_body_ok:function(){var h=b.HDABaseView.prototype._render_body_ok.call(this);if(this.model.isDeletedOrPurged()){return h}this.makeDbkeyEditLink(h);if(this.hasUser){h.find(".dataset-actions .left").append(this._render_visualizationsButton());this._renderTags(h);this._renderAnnotation(h)}return h},_renderTags:function(h){var i=this;this.tagsEditor=new a.TagsEditor({model:this.model,el:h.find(".tags-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.tagsEditorShown=true},onhide:function(){i.tagsEditorShown=false},$activator:faIconButton({title:_l("Edit dataset tags"),classes:"dataset-tag-btn",faIcon:"fa-tags"}).appendTo(h.find(".dataset-actions .right"))});if(this.tagsEditorShown){this.tagsEditor.toggle(true)}},_renderAnnotation:function(h){var i=this;this.annotationEditor=new e.AnnotationEditor({model:this.model,el:h.find(".annotation-display"),onshowFirstTime:function(){this.render()},onshow:function(){i.annotationEditorShown=true},onhide:function(){i.annotationEditorShown=false},$activator:faIconButton({title:_l("Edit dataset annotation"),classes:"dataset-annotate-btn",faIcon:"fa-comment"}).appendTo(h.find(".dataset-actions .right"))});if(this.annotationEditorShown){this.annotationEditor.toggle(true)}},makeDbkeyEditLink:function(i){if(this.model.get("metadata_dbkey")==="?"&&!this.model.isDeletedOrPurged()){var h=$('<a class="value">?</a>').attr("href",this.urls.edit).attr("target",this.linkTarget);i.find(".dataset-dbkey .value").replaceWith(h)}},events:_.extend(_.clone(b.HDABaseView.prototype.events),{"click .dataset-undelete":function(h){this.model.undelete();return false},"click .dataset-unhide":function(h){this.model.unhide();return false},"click .dataset-purge":"confirmPurge"}),confirmPurge:function d(h){this.model.purge();return false},toString:function(){var h=(this.model)?(this.model+""):("(no model)");return"HDAView("+h+")"}});function c(h,j,i){return function(){var k={};if(i){k["f-dbkey"]=i}$.ajax({url:h+"/list_tracks?"+$.param(k),dataType:"html",error:function(){alert(("Could not add this dataset to browser")+".")},success:function(l){var m=window.parent;m.Galaxy.modal.show({title:"View Data in a New or Saved Visualization",buttons:{Cancel:function(){m.Galaxy.modal.hide()},"View in saved visualization":function(){m.Galaxy.modal.show({title:"Add Data to Saved Visualization",body:l,buttons:{Cancel:function(){m.Galaxy.modal.hide()},"Add to visualization":function(){$(m.document).find("input[name=id]:checked").each(function(){m.Galaxy.modal.hide();var n=$(this).val();j.id=n;m.Galaxy.frame.add({title:"Trackster",type:"url",content:h+"/trackster?"+$.param(j)})})}}})},"View in new visualization":function(){m.Galaxy.modal.hide();var n=h+"/trackster?"+$.param(j);m.Galaxy.frame.add({title:"Trackster",type:"url",content:n})}}})}});return false}}return{HDAEditView:g}});
\ 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
commit/galaxy-central: carlfeberhard: Fix to 7155334: add user model to AMD chain for history panel
by commits-noreply@bitbucket.org 27 Mar '14
by commits-noreply@bitbucket.org 27 Mar '14
27 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ec75df18a967/
Changeset: ec75df18a967
User: carlfeberhard
Date: 2014-03-27 17:57:54
Summary: Fix to 7155334: add user model to AMD chain for history panel
Affected #: 6 files
diff -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -113,8 +113,6 @@
else:
history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
check_ownership=False, check_accessible=True, deleted=deleted )
- #history = self._get_history( trans, self._decode_id( trans, history_id ),
- # check_ownership=False, check_accessible=True, deleted=deleted )
history_data = self.get_history_dict( trans, history )
history_data[ 'contents_url' ] = url_for( 'history_contents', history_id=history_id )
diff -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 static/scripts/mvc/history/current-history-panel.js
--- a/static/scripts/mvc/history/current-history-panel.js
+++ b/static/scripts/mvc/history/current-history-panel.js
@@ -154,6 +154,7 @@
* @see Backbone.View#render
*/
render : function( speed, callback ){
+ this.log( 'render:', speed, callback );
// send a speed of 0 to have no fade in/out performed
speed = ( speed === undefined )?( this.fxSpeed ):( speed );
var panel = this,
diff -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 static/scripts/mvc/history/readonly-history-panel.js
--- a/static/scripts/mvc/history/readonly-history-panel.js
+++ b/static/scripts/mvc/history/readonly-history-panel.js
@@ -1,8 +1,9 @@
define([
"mvc/history/history-model",
"mvc/dataset/hda-base",
+ "mvc/user/user-model",
"mvc/base-mvc"
-], function( historyModel, hdaBase, baseMVC ){
+], function( historyModel, hdaBase, userModel, baseMVC ){
// ============================================================================
/** session storage for individual history preferences */
var HistoryPrefs = baseMVC.SessionStorageModel.extend({
@@ -224,7 +225,7 @@
parsed = {
message : this._bePolite( msg ),
details : {
- user : ( user instanceof User )?( user.toJSON() ):( user + '' ),
+ user : ( user instanceof userModel.User )?( user.toJSON() ):( user + '' ),
source : ( model instanceof Backbone.Model )?( model.toJSON() ):( model + '' ),
xhr : xhr,
options : ( xhr )?( _.omit( options, 'xhr' ) ):( options )
@@ -485,7 +486,7 @@
// we'll always need the message container
var $newRender = $( '<div/>' ),
$msgContainer = $( '<div/>' ).addClass( 'message-container' )
- .css({ 'margin-left': '4px', 'margin-right': '4px' });
+ .css({ 'margin': '4px' });
return $newRender.append( $msgContainer );
},
diff -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 static/scripts/packed/mvc/history/current-history-panel.js
--- a/static/scripts/packed/mvc/history/current-history-panel.js
+++ b/static/scripts/packed/mvc/history/current-history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/dataset/hda-edit","mvc/history/history-panel","mvc/base-mvc"],function(b,f,c){var d=c.SessionStorageModel.extend({defaults:{searching:false,tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});d.storageKey=function e(){return("history-panel")};var a=f.HistoryPanel.extend({HDAViewClass:b.HDAEditView,emptyMsg:_l("This history is empty. Click 'Get Data' on the left tool menu to start"),noneFoundMsg:_l("No matching datasets found"),initialize:function(g){g=g||{};this.preferences=new d(_.extend({id:d.storageKey()},_.pick(g,_.keys(d.prototype.defaults))));f.HistoryPanel.prototype.initialize.call(this,g)},loadCurrentHistory:function(h){var g=this;return this.loadHistoryWithHDADetails("current",h).then(function(j,i){g.trigger("current-history",g)})},switchToHistory:function(j,i){var g=this,h=function(){return jQuery.ajax({url:galaxy_config.root+"api/histories/"+j+"/set_as_current",method:"PUT"})};return this.loadHistoryWithHDADetails(j,i,h).then(function(l,k){g.trigger("switched-history",g)})},createNewHistory:function(i){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var g=this,h=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,i,h).then(function(k,j){g.trigger("new-history",g)})},setModel:function(h,g,i){f.HistoryPanel.prototype.setModel.call(this,h,g,i);if(this.model){this.log("checking for updates");this.model.checkForUpdates()}return this},_setUpModelEventHandlers:function(){f.HistoryPanel.prototype._setUpModelEventHandlers.call(this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("state:ready",function(h,i,g){if((!h.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[h.id])}},this)},render:function(i,j){i=(i===undefined)?(this.fxSpeed):(i);var g=this,h;if(this.model){h=this.renderModel()}else{h=this.renderWithoutModel()}$(g).queue("fx",[function(k){if(i&&g.$el.is(":visible")){g.$el.fadeOut(i,k)}else{k()}},function(k){g.$el.empty();if(h){g.$el.append(h.children());g.renderBasedOnPrefs()}k()},function(k){if(i&&!g.$el.is(":visible")){g.$el.fadeIn(i,k)}else{k()}},function(k){if(j){j.call(this)}g.trigger("rendered",this);k()}]);return this},renderBasedOnPrefs:function(){if(this.preferences.get("searching")){this.toggleSearchControls(0,true)}},_renderEmptyMsg:function(i){var h=this,g=h.$emptyMessage(i),j=$(".toolMenuContainer");if((_.isEmpty(h.hdaViews)&&!h.searchFor)&&(Galaxy&&Galaxy.upload&&j.size())){g.empty();g.html([_l("This history is empty. "),_l("You can "),'<a class="uploader-link" href="javascript:void(0)">',_l("load your own data"),"</a>",_l(" or "),'<a class="get-data-link" href="javascript:void(0)">',_l("get data from an external source"),"</a>"].join(""));g.find(".uploader-link").click(function(k){Galaxy.upload._eventShow(k)});g.find(".get-data-link").click(function(k){j.parent().scrollTop(0);j.find('span:contains("Get Data")').click()});g.show()}else{f.HistoryPanel.prototype._renderEmptyMsg.call(this,i)}return this},toggleSearchControls:function(h,g){var i=f.HistoryPanel.prototype.toggleSearchControls.call(this,h,g);this.preferences.set("searching",i)},_renderTags:function(g){var h=this;f.HistoryPanel.prototype._renderTags.call(this,g);if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}this.tagsEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(i){h.preferences.set("tagsEditorShown",i.hidden)})},_renderAnnotation:function(g){var h=this;f.HistoryPanel.prototype._renderAnnotation.call(this,g);if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}this.annotationEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(i){h.preferences.set("annotationEditorShown",i.hidden)})},connectToQuotaMeter:function(g){if(!g){return this}this.listenTo(g,"quota:over",this.showQuotaMessage);this.listenTo(g,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(g&&g.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var g=this.$el.find(".quota-message");if(g.is(":hidden")){g.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var g=this.$el.find(".quota-message");if(!g.is(":hidden")){g.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(g){if(!g){return this}this.on("new-storage",function(i,h){if(g&&i){g.findItemByHtml(_l("Include Deleted Datasets")).checked=i.get("show_deleted");g.findItemByHtml(_l("Include Hidden Datasets")).checked=i.get("show_hidden")}});return this},toString:function(){return"CurrentHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{CurrentHistoryPanel:a}});
\ No newline at end of file
+define(["mvc/dataset/hda-edit","mvc/history/history-panel","mvc/base-mvc"],function(b,f,c){var d=c.SessionStorageModel.extend({defaults:{searching:false,tagsEditorShown:false,annotationEditorShown:false},toString:function(){return"HistoryPanelPrefs("+JSON.stringify(this.toJSON())+")"}});d.storageKey=function e(){return("history-panel")};var a=f.HistoryPanel.extend({HDAViewClass:b.HDAEditView,emptyMsg:_l("This history is empty. Click 'Get Data' on the left tool menu to start"),noneFoundMsg:_l("No matching datasets found"),initialize:function(g){g=g||{};this.preferences=new d(_.extend({id:d.storageKey()},_.pick(g,_.keys(d.prototype.defaults))));f.HistoryPanel.prototype.initialize.call(this,g)},loadCurrentHistory:function(h){var g=this;return this.loadHistoryWithHDADetails("current",h).then(function(j,i){g.trigger("current-history",g)})},switchToHistory:function(j,i){var g=this,h=function(){return jQuery.ajax({url:galaxy_config.root+"api/histories/"+j+"/set_as_current",method:"PUT"})};return this.loadHistoryWithHDADetails(j,i,h).then(function(l,k){g.trigger("switched-history",g)})},createNewHistory:function(i){if(!Galaxy||!Galaxy.currUser||Galaxy.currUser.isAnonymous()){this.displayMessage("error",_l("You must be logged in to create histories"));return $.when()}var g=this,h=function(){return jQuery.post(galaxy_config.root+"api/histories",{current:true})};return this.loadHistory(undefined,i,h).then(function(k,j){g.trigger("new-history",g)})},setModel:function(h,g,i){f.HistoryPanel.prototype.setModel.call(this,h,g,i);if(this.model){this.log("checking for updates");this.model.checkForUpdates()}return this},_setUpModelEventHandlers:function(){f.HistoryPanel.prototype._setUpModelEventHandlers.call(this);if(Galaxy&&Galaxy.quotaMeter){this.listenTo(this.model,"change:nice_size",function(){Galaxy.quotaMeter.update()})}this.model.hdas.on("state:ready",function(h,i,g){if((!h.get("visible"))&&(!this.storage.get("show_hidden"))){this.removeHdaView(this.hdaViews[h.id])}},this)},render:function(i,j){this.log("render:",i,j);i=(i===undefined)?(this.fxSpeed):(i);var g=this,h;if(this.model){h=this.renderModel()}else{h=this.renderWithoutModel()}$(g).queue("fx",[function(k){if(i&&g.$el.is(":visible")){g.$el.fadeOut(i,k)}else{k()}},function(k){g.$el.empty();if(h){g.$el.append(h.children());g.renderBasedOnPrefs()}k()},function(k){if(i&&!g.$el.is(":visible")){g.$el.fadeIn(i,k)}else{k()}},function(k){if(j){j.call(this)}g.trigger("rendered",this);k()}]);return this},renderBasedOnPrefs:function(){if(this.preferences.get("searching")){this.toggleSearchControls(0,true)}},_renderEmptyMsg:function(i){var h=this,g=h.$emptyMessage(i),j=$(".toolMenuContainer");if((_.isEmpty(h.hdaViews)&&!h.searchFor)&&(Galaxy&&Galaxy.upload&&j.size())){g.empty();g.html([_l("This history is empty. "),_l("You can "),'<a class="uploader-link" href="javascript:void(0)">',_l("load your own data"),"</a>",_l(" or "),'<a class="get-data-link" href="javascript:void(0)">',_l("get data from an external source"),"</a>"].join(""));g.find(".uploader-link").click(function(k){Galaxy.upload._eventShow(k)});g.find(".get-data-link").click(function(k){j.parent().scrollTop(0);j.find('span:contains("Get Data")').click()});g.show()}else{f.HistoryPanel.prototype._renderEmptyMsg.call(this,i)}return this},toggleSearchControls:function(h,g){var i=f.HistoryPanel.prototype.toggleSearchControls.call(this,h,g);this.preferences.set("searching",i)},_renderTags:function(g){var h=this;f.HistoryPanel.prototype._renderTags.call(this,g);if(this.preferences.get("tagsEditorShown")){this.tagsEditor.toggle(true)}this.tagsEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(i){h.preferences.set("tagsEditorShown",i.hidden)})},_renderAnnotation:function(g){var h=this;f.HistoryPanel.prototype._renderAnnotation.call(this,g);if(this.preferences.get("annotationEditorShown")){this.annotationEditor.toggle(true)}this.annotationEditor.on("hiddenUntilActivated:shown hiddenUntilActivated:hidden",function(i){h.preferences.set("annotationEditorShown",i.hidden)})},connectToQuotaMeter:function(g){if(!g){return this}this.listenTo(g,"quota:over",this.showQuotaMessage);this.listenTo(g,"quota:under",this.hideQuotaMessage);this.on("rendered rendered:initial",function(){if(g&&g.isOverQuota()){this.showQuotaMessage()}});return this},showQuotaMessage:function(){var g=this.$el.find(".quota-message");if(g.is(":hidden")){g.slideDown(this.fxSpeed)}},hideQuotaMessage:function(){var g=this.$el.find(".quota-message");if(!g.is(":hidden")){g.slideUp(this.fxSpeed)}},connectToOptionsMenu:function(g){if(!g){return this}this.on("new-storage",function(i,h){if(g&&i){g.findItemByHtml(_l("Include Deleted Datasets")).checked=i.get("show_deleted");g.findItemByHtml(_l("Include Hidden Datasets")).checked=i.get("show_hidden")}});return this},toString:function(){return"CurrentHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});return{CurrentHistoryPanel:a}});
\ No newline at end of file
diff -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 static/scripts/packed/mvc/history/readonly-history-panel.js
--- a/static/scripts/packed/mvc/history/readonly-history-panel.js
+++ b/static/scripts/packed/mvc/history/readonly-history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/dataset/hda-base","mvc/base-mvc"],function(e,a,d){var g=d.SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(k){var j="expandedHdas";this.save(j,_.extend(this.get(j),_.object([k],[true])))},removeExpandedHda:function(k){var j="expandedHdas";this.save(j,_.omit(this.get(j),k))},toString:function(){return"HistoryPrefs("+this.id+")"}});g.storageKeyPrefix="history:";g.historyStorageKey=function c(j){if(!j){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+j)}return(g.storageKeyPrefix+j)};g.get=function b(j){return new g({id:g.historyStorageKey(j)})};g.clearAll=function f(k){for(var j in sessionStorage){if(j.indexOf(g.storageKeyPrefix)===0){sessionStorage.removeItem(j)}}};var h=Backbone.View.extend(d.LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(j){j=j||{};if(j.logger){this.logger=j.logger}this.log(this+".initialize:",j);this.linkTarget=j.linkTarget||"_blank";this.fxSpeed=_.has(j,"fxSpeed")?(j.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor="";this.findContainerFn=j.findContainerFn;this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this._setUpListeners();var k=_.pick(j,"initiallyExpanded","show_deleted","show_hidden");this.setModel(this.model,k,false);if(j.onready){j.onready.call(this)}},_setUpListeners:function(){this.on("error",function(k,n,j,m,l){this.errorHandler(k,n,j,m,l)});this.on("loading-history",function(){this._showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this._hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(j){this.log(this+"",arguments)},this)}return this},errorHandler:function(l,o,k,n,m){console.error(l,o,k,n,m);if(o&&o.status===0&&o.readyState===0){}else{if(o&&o.status===502){}else{var j=this._parseErrorMessage(l,o,k,n,m);if(!this.$messages().is(":visible")){this.once("rendered",function(){this.displayMessage("error",j.message,j.details)})}else{this.displayMessage("error",j.message,j.details)}}}},_parseErrorMessage:function(m,q,l,p,o){var k=Galaxy.currUser,j={message:this._bePolite(p),details:{user:(k instanceof User)?(k.toJSON()):(k+""),source:(m instanceof Backbone.Model)?(m.toJSON()):(m+""),xhr:q,options:(q)?(_.omit(l,"xhr")):(l)}};_.extend(j.details,o||{});if(q&&_.isFunction(q.getAllResponseHeaders)){var n=q.getAllResponseHeaders();n=_.compact(n.split("\n"));n=_.map(n,function(r){return r.split(": ")});j.details.xhr.responseHeaders=_.object(n)}return j},_bePolite:function(j){j=j||_l("An error occurred while getting updates from the server");return j+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(l,k,j,n){var m=function(o){return _.keys(g.get(o.id).get("expandedHdas"))};return this.loadHistory(l,k,j,n,m)},loadHistory:function(m,l,k,p,n){var j=this;l=l||{};j.trigger("loading-history",j);var o=e.History.getHistoryData(m,{historyFn:k,hdaFn:p,hdaDetailIds:l.initiallyExpanded||n});return j._loadHistoryFromXHR(o,l).fail(function(s,q,r){j.trigger("error",j,s,l,_l("An error was encountered while "+q),{historyId:m,history:r||{}})}).always(function(){j.trigger("loading-done",j)})},_loadHistoryFromXHR:function(l,k){var j=this;l.then(function(m,n){j.JSONToModel(m,n,k)});l.fail(function(n,m){j.render()});return l},JSONToModel:function(m,j,k){this.log("JSONToModel:",m,j,k);k=k||{};var l=new e.History(m,j,k);this.setModel(l);return this},setModel:function(k,j,l){j=j||{};l=(l!==undefined)?(l):(true);this.log("setModel:",k,j,l);this.freeModel();this.selectedHdaIds=[];if(k){this.model=k;if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(j.initiallyExpanded,j.show_deleted,j.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this)}if(l){this.render()}return this},freeModel:function(){if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.freeHdaViews();return this},freeHdaViews:function(){this.hdaViews={};return this},_setUpWebStorage:function(k,j,l){this.storage=new g({id:g.historyStorageKey(this.model.get("id"))});if(_.isObject(k)){this.storage.set("exandedHdas",k)}if(_.isBoolean(j)){this.storage.set("show_deleted",j)}if(_.isBoolean(l)){this.storage.set("show_hidden",l)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get());return this},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(k,m,j,l){this.errorHandler(k,m,j,l)},this);return this},render:function(l,m){this.log("render:",l,m);l=(l===undefined)?(this.fxSpeed):(l);var j=this,k;if(this.model){k=this.renderModel()}else{k=this.renderWithoutModel()}$(j).queue("fx",[function(n){if(l&&j.$el.is(":visible")){j.$el.fadeOut(l,n)}else{n()}},function(n){j.$el.empty();if(k){j.$el.append(k.children())}n()},function(n){if(l&&!j.$el.is(":visible")){j.$el.fadeIn(l,n)}else{n()}},function(n){if(m){m.call(this)}j.trigger("rendered",this);n()}]);return this},renderWithoutModel:function(){var j=$("<div/>"),k=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return j.append(k)},renderModel:function(){var j=$("<div/>");j.append(h.templates.historyPanel(this.model.toJSON()));this.$emptyMessage(j).text(this.emptyMsg);j.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(j);this.renderHdas(j);return j},_renderEmptyMsg:function(l){var k=this,j=k.$emptyMessage(l);if(!_.isEmpty(k.hdaViews)){j.hide()}else{if(k.searchFor){j.text(k.noneFoundMsg).show()}else{j.text(k.emptyMsg).show()}}return this},_renderSearchButton:function(j){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(j){j=j||this.$el;j.find("[title]").tooltip({placement:"bottom"});this._setUpSearchInput(j.find(".history-search-controls .history-search-input"));return this},$container:function(){return(this.findContainerFn)?(this.findContainerFn.call(this)):(this.$el.parent())},$datasetsList:function(j){return(j||this.$el).find(".datasets-list")},$messages:function(j){return(j||this.$el).find(".message-container")},$emptyMessage:function(j){return(j||this.$el).find(".empty-history-message")},renderHdas:function(k){k=k||this.$el;var j=this,m={},l=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);this.$datasetsList(k).empty();if(l.length){l.each(function(o){var n=o.get("id"),p=j._createHdaView(o);m[n]=p;if(_.contains(j.selectedHdaIds,n)){p.selected=true}j.attachHdaView(p.render(),k)})}this.hdaViews=m;this._renderEmptyMsg(k);return this.hdaViews},_createHdaView:function(k){var j=k.get("id"),l=new this.HDAViewClass({model:k,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[j],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(l);return l},_setUpHdaListeners:function(k){var j=this;k.on("error",function(m,o,l,n){j.errorHandler(m,o,l,n)});k.on("body-expanded",function(l){j.storage.addExpandedHda(l)});k.on("body-collapsed",function(l){j.storage.removeExpandedHda(l)});return this},attachHdaView:function(l,k){k=k||this.$el;var j=this.$datasetsList(k);j.prepend(l.$el);return this},addHdaView:function(m){this.log("add."+this,m);var k=this;if(!m.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return k}$({}).queue([function l(o){var n=k.$emptyMessage();if(n.is(":visible")){n.fadeOut(k.fxSpeed,o)}else{o()}},function j(n){var o=k._createHdaView(m);k.hdaViews[m.id]=o;o.render().$el.hide();k.scrollToTop();k.attachHdaView(o);o.$el.slideDown(k.fxSpeed)}]);return k},refreshHdas:function(k,j){if(this.model){return this.model.refresh(k,j)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(j){j.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{});return this},toggleShowDeleted:function(j){j=(j!==undefined)?(j):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",j);this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(j){j=(j!==undefined)?(j):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",j);this.renderHdas();return this.storage.get("show_hidden")},_setUpSearchInput:function(k){var l=this,m=".history-search-input";function j(n){if(l.model.hdas.haveDetails()){l.searchHdas(n);return}l.$el.find(m).searchInput("toggle-loading");l.model.hdas.fetchAllDetails({silent:true}).always(function(){l.$el.find(m).searchInput("toggle-loading")}).done(function(){l.searchHdas(n)})}k.searchInput({initialVal:l.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:j,onsearch:_.bind(this.searchHdas,this),onclear:_.bind(this.clearHdaSearch,this)});return k},toggleSearchControls:function(l,j){var k=this.$el.find(".history-search-controls"),m=(jQuery.type(l)==="number")?(l):(this.fxSpeed);j=(j!==undefined)?(j):(!k.is(":visible"));if(j){k.slideDown(m,function(){$(this).find("input").focus()})}else{k.slideUp(m)}return j},searchHdas:function(j){var k=this;this.searchFor=j;this.filters=[function(l){return l.matchesAll(k.searchFor)}];this.trigger("search:searching",j,this);this.renderHdas();return this},clearHdaSearch:function(j){this.searchFor="";this.filters=[];this.trigger("search:clear",this);this.renderHdas();return this},_showLoadingIndicator:function(k,j,l){j=(j!==undefined)?(j):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,l)}else{this.$el.fadeOut(j);this.indicator.show(k,j,l)}},_hideLoadingIndicator:function(j,k){j=(j!==undefined)?(j):(this.fxSpeed);if(this.indicator){this.indicator.hide(j,k)}},displayMessage:function(o,p,n){var l=this;this.scrollToTop();var m=this.$messages(),j=$("<div/>").addClass(o+"message").html(p);if(!_.isEmpty(n)){var k=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(l._messageToModalOptions(o,p,n));return false});j.append(" ",k)}return m.html(j)},_messageToModalOptions:function(n,p,m){var j=this,o=$("<div/>"),l={title:"Details"};function k(q){q=_.omit(q,_.functions(q));return["<table>",_.map(q,function(s,r){s=(_.isObject(s))?(k(s)):(s);return'<tr><td style="vertical-align: top; color: grey">'+r+'</td><td style="padding-left: 8px">'+s+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(m)){l.body=o.append(k(m))}else{l.body=o.html(m)}l.buttons={Ok:function(){Galaxy.modal.hide();j.clearMessages()}};return l},clearMessages:function(){this.$messages().empty();return this},scrollPosition:function(){return this.$container().scrollTop()},scrollTo:function(j){this.$container().scrollTop(j);return this},scrollToTop:function(){this.$container().scrollTop(0);return this},scrollToId:function(k){if((!k)||(!this.hdaViews[k])){return this}var j=this.hdaViews[k];this.scrollTo(j.el.offsetTop);return this},scrollToHid:function(j){var k=this.model.hdas.getByHid(j);if(!k){return this}return this.scrollToId(k.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var i=['<div class="history-controls">','<div class="history-search-controls">','<div class="history-search-input"></div>',"</div>",'<div class="history-title">',"<% if( history.name ){ %>",'<div class="history-name"><%= history.name %></div>',"<% } %>","</div>",'<div class="history-subtitle clear">',"<% if( history.nice_size ){ %>",'<div class="history-size"><%= history.nice_size %></div>',"<% } %>",'<div class="history-secondary-actions"></div>',"</div>","<% if( history.deleted ){ %>",'<div class="warningmessagesmall"><strong>',_l("You are currently viewing a deleted history!"),"</strong></div>","<% } %>",'<div class="message-container">',"<% if( history.message ){ %>",'<div class="<%= history.status %>message"><%= history.message %></div>',"<% } %>","</div>",'<div class="quota-message errormessage">',_l("You are over your disk quota."),_l("Tool execution is on hold until your disk usage drops below your allocated quota."),"</div>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="history-dataset-actions">','<div class="btn-group">','<button class="history-select-all-datasets-btn btn btn-default"','data-mode="select">',_l("All"),"</button>",'<button class="history-deselect-all-datasets-btn btn btn-default"','data-mode="select">',_l("None"),"</button>","</div>",'<button class="history-dataset-action-popup-btn btn btn-default">',_l("For all selected"),"...</button>","</div>","</div>",'<div class="datasets-list"></div>','<div class="empty-history-message infomessagesmall">',_l("Your history is empty. Click 'Get Data' on the left pane to start"),"</div>"].join("");h.templates={historyPanel:function(j){return _.template(i,j,{variable:"history"})}};return{ReadOnlyHistoryPanel:h}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/dataset/hda-base","mvc/user/user-model","mvc/base-mvc"],function(f,b,a,e){var h=e.SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(l){var k="expandedHdas";this.save(k,_.extend(this.get(k),_.object([l],[true])))},removeExpandedHda:function(l){var k="expandedHdas";this.save(k,_.omit(this.get(k),l))},toString:function(){return"HistoryPrefs("+this.id+")"}});h.storageKeyPrefix="history:";h.historyStorageKey=function d(k){if(!k){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+k)}return(h.storageKeyPrefix+k)};h.get=function c(k){return new h({id:h.historyStorageKey(k)})};h.clearAll=function g(l){for(var k in sessionStorage){if(k.indexOf(h.storageKeyPrefix)===0){sessionStorage.removeItem(k)}}};var i=Backbone.View.extend(e.LoggableMixin).extend({HDAViewClass:b.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(k){k=k||{};if(k.logger){this.logger=k.logger}this.log(this+".initialize:",k);this.linkTarget=k.linkTarget||"_blank";this.fxSpeed=_.has(k,"fxSpeed")?(k.fxSpeed):(this.fxSpeed);this.filters=[];this.searchFor="";this.findContainerFn=k.findContainerFn;this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this._setUpListeners();var l=_.pick(k,"initiallyExpanded","show_deleted","show_hidden");this.setModel(this.model,l,false);if(k.onready){k.onready.call(this)}},_setUpListeners:function(){this.on("error",function(l,o,k,n,m){this.errorHandler(l,o,k,n,m)});this.on("loading-history",function(){this._showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this._hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(k){this.log(this+"",arguments)},this)}return this},errorHandler:function(m,p,l,o,n){console.error(m,p,l,o,n);if(p&&p.status===0&&p.readyState===0){}else{if(p&&p.status===502){}else{var k=this._parseErrorMessage(m,p,l,o,n);if(!this.$messages().is(":visible")){this.once("rendered",function(){this.displayMessage("error",k.message,k.details)})}else{this.displayMessage("error",k.message,k.details)}}}},_parseErrorMessage:function(n,r,m,q,p){var l=Galaxy.currUser,k={message:this._bePolite(q),details:{user:(l instanceof a.User)?(l.toJSON()):(l+""),source:(n instanceof Backbone.Model)?(n.toJSON()):(n+""),xhr:r,options:(r)?(_.omit(m,"xhr")):(m)}};_.extend(k.details,p||{});if(r&&_.isFunction(r.getAllResponseHeaders)){var o=r.getAllResponseHeaders();o=_.compact(o.split("\n"));o=_.map(o,function(s){return s.split(": ")});k.details.xhr.responseHeaders=_.object(o)}return k},_bePolite:function(k){k=k||_l("An error occurred while getting updates from the server");return k+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(m,l,k,o){var n=function(p){return _.keys(h.get(p.id).get("expandedHdas"))};return this.loadHistory(m,l,k,o,n)},loadHistory:function(n,m,l,q,o){var k=this;m=m||{};k.trigger("loading-history",k);var p=f.History.getHistoryData(n,{historyFn:l,hdaFn:q,hdaDetailIds:m.initiallyExpanded||o});return k._loadHistoryFromXHR(p,m).fail(function(t,r,s){k.trigger("error",k,t,m,_l("An error was encountered while "+r),{historyId:n,history:s||{}})}).always(function(){k.trigger("loading-done",k)})},_loadHistoryFromXHR:function(m,l){var k=this;m.then(function(n,o){k.JSONToModel(n,o,l)});m.fail(function(o,n){k.render()});return m},JSONToModel:function(n,k,l){this.log("JSONToModel:",n,k,l);l=l||{};var m=new f.History(n,k,l);this.setModel(m);return this},setModel:function(l,k,m){k=k||{};m=(m!==undefined)?(m):(true);this.log("setModel:",l,k,m);this.freeModel();this.selectedHdaIds=[];if(l){this.model=l;if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(k.initiallyExpanded,k.show_deleted,k.show_hidden);this._setUpModelEventHandlers();this.trigger("new-model",this)}if(m){this.render()}return this},freeModel:function(){if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.freeHdaViews();return this},freeHdaViews:function(){this.hdaViews={};return this},_setUpWebStorage:function(l,k,m){this.storage=new h({id:h.historyStorageKey(this.model.get("id"))});if(_.isObject(l)){this.storage.set("exandedHdas",l)}if(_.isBoolean(k)){this.storage.set("show_deleted",k)}if(_.isBoolean(m)){this.storage.set("show_hidden",m)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get());return this},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(l,n,k,m){this.errorHandler(l,n,k,m)},this);return this},render:function(m,n){this.log("render:",m,n);m=(m===undefined)?(this.fxSpeed):(m);var k=this,l;if(this.model){l=this.renderModel()}else{l=this.renderWithoutModel()}$(k).queue("fx",[function(o){if(m&&k.$el.is(":visible")){k.$el.fadeOut(m,o)}else{o()}},function(o){k.$el.empty();if(l){k.$el.append(l.children())}o()},function(o){if(m&&!k.$el.is(":visible")){k.$el.fadeIn(m,o)}else{o()}},function(o){if(n){n.call(this)}k.trigger("rendered",this);o()}]);return this},renderWithoutModel:function(){var k=$("<div/>"),l=$("<div/>").addClass("message-container").css({margin:"4px"});return k.append(l)},renderModel:function(){var k=$("<div/>");k.append(i.templates.historyPanel(this.model.toJSON()));this.$emptyMessage(k).text(this.emptyMsg);k.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(k);this.renderHdas(k);return k},_renderEmptyMsg:function(m){var l=this,k=l.$emptyMessage(m);if(!_.isEmpty(l.hdaViews)){k.hide()}else{if(l.searchFor){k.text(l.noneFoundMsg).show()}else{k.text(l.emptyMsg).show()}}return this},_renderSearchButton:function(k){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(k){k=k||this.$el;k.find("[title]").tooltip({placement:"bottom"});this._setUpSearchInput(k.find(".history-search-controls .history-search-input"));return this},$container:function(){return(this.findContainerFn)?(this.findContainerFn.call(this)):(this.$el.parent())},$datasetsList:function(k){return(k||this.$el).find(".datasets-list")},$messages:function(k){return(k||this.$el).find(".message-container")},$emptyMessage:function(k){return(k||this.$el).find(".empty-history-message")},renderHdas:function(l){l=l||this.$el;var k=this,n={},m=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);this.$datasetsList(l).empty();if(m.length){m.each(function(p){var o=p.get("id"),q=k._createHdaView(p);n[o]=q;if(_.contains(k.selectedHdaIds,o)){q.selected=true}k.attachHdaView(q.render(),l)})}this.hdaViews=n;this._renderEmptyMsg(l);return this.hdaViews},_createHdaView:function(l){var k=l.get("id"),m=new this.HDAViewClass({model:l,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[k],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(m);return m},_setUpHdaListeners:function(l){var k=this;l.on("error",function(n,p,m,o){k.errorHandler(n,p,m,o)});l.on("body-expanded",function(m){k.storage.addExpandedHda(m)});l.on("body-collapsed",function(m){k.storage.removeExpandedHda(m)});return this},attachHdaView:function(m,l){l=l||this.$el;var k=this.$datasetsList(l);k.prepend(m.$el);return this},addHdaView:function(n){this.log("add."+this,n);var l=this;if(!n.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return l}$({}).queue([function m(p){var o=l.$emptyMessage();if(o.is(":visible")){o.fadeOut(l.fxSpeed,p)}else{p()}},function k(o){var p=l._createHdaView(n);l.hdaViews[n.id]=p;p.render().$el.hide();l.scrollToTop();l.attachHdaView(p);p.$el.slideDown(l.fxSpeed)}]);return l},refreshHdas:function(l,k){if(this.model){return this.model.refresh(l,k)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(k){k.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{});return this},toggleShowDeleted:function(k){k=(k!==undefined)?(k):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",k);this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(k){k=(k!==undefined)?(k):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",k);this.renderHdas();return this.storage.get("show_hidden")},_setUpSearchInput:function(l){var m=this,n=".history-search-input";function k(o){if(m.model.hdas.haveDetails()){m.searchHdas(o);return}m.$el.find(n).searchInput("toggle-loading");m.model.hdas.fetchAllDetails({silent:true}).always(function(){m.$el.find(n).searchInput("toggle-loading")}).done(function(){m.searchHdas(o)})}l.searchInput({initialVal:m.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:k,onsearch:_.bind(this.searchHdas,this),onclear:_.bind(this.clearHdaSearch,this)});return l},toggleSearchControls:function(m,k){var l=this.$el.find(".history-search-controls"),n=(jQuery.type(m)==="number")?(m):(this.fxSpeed);k=(k!==undefined)?(k):(!l.is(":visible"));if(k){l.slideDown(n,function(){$(this).find("input").focus()})}else{l.slideUp(n)}return k},searchHdas:function(k){var l=this;this.searchFor=k;this.filters=[function(m){return m.matchesAll(l.searchFor)}];this.trigger("search:searching",k,this);this.renderHdas();return this},clearHdaSearch:function(k){this.searchFor="";this.filters=[];this.trigger("search:clear",this);this.renderHdas();return this},_showLoadingIndicator:function(l,k,m){k=(k!==undefined)?(k):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,m)}else{this.$el.fadeOut(k);this.indicator.show(l,k,m)}},_hideLoadingIndicator:function(k,l){k=(k!==undefined)?(k):(this.fxSpeed);if(this.indicator){this.indicator.hide(k,l)}},displayMessage:function(p,q,o){var m=this;this.scrollToTop();var n=this.$messages(),k=$("<div/>").addClass(p+"message").html(q);if(!_.isEmpty(o)){var l=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(m._messageToModalOptions(p,q,o));return false});k.append(" ",l)}return n.html(k)},_messageToModalOptions:function(o,q,n){var k=this,p=$("<div/>"),m={title:"Details"};function l(r){r=_.omit(r,_.functions(r));return["<table>",_.map(r,function(t,s){t=(_.isObject(t))?(l(t)):(t);return'<tr><td style="vertical-align: top; color: grey">'+s+'</td><td style="padding-left: 8px">'+t+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(n)){m.body=p.append(l(n))}else{m.body=p.html(n)}m.buttons={Ok:function(){Galaxy.modal.hide();k.clearMessages()}};return m},clearMessages:function(){this.$messages().empty();return this},scrollPosition:function(){return this.$container().scrollTop()},scrollTo:function(k){this.$container().scrollTop(k);return this},scrollToTop:function(){this.$container().scrollTop(0);return this},scrollToId:function(l){if((!l)||(!this.hdaViews[l])){return this}var k=this.hdaViews[l];this.scrollTo(k.el.offsetTop);return this},scrollToHid:function(k){var l=this.model.hdas.getByHid(k);if(!l){return this}return this.scrollToId(l.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});var j=['<div class="history-controls">','<div class="history-search-controls">','<div class="history-search-input"></div>',"</div>",'<div class="history-title">',"<% if( history.name ){ %>",'<div class="history-name"><%= history.name %></div>',"<% } %>","</div>",'<div class="history-subtitle clear">',"<% if( history.nice_size ){ %>",'<div class="history-size"><%= history.nice_size %></div>',"<% } %>",'<div class="history-secondary-actions"></div>',"</div>","<% if( history.deleted ){ %>",'<div class="warningmessagesmall"><strong>',_l("You are currently viewing a deleted history!"),"</strong></div>","<% } %>",'<div class="message-container">',"<% if( history.message ){ %>",'<div class="<%= history.status %>message"><%= history.message %></div>',"<% } %>","</div>",'<div class="quota-message errormessage">',_l("You are over your disk quota."),_l("Tool execution is on hold until your disk usage drops below your allocated quota."),"</div>",'<div class="tags-display"></div>','<div class="annotation-display"></div>','<div class="history-dataset-actions">','<div class="btn-group">','<button class="history-select-all-datasets-btn btn btn-default"','data-mode="select">',_l("All"),"</button>",'<button class="history-deselect-all-datasets-btn btn btn-default"','data-mode="select">',_l("None"),"</button>","</div>",'<button class="history-dataset-action-popup-btn btn btn-default">',_l("For all selected"),"...</button>","</div>","</div>",'<div class="datasets-list"></div>','<div class="empty-history-message infomessagesmall">',_l("Your history is empty. Click 'Get Data' on the left pane to start"),"</div>"].join("");i.templates={historyPanel:function(k){return _.template(j,k,{variable:"history"})}};return{ReadOnlyHistoryPanel:i}});
\ No newline at end of file
diff -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b -r ec75df18a967a60c8026b6a24ddfe37351ba22e5 templates/webapps/galaxy/history/history_panel.mako
--- a/templates/webapps/galaxy/history/history_panel.mako
+++ b/templates/webapps/galaxy/history/history_panel.mako
@@ -15,14 +15,10 @@
el : $( "${selector_to_attach_to}" ),
linkTarget : 'galaxy_main',
onready : function loadAsCurrentHistoryPanel(){
- var panel = this;
this.connectToQuotaMeter( Galaxy.quotaMeter )
.connectToOptionsMenu( Galaxy.historyOptionsMenu );
- this.loadCurrentHistory()
- .fail( function(){
- panel.render();
- });
- }
+ this.loadCurrentHistory();
+ }
});
Galaxy.currHistoryPanel = currPanel;
});
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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4ae7e5848f7f/
Changeset: 4ae7e5848f7f
User: nsoranzo
Date: 2014-03-27 17:03:16
Summary: Add BCF datatype sniffing, so BCF files are not uncompressed during upload.
Affected #: 1 file
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r 4ae7e5848f7f555e24540518ba95582f6af1cd58 lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -69,6 +69,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def get_mime( self ):
"""Returns the mime type of the datatype"""
return 'application/octet-stream'
@@ -96,6 +97,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -133,12 +135,14 @@
version = line.split()[1]
break
return version
+
def _is_coordinate_sorted( self, file_name ):
"""See if the input BAM file is sorted from the header information."""
params = [ "samtools", "view", "-H", file_name ]
output = subprocess.Popen( params, stderr=subprocess.PIPE, stdout=subprocess.PIPE ).communicate()[0]
# find returns -1 if string is not found
return output.find( "SO:coordinate" ) != -1 or output.find( "SO:sorted" ) != -1
+
def dataset_content_needs_grooming( self, file_name ):
"""See if file_name is a sorted BAM file"""
version = self._get_samtools_version()
@@ -186,6 +190,7 @@
except OSError:
pass
return False
+
def groom_dataset_content( self, file_name ):
"""
Ensures that the Bam file contents are sorted. This function is called
@@ -221,8 +226,10 @@
# Remove temp file and empty temporary directory
os.unlink( stderr_name )
os.rmdir( tmp_dir )
+
def init_meta( self, dataset, copy_from=None ):
Binary.init_meta( self, dataset, copy_from=copy_from )
+
def set_meta( self, dataset, overwrite = True, **kwd ):
""" Creates the index for the BAM file. """
# These metadata values are not accessible by users, always overwrite
@@ -247,6 +254,7 @@
dataset.metadata.bam_index = index_file
# Remove temp file
os.unlink( stderr_name )
+
def sniff( self, filename ):
# BAM is compressed in the BGZF format, and must not be uncompressed in Galaxy.
# The first 4 bytes of any bam file is 'BAM\1', and the file is binary.
@@ -257,6 +265,7 @@
return False
except:
return False
+
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "Binary bam alignments file"
@@ -264,6 +273,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -355,6 +365,24 @@
Binary.register_sniffable_binary_format("bam", "bam", Bam)
+class Bcf( Binary):
+ """Class describing a BCF file"""
+ file_ext = "bcf"
+
+ def sniff( self, filename ):
+ # BCF is compressed in the BGZF format, and must not be uncompressed in Galaxy.
+ # The first 3 bytes of any bcf file is 'BCF', and the file is binary.
+ try:
+ header = gzip.open( filename ).read(3)
+ if binascii.b2a_hex( header ) == binascii.hexlify( 'BCF' ):
+ return True
+ return False
+ except:
+ return False
+
+Binary.register_sniffable_binary_format("bcf", "bcf", Bcf)
+
+
class H5( Binary ):
"""Class describing an HDF5 file"""
file_ext = "h5"
@@ -366,6 +394,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -386,6 +415,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -401,6 +431,7 @@
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
+
def sniff( self, filename ):
# The first 4 bytes of any sff file is '.sff', and the file is binary. For details
# about the format, see http://www.ncbi.nlm.nih.gov/Traces/trace.cgi?cmd=show&f=formats&m=doc&s=for…
@@ -411,6 +442,7 @@
return False
except:
return False
+
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "Binary sff file"
@@ -418,6 +450,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -440,14 +473,17 @@
Binary.__init__( self, **kwd )
self._magic = 0x888FFC26
self._name = "BigWig"
+
def _unpack( self, pattern, handle ):
return struct.unpack( pattern, handle.read( struct.calcsize( pattern ) ) )
+
def sniff( self, filename ):
try:
magic = self._unpack( "I", open( filename ) )
return magic[0] == self._magic
except:
return False
+
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "Binary UCSC %s file" % self._name
@@ -455,6 +491,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -493,12 +530,14 @@
return True
except IOError:
return False
+
def set_peek(self, dataset, is_multi_byte=False):
if not dataset.dataset.purged:
dataset.peek = "Binary TwoBit format nucleotide file"
dataset.blurb = data.nice_size(dataset.get_size())
else:
return super(TwoBit, self).set_peek(dataset, is_multi_byte)
+
def display_peek(self, dataset):
try:
return dataset.peek
https://bitbucket.org/galaxy/galaxy-central/commits/6f9d3980f9d8/
Changeset: 6f9d3980f9d8
User: nsoranzo
Date: 2014-03-27 17:19:39
Summary: Use new Bcf class.
Affected #: 1 file
diff -r 4ae7e5848f7f555e24540518ba95582f6af1cd58 -r 6f9d3980f9d87af158e11cabad5df892efbb69ad datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -189,7 +189,7 @@
<display file="igv/vcf.xml" /><display file="rviewer/vcf.xml" inherit="True"/></datatype>
- <datatype extension="bcf" type="galaxy.datatypes.binary:Binary" subclass="True" display_in_upload="True"/>
+ <datatype extension="bcf" type="galaxy.datatypes.binary:Bcf" mimetype="application/octet-stream" display_in_upload="True"/><datatype extension="velvet" type="galaxy.datatypes.assembly:Velvet" display_in_upload="false"/><datatype extension="wig" type="galaxy.datatypes.interval:Wiggle" display_in_upload="true" description="The wiggle format is line-oriented. Wiggle data is preceded by a track definition line, which adds a number of options for controlling the default display of this track." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Wig"><converter file="wig_to_bigwig_converter.xml" target_datatype="bigwig"/>
https://bitbucket.org/galaxy/galaxy-central/commits/4d99cae3baac/
Changeset: 4d99cae3baac
User: dannon
Date: 2014-03-27 17:37:21
Summary: Merged in nsoranzo/galaxy-central (pull request #353)
Add BCF datatype sniffing, so BCF files are not uncompressed during upload.
Affected #: 2 files
diff -r c4f468e43b93406804bd7665a2755b16f8bac463 -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b datatypes_conf.xml.sample
--- a/datatypes_conf.xml.sample
+++ b/datatypes_conf.xml.sample
@@ -189,7 +189,7 @@
<display file="igv/vcf.xml" /><display file="rviewer/vcf.xml" inherit="True"/></datatype>
- <datatype extension="bcf" type="galaxy.datatypes.binary:Binary" subclass="True" display_in_upload="True"/>
+ <datatype extension="bcf" type="galaxy.datatypes.binary:Bcf" mimetype="application/octet-stream" display_in_upload="True"/><datatype extension="velvet" type="galaxy.datatypes.assembly:Velvet" display_in_upload="false"/><datatype extension="wig" type="galaxy.datatypes.interval:Wiggle" display_in_upload="true" description="The wiggle format is line-oriented. Wiggle data is preceded by a track definition line, which adds a number of options for controlling the default display of this track." description_url="https://wiki.galaxyproject.org/Learn/Datatypes#Wig"><converter file="wig_to_bigwig_converter.xml" target_datatype="bigwig"/>
diff -r c4f468e43b93406804bd7665a2755b16f8bac463 -r 4d99cae3baac3d5c136541aaed5aa640881e6a5b lib/galaxy/datatypes/binary.py
--- a/lib/galaxy/datatypes/binary.py
+++ b/lib/galaxy/datatypes/binary.py
@@ -69,6 +69,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def get_mime( self ):
"""Returns the mime type of the datatype"""
return 'application/octet-stream'
@@ -96,6 +97,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -133,12 +135,14 @@
version = line.split()[1]
break
return version
+
def _is_coordinate_sorted( self, file_name ):
"""See if the input BAM file is sorted from the header information."""
params = [ "samtools", "view", "-H", file_name ]
output = subprocess.Popen( params, stderr=subprocess.PIPE, stdout=subprocess.PIPE ).communicate()[0]
# find returns -1 if string is not found
return output.find( "SO:coordinate" ) != -1 or output.find( "SO:sorted" ) != -1
+
def dataset_content_needs_grooming( self, file_name ):
"""See if file_name is a sorted BAM file"""
version = self._get_samtools_version()
@@ -186,6 +190,7 @@
except OSError:
pass
return False
+
def groom_dataset_content( self, file_name ):
"""
Ensures that the Bam file contents are sorted. This function is called
@@ -221,8 +226,10 @@
# Remove temp file and empty temporary directory
os.unlink( stderr_name )
os.rmdir( tmp_dir )
+
def init_meta( self, dataset, copy_from=None ):
Binary.init_meta( self, dataset, copy_from=copy_from )
+
def set_meta( self, dataset, overwrite = True, **kwd ):
""" Creates the index for the BAM file. """
# These metadata values are not accessible by users, always overwrite
@@ -247,6 +254,7 @@
dataset.metadata.bam_index = index_file
# Remove temp file
os.unlink( stderr_name )
+
def sniff( self, filename ):
# BAM is compressed in the BGZF format, and must not be uncompressed in Galaxy.
# The first 4 bytes of any bam file is 'BAM\1', and the file is binary.
@@ -257,6 +265,7 @@
return False
except:
return False
+
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "Binary bam alignments file"
@@ -264,6 +273,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -355,6 +365,24 @@
Binary.register_sniffable_binary_format("bam", "bam", Bam)
+class Bcf( Binary):
+ """Class describing a BCF file"""
+ file_ext = "bcf"
+
+ def sniff( self, filename ):
+ # BCF is compressed in the BGZF format, and must not be uncompressed in Galaxy.
+ # The first 3 bytes of any bcf file is 'BCF', and the file is binary.
+ try:
+ header = gzip.open( filename ).read(3)
+ if binascii.b2a_hex( header ) == binascii.hexlify( 'BCF' ):
+ return True
+ return False
+ except:
+ return False
+
+Binary.register_sniffable_binary_format("bcf", "bcf", Bcf)
+
+
class H5( Binary ):
"""Class describing an HDF5 file"""
file_ext = "h5"
@@ -366,6 +394,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -386,6 +415,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -401,6 +431,7 @@
def __init__( self, **kwd ):
Binary.__init__( self, **kwd )
+
def sniff( self, filename ):
# The first 4 bytes of any sff file is '.sff', and the file is binary. For details
# about the format, see http://www.ncbi.nlm.nih.gov/Traces/trace.cgi?cmd=show&f=formats&m=doc&s=for…
@@ -411,6 +442,7 @@
return False
except:
return False
+
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "Binary sff file"
@@ -418,6 +450,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -440,14 +473,17 @@
Binary.__init__( self, **kwd )
self._magic = 0x888FFC26
self._name = "BigWig"
+
def _unpack( self, pattern, handle ):
return struct.unpack( pattern, handle.read( struct.calcsize( pattern ) ) )
+
def sniff( self, filename ):
try:
magic = self._unpack( "I", open( filename ) )
return magic[0] == self._magic
except:
return False
+
def set_peek( self, dataset, is_multi_byte=False ):
if not dataset.dataset.purged:
dataset.peek = "Binary UCSC %s file" % self._name
@@ -455,6 +491,7 @@
else:
dataset.peek = 'file does not exist'
dataset.blurb = 'file purged from disk'
+
def display_peek( self, dataset ):
try:
return dataset.peek
@@ -493,12 +530,14 @@
return True
except IOError:
return False
+
def set_peek(self, dataset, is_multi_byte=False):
if not dataset.dataset.purged:
dataset.peek = "Binary TwoBit format nucleotide file"
dataset.blurb = data.nice_size(dataset.get_size())
else:
return super(TwoBit, self).set_peek(dataset, is_multi_byte)
+
def display_peek(self, dataset):
try:
return dataset.peek
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: History/HDA API: normalize exceptions and exception codes; Fix ability to history/view a history shared with another user
by commits-noreply@bitbucket.org 27 Mar '14
by commits-noreply@bitbucket.org 27 Mar '14
27 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c4f468e43b93/
Changeset: c4f468e43b93
User: carlfeberhard
Date: 2014-03-27 17:17:18
Summary: History/HDA API: normalize exceptions and exception codes; Fix ability to history/view a history shared with another user
Affected #: 14 files
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/exceptions/__init__.py
--- a/lib/galaxy/exceptions/__init__.py
+++ b/lib/galaxy/exceptions/__init__.py
@@ -68,6 +68,11 @@
status_code = 400
err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+class AuthenticationRequired( MessageException ):
+ status_code = 403
+ #TODO: as 401 and send WWW-Authenticate: ???
+ err_code = error_codes.USER_NO_API_KEY
+
class ItemAccessibilityException( MessageException ):
status_code = 403
err_code = error_codes.USER_CANNOT_ACCESS_ITEM
@@ -76,6 +81,10 @@
status_code = 403
err_code = error_codes.USER_DOES_NOT_OWN_ITEM
+class ConfigDoesNotAllowException( MessageException ):
+ status_code = 403
+ err_code = error_codes.CONFIG_DOES_NOT_ALLOW
+
class ObjectNotFound( MessageException ):
""" Accessed object was not found """
status_code = 404
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -52,7 +52,7 @@
{
"name": "USER_NO_API_KEY",
"code": 403001,
- "message": "API Authentication Required for this request"
+ "message": "API authentication required for this request"
},
{
"name": "USER_CANNOT_ACCESS_ITEM",
@@ -65,6 +65,11 @@
"message": "User does not own specified item."
},
{
+ "name": "CONFIG_DOES_NOT_ALLOW",
+ "code": 403004,
+ "message": "The configuration of this Galaxy instance does not allow that operation"
+ },
+ {
"name": "USER_OBJECT_NOT_FOUND",
"code": 404001,
"message": "No such object found."
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -13,6 +13,7 @@
from paste.httpexceptions import HTTPBadRequest, HTTPInternalServerError
from paste.httpexceptions import HTTPNotImplemented, HTTPRequestRangeNotSatisfiable
+from galaxy import exceptions
from galaxy.exceptions import ItemAccessibilityException, ItemDeletionException, ItemOwnershipException
from galaxy.exceptions import MessageException
@@ -183,20 +184,22 @@
# should probably be in sep. serializer class/object _used_ by controller
def validate_and_sanitize_basestring( self, key, val ):
if not isinstance( val, basestring ):
- raise ValueError( '%s must be a string or unicode: %s' %( key, str( type( val ) ) ) )
+ raise exceptions.RequestParameterInvalidException( '%s must be a string or unicode: %s'
+ %( key, str( type( val ) ) ) )
return unicode( sanitize_html( val, 'utf-8', 'text/html' ), 'utf-8' )
def validate_and_sanitize_basestring_list( self, key, val ):
- if not isinstance( val, list ):
- raise ValueError( '%s must be a list of strings: %s' %( key, str( type( val ) ) ) )
try:
+ assert isinstance( val, list )
return [ unicode( sanitize_html( t, 'utf-8', 'text/html' ), 'utf-8' ) for t in val ]
- except TypeError, type_err:
- raise ValueError( '%s must be a list of strings: %s' %( key, str( type_err ) ) )
+ except ( AssertionError, TypeError ), err:
+ raise exceptions.RequestParameterInvalidException( '%s must be a list of strings: %s'
+ %( key, str( type( val ) ) ) )
def validate_boolean( self, key, val ):
if not isinstance( val, bool ):
- raise ValueError( '%s must be a boolean: %s' %( key, str( type( val ) ) ) )
+ raise exceptions.RequestParameterInvalidException( '%s must be a boolean: %s'
+ %( key, str( type( val ) ) ) )
return val
#TODO:
@@ -361,7 +364,9 @@
""" Mixin for controllers that use History objects. """
def get_history( self, trans, id, check_ownership=True, check_accessible=False, deleted=None ):
- """Get a History from the database by id, verifying ownership."""
+ """
+ Get a History from the database by id, verifying ownership.
+ """
history = self.get_object( trans, id, 'History',
check_ownership=check_ownership, check_accessible=check_accessible, deleted=deleted )
history = self.security_check( trans, history, check_ownership, check_accessible )
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/web/framework/__init__.py
--- a/lib/galaxy/web/framework/__init__.py
+++ b/lib/galaxy/web/framework/__init__.py
@@ -296,7 +296,8 @@
if user_required and trans.anonymous:
error_code = error_codes.USER_NO_API_KEY
# Use error codes default error message.
- return __api_error_response( trans, err_code=error_code, status_code=403 )
+ err_msg = "API authentication required for this request"
+ return __api_error_response( trans, err_code=error_code, err_msg=err_msg, status_code=403 )
if trans.request.body:
try:
kwargs['payload'] = __extract_payload_from_request(trans, func, kwargs)
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/webapps/galaxy/api/histories.py
--- a/lib/galaxy/webapps/galaxy/api/histories.py
+++ b/lib/galaxy/webapps/galaxy/api/histories.py
@@ -7,11 +7,6 @@
import pkg_resources
pkg_resources.require( "Paste" )
-from paste.httpexceptions import HTTPBadRequest
-from paste.httpexceptions import HTTPForbidden
-from paste.httpexceptions import HTTPInternalServerError
-from paste.httpexceptions import HTTPException
-
from galaxy import exceptions
from galaxy import web
from galaxy.web import _future_expose_api as expose_api
@@ -24,6 +19,9 @@
from galaxy.web.base.controller import ExportsHistoryMixin
from galaxy.web.base.controller import ImportsHistoryMixin
+from galaxy.model import orm
+
+from galaxy import util
from galaxy.util import string_as_bool
from galaxy.util import restore_text
from galaxy.web import url_for
@@ -35,6 +33,19 @@
class HistoriesController( BaseAPIController, UsesHistoryMixin, UsesTagsMixin,
ExportsHistoryMixin, ImportsHistoryMixin ):
+ def __init__( self, app ):
+ super( HistoriesController, self ).__init__( app )
+ self.mgrs = util.bunch.Bunch(
+ histories = HistoryManager()
+ )
+
+ def _decode_id( self, trans, id ):
+ try:
+ return trans.security.decode_id( id )
+ except:
+ raise exceptions.MalformedId( "Malformed History id ( %s ) specified, unable to decode"
+ % ( str( id ) ), type='error' )
+
@expose_api_anonymous
def index( self, trans, deleted='False', **kwd ):
"""
@@ -55,24 +66,15 @@
rval = []
deleted = string_as_bool( deleted )
- if trans.user:
- histories = self.get_user_histories( trans, user=trans.user, only_deleted=deleted )
-
- for history in histories:
- item = history.to_dict(value_mapper={'id': trans.security.encode_id})
- item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) )
- rval.append( item )
-
- elif trans.galaxy_session.current_history:
- #No user, this must be session authentication with an anonymous user.
- history = trans.galaxy_session.current_history
- item = history.to_dict(value_mapper={'id': trans.security.encode_id})
+ histories = self.mgrs.histories.by_user( trans, user=trans.user, only_deleted=deleted )
+ for history in histories:
+ item = history.to_dict( value_mapper={ 'id': trans.security.encode_id } )
item['url'] = url_for( 'history', id=trans.security.encode_id( history.id ) )
- rval.append(item)
+ rval.append( item )
return rval
- @web.expose_api_anonymous
+ @expose_api_anonymous
def show( self, trans, id, deleted='False', **kwd ):
"""
show( trans, id, deleted='False' )
@@ -82,10 +84,13 @@
return the deleted history with ``id``
* GET /api/histories/most_recently_used:
return the most recently used history
+ * GET /api/histories/current:
+ return the current (working) history
.. note:: Anonymous users are allowed to get their current history
:type id: an encoded id string
- :param id: the encoded id of the history to query or the string 'most_recently_used'
+ :param id: the encoded id of the history to query
+ or the string 'most_recently_used' or the string 'current'
:type deleted: boolean
:param deleted: if True, allow information on a deleted history to be shown.
@@ -93,11 +98,9 @@
:returns: detailed history information from
:func:`galaxy.web.base.controller.UsesHistoryDatasetAssociationMixin.get_history_dict`
"""
- #TODO: GET /api/histories/s/{username}/{slug}
history_id = id
deleted = string_as_bool( deleted )
- #try:
if history_id == "most_recently_used":
if not trans.user or len( trans.user.galaxy_sessions ) <= 0:
return None
@@ -108,25 +111,16 @@
history = trans.get_history( create=True )
else:
- history = self.get_history( trans, history_id, check_ownership=False,
- check_accessible=True, deleted=deleted )
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=False, check_accessible=True, deleted=deleted )
+ #history = self._get_history( trans, self._decode_id( trans, history_id ),
+ # check_ownership=False, check_accessible=True, deleted=deleted )
history_data = self.get_history_dict( trans, history )
history_data[ 'contents_url' ] = url_for( 'history_contents', history_id=history_id )
-
- #except HTTPBadRequest, bad_req:
- # trans.response.status = 400
- # raise exceptions.MessageException( bad_req.detail )
- #
- #except Exception, e:
- # msg = "Error in history API at showing history detail: %s" % ( str( e ) )
- # log.exception( msg )
- # trans.response.status = 500
- # return msg
-
return history_data
- @web.expose_api
+ @expose_api
def set_as_current( self, trans, id, **kwd ):
"""
set_as_current( trans, id, **kwd )
@@ -143,22 +137,11 @@
# added as a non-ATOM API call to support the notion of a 'current/working' history
# - unique to the history resource
history_id = id
- try:
- history = self.get_history( trans, history_id, check_ownership=True, check_accessible=True )
- trans.history = history
- history_data = self.get_history_dict( trans, history )
- history_data[ 'contents_url' ] = url_for( 'history_contents', history_id=history_id )
-
- except HTTPBadRequest, bad_req:
- trans.response.status = 400
- return str( bad_req )
-
- except Exception, e:
- msg = "Error in history API when switching current history: %s" % ( str( e ) )
- log.exception( msg )
- trans.response.status = 500
- return msg
-
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=True, check_accessible=True )
+ trans.history = history
+ history_data = self.get_history_dict( trans, history )
+ history_data[ 'contents_url' ] = url_for( 'history_contents', history_id=history_id )
return history_data
@expose_api
@@ -196,14 +179,8 @@
new_history = None
# if a history id was passed, copy that history
if copy_this_history_id:
- try:
- original_history = self.get_history( trans, copy_this_history_id,
- check_ownership=False, check_accessible=True )
- except HTTPBadRequest, bad_request:
- trans.response.status = 403
- #TODO: it's either that or parse each possible detail to it's own status code
- return { 'error': bad_request.detail or 'Bad request' }
-
+ original_history = self.mgrs.histories.get( trans, self._decode_id( trans, copy_this_history_id ),
+ check_ownership=False, check_accessible=True )
hist_name = hist_name or ( "Copy of '%s'" % original_history.name )
new_history = original_history.copy( name=hist_name, target_user=trans.user )
@@ -211,20 +188,17 @@
else:
new_history = trans.app.model.History( user=trans.user, name=hist_name )
- item = {}
-
trans.sa_session.add( new_history )
trans.sa_session.flush()
-
- item = self.get_history_dict( trans, new_history )
- item['url'] = url_for( 'history', id=item['id'] )
-
if set_as_current:
trans.history = new_history
+ item = {}
+ item = self.get_history_dict( trans, new_history )
+ item['url'] = url_for( 'history', id=item['id'] )
return item
- @web.expose_api
+ @expose_api
def delete( self, trans, id, **kwd ):
"""
delete( self, trans, id, **kwd )
@@ -253,54 +227,40 @@
purge = string_as_bool( kwd['payload'].get( 'purge', False ) )
rval = { 'id' : history_id }
- try:
- history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False )
- history.deleted = True
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=True, check_accessible=False )
+ history.deleted = True
+ if purge:
+ if not trans.app.config.allow_user_dataset_purge and not trans.user_is_admin():
+ raise exceptions.ConfigDoesNotAllowException( 'This instance does not allow user dataset purging' )
- if purge:
- if not trans.app.config.allow_user_dataset_purge:
- raise HTTPForbidden( detail='This instance does not allow user dataset purging' )
+ # First purge all the datasets
+ for hda in history.datasets:
+ if hda.purged:
+ continue
+ hda.purged = True
+ trans.sa_session.add( hda )
+ trans.sa_session.flush()
- # First purge all the datasets
- for hda in history.datasets:
- if hda.purged:
- continue
- hda.purged = True
- trans.sa_session.add( hda )
+ if hda.dataset.user_can_purge:
+ try:
+ hda.dataset.full_delete()
+ trans.sa_session.add( hda.dataset )
+ except:
+ pass
+ # flush now to preserve deleted state in case of later interruption
trans.sa_session.flush()
- if hda.dataset.user_can_purge:
- try:
- hda.dataset.full_delete()
- trans.sa_session.add( hda.dataset )
- except:
- pass
- # flush now to preserve deleted state in case of later interruption
- trans.sa_session.flush()
+ # Now mark the history as purged
+ history.purged = True
+ self.sa_session.add( history )
+ rval[ 'purged' ] = True
- # Now mark the history as purged
- history.purged = True
- self.sa_session.add( history )
- rval[ 'purged' ] = True
-
- trans.sa_session.flush()
- rval[ 'deleted' ] = True
-
- except HTTPInternalServerError, http_server_err:
- log.exception( 'Histories API, delete: uncaught HTTPInternalServerError: %s, %s\n%s',
- history_id, str( kwd ), str( http_server_err ) )
- raise
- except HTTPException:
- raise
- except Exception, exc:
- log.exception( 'Histories API, delete: uncaught exception: %s, %s\n%s',
- history_id, str( kwd ), str( exc ) )
- trans.response.status = 500
- rval.update({ 'error': str( exc ) })
-
+ trans.sa_session.flush()
+ rval[ 'deleted' ] = True
return rval
- @web.expose_api
+ @expose_api
def undelete( self, trans, id, **kwd ):
"""
undelete( self, trans, id, **kwd )
@@ -314,13 +274,14 @@
:returns: 'OK' if the history was undeleted
"""
history_id = id
- history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False, deleted=True )
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=True, check_accessible=False, deleted=True )
history.deleted = False
trans.sa_session.add( history )
trans.sa_session.flush()
return 'OK'
- @web.expose_api
+ @expose_api
def update( self, trans, id, payload, **kwd ):
"""
update( self, trans, id, payload, **kwd )
@@ -340,23 +301,14 @@
any values that were different from the original and, therefore, updated
"""
#TODO: PUT /api/histories/{encoded_history_id} payload = { rating: rating } (w/ no security checks)
- try:
- history = self.get_history( trans, id, check_ownership=True, check_accessible=True )
- # validation handled here and some parsing, processing, and conversion
- payload = self._validate_and_parse_update_payload( payload )
- # additional checks here (security, etc.)
- changed = self.set_history_from_dict( trans, history, payload )
+ history_id = id
- except Exception, exception:
- log.error( 'Update of history (%s) failed: %s', id, str( exception ), exc_info=True )
- # convert to appropo HTTP code
- if( isinstance( exception, ValueError )
- or isinstance( exception, AttributeError ) ):
- # bad syntax from the validater/parser
- trans.response.status = 400
- else:
- trans.response.status = 500
- return { 'error': str( exception ) }
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=True, check_accessible=True )
+ # validation handled here and some parsing, processing, and conversion
+ payload = self._validate_and_parse_update_payload( payload )
+ # additional checks here (security, etc.)
+ changed = self.set_history_from_dict( trans, history, payload )
return changed
@@ -377,7 +329,8 @@
# PUT instead of POST because multiple requests should just result
# in one object being created.
history_id = id
- history = self.get_history( trans, history_id, check_ownership=False, check_accessible=True )
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=False, check_accessible=True )
jeha = history.latest_export
up_to_date = jeha and jeha.up_to_date
if not up_to_date:
@@ -389,7 +342,7 @@
if up_to_date and jeha.ready:
jeha_id = trans.security.encode_id( jeha.id )
- return dict( download_url=url_for( "history_archive_download", id=history_id, jeha_id=jeha_id ) )
+ return dict( download_url=url_for( "history_archive_download", id=id, jeha_id=jeha_id ) )
else:
# Valid request, just resource is not ready yet.
trans.response.status = "202 Accepted"
@@ -408,7 +361,9 @@
"""
# Seems silly to put jeha_id in here, but want GET to be immuatable?
# and this is being accomplished this way.
- history = self.get_history( trans, id, check_ownership=False, check_accessible=True )
+ history_id = id
+ history = self.mgrs.histories.get( trans, trans.security.decode_id( history_id ),
+ check_ownership=False, check_accessible=True )
matching_exports = filter( lambda e: trans.security.encode_id( e.id ) == jeha_id, history.exports )
if not matching_exports:
raise exceptions.ObjectNotFound()
@@ -452,3 +407,96 @@
pass
#log.warn( 'unknown key: %s', str( key ) )
return validated_payload
+
+
+
+
+class HistoryManager( object ):
+ #TODO: all the following would be more useful if passed the user instead of defaulting to trans.user
+
+ def get( self, trans, unencoded_id, check_ownership=True, check_accessible=True, deleted=None ):
+ """
+ Get a History from the database by id, verifying ownership.
+ """
+ # this is a replacement for UsesHistoryMixin because mixins are a bad soln/structure
+ history = trans.sa_session.query( trans.app.model.History ).get( unencoded_id )
+ if history is None:
+ raise exceptions.ObjectNotFound()
+ if deleted == True and not history.deleted:
+ raise exceptions.ItemDeletionException( 'History "%s" is not deleted' % ( history.name ), type="error" )
+ elif deleted == False and history.deleted:
+ raise exceptions.ItemDeletionException( 'History "%s" is deleted' % ( history.name ), type="error" )
+
+ history = self.secure( trans, history, check_ownership, check_accessible )
+ return history
+
+ def by_user( self, trans, user=None, include_deleted=False, only_deleted=False ):
+ """
+ Get all the histories for a given user (defaulting to `trans.user`)
+ ordered by update time and filtered on whether they've been deleted.
+ """
+ # handle default and/or anonymous user (which still may not have a history yet)
+ user = user or trans.user
+ if not user:
+ current_history = trans.get_history()
+ return [ current_history ] if current_history else []
+
+ history_model = trans.model.History
+ query = ( trans.sa_session.query( history_model )
+ .filter( history_model.user == user )
+ .order_by( orm.desc( history_model.table.c.update_time ) ) )
+ if only_deleted:
+ query = query.filter( history_model.deleted == True )
+ elif not include_deleted:
+ query = query.filter( history_model.deleted == False )
+ return query.all()
+
+ def secure( self, trans, history, check_ownership=True, check_accessible=True ):
+ """
+ checks if (a) user owns item or (b) item is accessible to user.
+ """
+ # all items are accessible to an admin
+ if trans.user and trans.user_is_admin():
+ return history
+ if check_ownership:
+ history = self.check_ownership( trans, history )
+ if check_accessible:
+ history = self.check_accessible( trans, history )
+ return history
+
+ def is_current( self, trans, history ):
+ return trans.history == history
+
+ def is_owner( self, trans, history ):
+ # anon users are only allowed to view their current history
+ if not trans.user:
+ return self.is_current( trans, history )
+ return trans.user == history.user
+
+ def check_ownership( self, trans, history ):
+ if trans.user and trans.user_is_admin():
+ return history
+ if not trans.user and not self.is_current( trans, history ):
+ raise exceptions.AuthenticationRequired( "Must be logged in to manage Galaxy histories", type='error' )
+ if self.is_owner( trans, history ):
+ return history
+ raise exceptions.ItemOwnershipException( "History is not owned by the current user", type='error' )
+
+ def is_accessible( self, trans, history ):
+ # admin always have access
+ if trans.user and trans.user_is_admin():
+ return True
+ # owner has implicit access
+ if self.is_owner( trans, history ):
+ return True
+ # importable and shared histories are always accessible
+ if history.importable:
+ return True
+ if trans.user in history.users_shared_with_dot_users:
+ return True
+ return False
+
+ def check_accessible( self, trans, history ):
+ if self.is_accessible( trans, history ):
+ return history
+ raise exceptions.ItemAccessibilityException( "History is not accessible to the current user", type='error' )
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/webapps/galaxy/api/history_contents.py
--- a/lib/galaxy/webapps/galaxy/api/history_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/history_contents.py
@@ -20,6 +20,8 @@
from galaxy.web.base.controller import url_for
from galaxy.util.sanitize_html import sanitize_html
+from galaxy.webapps.galaxy.api import histories
+
import logging
log = logging.getLogger( __name__ )
@@ -27,6 +29,20 @@
class HistoryContentsController( BaseAPIController, UsesHistoryDatasetAssociationMixin, UsesHistoryMixin,
UsesLibraryMixin, UsesLibraryMixinItems, UsesTagsMixin ):
+ def __init__( self, app ):
+ super( HistoryContentsController, self ).__init__( app )
+ self.mgrs = util.bunch.Bunch(
+ histories = histories.HistoryManager(),
+ hdas = HDAManager()
+ )
+
+ def _decode_id( self, trans, id ):
+ try:
+ return trans.security.decode_id( id )
+ except:
+ raise exceptions.MalformedId( "Malformed History id ( %s ) specified, unable to decode"
+ % ( str( id ) ), type='error' )
+
@expose_api_anonymous
def index( self, trans, history_id, ids=None, **kwd ):
"""
@@ -56,53 +72,49 @@
:func:`galaxy.web.base.controller.UsesHistoryDatasetAssociationMixin.get_hda_dict`
"""
rval = []
- try:
- # get the history, if anon user and requesting current history - allow it
- if( ( trans.user == None )
- and ( history_id == trans.security.encode_id( trans.history.id ) ) ):
- #TODO:?? is secure?
- history = trans.history
- # otherwise, check permissions for the history first
- else:
- history = self.get_history( trans, history_id, check_ownership=False, check_accessible=True )
- # Allow passing in type or types - for continuity rest of methods
- # take in type - but this one can be passed multiple types and
- # type=dataset,dataset_collection is a bit silly.
- types = kwd.get( 'type', kwd.get( 'types', None ) ) or []
- if types:
- types = util.listify(types)
- else:
- types = [ 'dataset' ]
+ # get the history, if anon user and requesting current history - allow it
+ if( ( trans.user == None )
+ and ( history_id == trans.security.encode_id( trans.history.id ) ) ):
+ history = trans.history
+ # otherwise, check permissions for the history first
+ else:
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=False, check_accessible=True )
- contents_kwds = {'types': types}
- if ids:
- ids = map( lambda id: trans.security.decode_id( id ), ids.split( ',' ) )
- contents_kwds[ 'ids' ] = ids
- # If explicit ids given, always used detailed result.
- details = 'all'
- else:
- contents_kwds[ 'deleted' ] = kwd.get( 'deleted', None )
- contents_kwds[ 'visible' ] = kwd.get( 'visible', None )
- # details param allows a mixed set of summary and detailed hdas
- #TODO: this is getting convoluted due to backwards compat
- details = kwd.get( 'details', None ) or []
- if details and details != 'all':
- details = util.listify( details )
+ # Allow passing in type or types - for continuity rest of methods
+ # take in type - but this one can be passed multiple types and
+ # type=dataset,dataset_collection is a bit silly.
+ types = kwd.get( 'type', kwd.get( 'types', None ) ) or []
+ if types:
+ types = util.listify(types)
+ else:
+ types = [ 'dataset' ]
- for content in history.contents_iter( **contents_kwds ):
- if isinstance(content, trans.app.model.HistoryDatasetAssociation):
- encoded_content_id = trans.security.encode_id( content.id )
- detailed = details == 'all' or ( encoded_content_id in details )
- if detailed:
- rval.append( self._detailed_hda_dict( trans, content ) )
- else:
- rval.append( self._summary_hda_dict( trans, history_id, content ) )
- except Exception, e:
- # for errors that are not specific to one hda (history lookup or summary list)
- rval = "Error in history API at listing contents: " + str( e )
- log.error( rval + ": %s, %s" % ( type( e ), str( e ) ), exc_info=True )
- trans.response.status = 500
+ contents_kwds = {'types': types}
+ if ids:
+ ids = map( lambda id: trans.security.decode_id( id ), ids.split( ',' ) )
+ contents_kwds[ 'ids' ] = ids
+ # If explicit ids given, always used detailed result.
+ details = 'all'
+ else:
+ contents_kwds[ 'deleted' ] = kwd.get( 'deleted', None )
+ contents_kwds[ 'visible' ] = kwd.get( 'visible', None )
+ # details param allows a mixed set of summary and detailed hdas
+ #TODO: this is getting convoluted due to backwards compat
+ details = kwd.get( 'details', None ) or []
+ if details and details != 'all':
+ details = util.listify( details )
+
+ for content in history.contents_iter( **contents_kwds ):
+ if isinstance(content, trans.app.model.HistoryDatasetAssociation):
+ encoded_content_id = trans.security.encode_id( content.id )
+ detailed = details == 'all' or ( encoded_content_id in details )
+ if detailed:
+ rval.append( self._detailed_hda_dict( trans, content ) )
+ else:
+ rval.append( self._summary_hda_dict( trans, history_id, content ) )
+
return rval
#TODO: move to model or Mixin
@@ -165,23 +177,20 @@
"""
contents_type = kwd.get('type', 'dataset')
if contents_type == 'dataset':
- return self.__show_dataset( trans, id, history_id, **kwd )
+ return self.__show_dataset( trans, id, **kwd )
else:
return self.__handle_unknown_contents_type( trans, contents_type )
- def __show_dataset( self, trans, id, history_id, **kwd ):
- try:
- hda = self.get_history_dataset_association_from_ids( trans, id, history_id )
- hda_dict = self.get_hda_dict( trans, hda )
- hda_dict[ 'display_types' ] = self.get_old_display_applications( trans, hda )
- hda_dict[ 'display_apps' ] = self.get_display_apps( trans, hda )
- return hda_dict
- except Exception, e:
- msg = "Error in history API at listing dataset: %s" % ( str(e) )
- log.error( msg, exc_info=True )
- trans.response.status = 500
- return msg
+ def __show_dataset( self, trans, id, **kwd ):
+ hda = self.mgrs.hdas.get( trans, self._decode_id( trans, id ), check_ownership=False, check_accessible=True )
+ #if hda.history.id != self._decode_id( trans, history_id ):
+ # raise exceptions.ObjectNotFound( 'dataset was not found in this history' )
+ hda_dict = self.get_hda_dict( trans, hda )
+ hda_dict[ 'display_types' ] = self.get_old_display_applications( trans, hda )
+ hda_dict[ 'display_apps' ] = self.get_display_apps( trans, hda )
+ return hda_dict
+ #TODO: allow anon users to copy hdas, ldas
@expose_api
def create( self, trans, history_id, payload, **kwd ):
"""
@@ -207,18 +216,10 @@
:rtype: dict
:returns: dictionary containing detailed information for the new HDA
"""
- #TODO: copy existing, accessible hda - dataset controller, copy_datasets
#TODO: convert existing, accessible hda - model.DatasetInstance(or hda.datatype).get_converter_types
- # check parameters
- # retrieve history
- try:
- history = self.get_history( trans, history_id, check_ownership=True, check_accessible=False )
- except exceptions.httpexceptions.HTTPException:
- raise
- except Exception, e:
- # no way to tell if it failed bc of perms or other (all MessageExceptions)
- trans.response.status = 500
- return str( e )
+ history = self.mgrs.histories.get( trans, self._decode_id( trans, history_id ),
+ check_ownership=True, check_accessible=False )
+
type = payload.get('type', 'dataset')
if type == 'dataset':
return self.__create_dataset( trans, history, payload, **kwd )
@@ -226,53 +227,34 @@
return self.__handle_unknown_contents_type( trans, type )
def __create_dataset( self, trans, history, payload, **kwd ):
- source = payload.get('source', None)
- content = payload.get('content', None)
- if source not in ['library', 'hda'] or content is None:
- trans.response.status = 400
- return "Please define the source ('library' or 'hda') and the content."
+ source = payload.get( 'source', None )
+ if source not in ( 'library', 'hda' ):
+ raise exceptions.RequestParameterInvalidException(
+ "'source' must be either 'library' or 'hda': %s" %( source ) )
+ content = payload.get( 'content', None )
+ if content is None:
+ raise exceptions.RequestParameterMissingException( "'content' id of lda or hda is missing" )
+
# copy from library dataset
+ hda = None
if source == 'library':
- # get library data set
- try:
- ld = self.get_library_dataset( trans, content, check_ownership=False, check_accessible=False )
- assert type( ld ) is trans.app.model.LibraryDataset, (
+ ld = self.get_library_dataset( trans, content, check_ownership=False, check_accessible=False )
+ #TODO: why would get_library_dataset NOT return a library dataset?
+ if type( ld ) is not trans.app.model.LibraryDataset:
+ raise exceptions.RequestParameterInvalidException(
"Library content id ( %s ) is not a dataset" % content )
- except AssertionError, e:
- trans.response.status = 400
- return str( e )
- except Exception, e:
- return str( e )
# insert into history
hda = ld.library_dataset_dataset_association.to_history_dataset_association( history, add_to_history=True )
- trans.sa_session.flush()
- return hda.to_dict()
+
+ # copy an existing, accessible hda
elif source == 'hda':
- try:
- #NOTE: user currently only capable of copying one of their own datasets
- hda = self.get_dataset( trans, content, check_ownership=False, check_accessible=True )
- self.security_check( trans, hda.history, check_ownership=False, check_accessible=True )
- except ( exceptions.httpexceptions.HTTPRequestRangeNotSatisfiable,
- exceptions.httpexceptions.HTTPBadRequest ), id_exc:
- # wot...
- trans.response.status = 400
- return str( id_exc )
- except exceptions.MessageException, msg_exc:
- #TODO: covers most but not all user exceptions, too generic (403 v.401)
- trans.response.status = 403
- return str( msg_exc )
- except Exception, exc:
- trans.response.status = 500
- log.exception( "history: %s, source: %s, content: %s", trans.security.encode_id(history.id), source, content )
- return str( exc )
- data_copy=hda.copy( copy_children=True )
- result=history.add_dataset( data_copy )
- trans.sa_session.flush()
- return result.to_dict()
- else:
- # other options
- trans.response.status = 501
- return
+ unencoded_hda_id = self._decode_id( trans, content )
+ original = self.mgrs.hdas.get( trans, unencoded_hda_id, check_ownership=False, check_accessible=True )
+ data_copy = original.copy( copy_children=True )
+ hda = history.add_dataset( data_copy )
+
+ trans.sa_session.flush()
+ return hda.to_dict() if hda else None
@expose_api_anonymous
def update( self, trans, history_id, id, payload, **kwd ):
@@ -305,45 +287,38 @@
def __update_dataset( self, trans, history_id, id, payload, **kwd ):
changed = {}
- try:
- # anon user
- if trans.user == None:
- if history_id != trans.security.encode_id( trans.history.id ):
- trans.response.status = 401
- return { 'error': 'Anonymous users cannot edit histories other than their current history' }
- anon_allowed_payload = {}
- if 'deleted' in payload:
- anon_allowed_payload[ 'deleted' ] = payload[ 'deleted' ]
- if 'visible' in payload:
- anon_allowed_payload[ 'visible' ] = payload[ 'visible' ]
- payload = self._validate_and_parse_update_payload( anon_allowed_payload )
- hda = self.get_dataset( trans, id, check_ownership=False, check_accessible=False, check_state=True )
- if hda.history != trans.history:
- trans.response.status = 401
- return { 'error': 'Anonymous users cannot edit datasets outside their current history' }
+ # anon user
+ if trans.user == None:
+ if history_id != trans.security.encode_id( trans.history.id ):
+ raise exceptions.AuthenticationRequired( 'You must be logged in to update this history' )
+ anon_allowed_payload = {}
+ if 'deleted' in payload:
+ anon_allowed_payload[ 'deleted' ] = payload[ 'deleted' ]
+ if 'visible' in payload:
+ anon_allowed_payload[ 'visible' ] = payload[ 'visible' ]
+ payload = self._validate_and_parse_update_payload( anon_allowed_payload )
- else:
- payload = self._validate_and_parse_update_payload( payload )
- # only check_state if not deleting, otherwise cannot delete uploading files
- check_state = not payload.get( 'deleted', False )
- hda = self.get_dataset( trans, id, check_ownership=True, check_accessible=True, check_state=check_state )
- # get_dataset can return a string during an error
- if hda and isinstance( hda, trans.model.HistoryDatasetAssociation ):
- changed = self.set_hda_from_dict( trans, hda, payload )
- if payload.get( 'deleted', False ):
- self.stop_hda_creating_job( hda )
+ hda = self.mgrs.hdas.get( trans, self._decode_id( trans, id ),
+ check_ownership=False, check_accessible=False )
+ hda = self.mgrs.hdas.err_if_uploading( trans, hda )
+ if hda.history != trans.history:
+ raise exceptions.AuthenticationRequired( 'You must be logged in to update this dataset' )
- except Exception, exception:
- log.error( 'Update of history (%s), HDA (%s) failed: %s',
- history_id, id, str( exception ), exc_info=True )
- # convert to appropo HTTP code
- if( isinstance( exception, ValueError )
- or isinstance( exception, AttributeError ) ):
- # bad syntax from the validater/parser
- trans.response.status = 400
- else:
- trans.response.status = 500
- return { 'error': str( exception ) }
+ else:
+ payload = self._validate_and_parse_update_payload( payload )
+ # only check_state if not deleting, otherwise cannot delete uploading files
+ check_state = not payload.get( 'deleted', False )
+ hda = self.mgrs.hdas.get( trans, self._decode_id( trans, id ),
+ check_ownership=True, check_accessible=True )
+ if check_state:
+ hda = self.mgrs.hdas.err_if_uploading( trans, hda )
+ #hda = self.get_dataset( trans, id, check_ownership=True, check_accessible=True, check_state=check_state )
+
+ if hda and isinstance( hda, trans.model.HistoryDatasetAssociation ):
+ changed = self.set_hda_from_dict( trans, hda, payload )
+ if payload.get( 'deleted', False ):
+ self.stop_hda_creating_job( hda )
+
return changed
#TODO: allow anonymous del/purge and test security on this
@@ -387,44 +362,32 @@
# payload takes priority
purge = util.string_as_bool( kwd['payload'].get( 'purge', purge ) )
+ hda = self.mgrs.hdas.get( trans, self._decode_id( trans, id ),
+ check_ownership=True, check_accessible=True )
+ self.mgrs.hdas.err_if_uploading( trans, hda )
+
rval = { 'id' : id }
- try:
- hda = self.get_dataset( trans, id,
- check_ownership=True, check_accessible=True, check_state=True )
- hda.deleted = True
- if purge:
- if not trans.app.config.allow_user_dataset_purge:
- raise exceptions.httpexceptions.HTTPForbidden(
- detail='This instance does not allow user dataset purging' )
- hda.purged = True
- trans.sa_session.add( hda )
+ hda.deleted = True
+ if purge:
+ if not trans.app.config.allow_user_dataset_purge:
+ raise exceptions.ConfigDoesNotAllowException( 'This instance does not allow user dataset purging' )
+ hda.purged = True
+ trans.sa_session.add( hda )
+ trans.sa_session.flush()
+ if hda.dataset.user_can_purge:
+ try:
+ hda.dataset.full_delete()
+ trans.sa_session.add( hda.dataset )
+ except:
+ pass
+ # flush now to preserve deleted state in case of later interruption
trans.sa_session.flush()
- if hda.dataset.user_can_purge:
- try:
- hda.dataset.full_delete()
- trans.sa_session.add( hda.dataset )
- except:
- pass
- # flush now to preserve deleted state in case of later interruption
- trans.sa_session.flush()
- rval[ 'purged' ] = True
+ rval[ 'purged' ] = True
- self.stop_hda_creating_job( hda )
+ self.stop_hda_creating_job( hda )
+ trans.sa_session.flush()
- trans.sa_session.flush()
- rval[ 'deleted' ] = True
-
- except exceptions.httpexceptions.HTTPInternalServerError, http_server_err:
- log.exception( 'HDA API, delete: uncaught HTTPInternalServerError: %s, %s\n%s',
- id, str( kwd ), str( http_server_err ) )
- raise
- except exceptions.httpexceptions.HTTPException:
- raise
- except Exception, exc:
- log.exception( 'HDA API, delete: uncaught exception: %s, %s\n%s',
- id, str( kwd ), str( exc ) )
- trans.response.status = 500
- rval.update({ 'error': str( exc ) })
+ rval[ 'deleted' ] = True
return rval
def _validate_and_parse_update_payload( self, payload ):
@@ -470,3 +433,68 @@
# TODO: raise a message exception instead of setting status and returning dict.
trans.response.status = 400
return { 'error': 'Unknown contents type %s' % type }
+
+
+class HDAManager( object ):
+
+ def __init__( self ):
+ self.histories_mgr = histories.HistoryManager()
+
+ def get( self, trans, unencoded_id, check_ownership=True, check_accessible=True ):
+ """
+ """
+ # this is a replacement for UsesHistoryDatasetAssociationMixin because mixins are a bad soln/structure
+ hda = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( unencoded_id )
+ if hda is None:
+ raise exceptions.ObjectNotFound()
+ hda = self.secure( trans, hda, check_ownership, check_accessible )
+ return hda
+
+ def secure( self, trans, hda, check_ownership=True, check_accessible=True ):
+ """
+ checks if (a) user owns item or (b) item is accessible to user.
+ """
+ # all items are accessible to an admin
+ if trans.user and trans.user_is_admin():
+ return hda
+ if check_ownership:
+ hda = self.check_ownership( trans, hda )
+ if check_accessible:
+ hda = self.check_accessible( trans, hda )
+ return hda
+
+ def can_access_dataset( self, trans, hda ):
+ current_user_roles = trans.get_current_user_roles()
+ return trans.app.security_agent.can_access_dataset( current_user_roles, hda.dataset )
+
+ #TODO: is_owner, is_accessible
+
+ def check_ownership( self, trans, hda ):
+ if not trans.user:
+ #if hda.history == trans.history:
+ # return hda
+ raise exceptions.AuthenticationRequired( "Must be logged in to manage Galaxy datasets", type='error' )
+ if trans.user_is_admin():
+ return hda
+ # check for ownership of the containing history and accessibility of the underlying dataset
+ if( self.histories_mgr.is_owner( trans, hda.history )
+ and self.can_access_dataset( trans, hda ) ):
+ return hda
+ raise exceptions.ItemOwnershipException(
+ "HistoryDatasetAssociation is not owned by the current user", type='error' )
+
+ def check_accessible( self, trans, hda ):
+ if trans.user and trans.user_is_admin():
+ return hda
+ # check for access of the containing history...
+ self.histories_mgr.check_accessible( trans, hda.history )
+ # ...then the underlying dataset
+ if self.can_access_dataset( trans, hda ):
+ return hda
+ raise exceptions.ItemAccessibilityException(
+ "HistoryDatasetAssociation is not accessible to the current user", type='error' )
+
+ def err_if_uploading( self, trans, hda ):
+ if hda.state == trans.model.Dataset.states.UPLOAD:
+ raise exceptions.Conflict( "Please wait until this dataset finishes uploading" )
+ return hda
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 lib/galaxy/webapps/galaxy/controllers/history.py
--- a/lib/galaxy/webapps/galaxy/controllers/history.py
+++ b/lib/galaxy/webapps/galaxy/controllers/history.py
@@ -860,17 +860,17 @@
hda_dictionaries = []
user_is_owner = False
try:
- history_to_view = self.get_history( trans, id, False )
+ history_to_view = self.get_history( trans, id, check_ownership=False, check_accessible=False )
if not history_to_view:
return trans.show_error_message( "The specified history does not exist." )
if history_to_view.user == trans.user:
user_is_owner = True
+ if( ( history_to_view.user != trans.user )
# Admin users can view any history
- if( ( history_to_view.user != trans.user )
- and ( not trans.user_is_admin() )
- and ( not history_to_view.importable ) ):
- #TODO: no check for shared with
+ and ( not trans.user_is_admin() )
+ and ( not history_to_view.importable )
+ and ( trans.user not in history_to_view.users_shared_with_dot_users ) ):
return trans.show_error_message( "Either you are not allowed to view this history"
+ " or the owner of this history has not made it accessible." )
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/api-anon-history-permission-tests.js
--- /dev/null
+++ b/test/casperjs/api-anon-history-permission-tests.js
@@ -0,0 +1,224 @@
+/* Utility to load a specific page and output html, page text, or a screenshot
+ * Optionally wait for some time, text, or dom selector
+ */
+try {
+ //...if there's a better way - please let me know, universe
+ var scriptDir = require( 'system' ).args[3]
+ // remove the script filename
+ .replace( /[\w|\.|\-|_]*$/, '' )
+ // if given rel. path, prepend the curr dir
+ .replace( /^(?!\/)/, './' ),
+ spaceghost = require( scriptDir + 'spaceghost' ).create({
+ // script options here (can be overridden by CLI)
+ //verbose: true,
+ //logLevel: debug,
+ scriptDir: scriptDir
+ });
+
+} catch( error ){
+ console.debug( error );
+ phantom.exit( 1 );
+}
+spaceghost.start();
+
+
+// =================================================================== SET UP
+var utils = require( 'utils' );
+
+var email = spaceghost.user.getRandomEmail(),
+ password = '123456';
+if( spaceghost.fixtureData.testUser ){
+ email = spaceghost.fixtureData.testUser.email;
+ password = spaceghost.fixtureData.testUser.password;
+}
+var inaccessibleHistory, accessibleHistory, publishedHistory,
+ inaccessibleHdas, accessibleHdas, publishedHdas,
+ accessibleLink;
+
+//// ------------------------------------------------------------------------------------------- create 3 histories
+spaceghost.user.loginOrRegisterUser( email, password );
+spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ // create three histories: make the 2nd importable (via the API), and the third published
+
+ // make the current the inaccessible one
+ inaccessibleHistory = this.api.histories.show( 'current' );
+ this.api.histories.update( inaccessibleHistory.id, { name: 'inaccessible' });
+ inaccessibleHistory = this.api.histories.show( 'current' );
+
+ accessibleHistory = this.api.histories.create({ name: 'accessible' });
+ var returned = this.api.histories.update( accessibleHistory.id, {
+ importable : true
+ });
+ //this.debug( this.jsonStr( returned ) );
+ accessibleHistory = this.api.histories.show( accessibleHistory.id );
+
+ publishedHistory = this.api.histories.create({ name: 'published' });
+ returned = this.api.histories.update( publishedHistory.id, {
+ published : true
+ });
+ //this.debug( this.jsonStr( returned ) );
+ publishedHistory = this.api.histories.show( publishedHistory.id );
+
+});
+
+//// ------------------------------------------------------------------------------------------- upload some files
+spaceghost.then( function(){
+ this.api.tools.thenUpload( inaccessibleHistory.id, { filepath: this.options.scriptDir + '/../../test-data/1.bed' });
+ this.api.tools.thenUpload( accessibleHistory.id, { filepath: this.options.scriptDir + '/../../test-data/1.bed' });
+ this.api.tools.thenUpload( publishedHistory.id, { filepath: this.options.scriptDir + '/../../test-data/1.bed' });
+});
+spaceghost.then( function(){
+ // check that they're there
+ inaccessibleHdas = this.api.hdas.index( inaccessibleHistory.id ),
+ accessibleHdas = this.api.hdas.index( accessibleHistory.id ),
+ publishedHdas = this.api.hdas.index( publishedHistory.id );
+});
+spaceghost.user.logout();
+
+// =================================================================== TESTS
+//// ------------------------------------------------------------------------------------------- anon user
+function testAnonReadFunctionsOnAccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for ACCESSIBLE history: ' + history.name );
+
+ // read functions for history
+ this.test.comment( 'show should work for history: ' + history.name );
+ this.test.assert( this.api.histories.show( history.id ).id === history.id,
+ 'show worked' );
+ this.test.comment( 'copying should fail for history (multiple histories not allowed): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ history_id : history.id });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
+
+ // read functions for history contents
+ this.test.comment( 'index of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.index( history.id ).length === 1,
+ 'hda index worked' );
+ this.test.comment( 'showing of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.show( history.id, hdas[0].id ).id === hdas[0].id,
+ 'hda show worked' );
+
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' fails from accessible history (currently login is required): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( this.api.histories.show( 'current' ).id, {
+ source : 'hda',
+ content : hdas[0].id
+ });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
+}
+
+function testAnonReadFunctionsOnInaccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for INACCESSIBLE history: ' + history.name );
+
+ // read functions for history
+ this.test.comment( 'show should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.show( history.id );
+ }, 403, 'History is not accessible to the current user', 'show failed with error' );
+ this.test.comment( 'copying should fail for history (implicit multiple histories): ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ history_id : history.id });
+ }, 403, 'API authentication required for this request', 'copy failed with error' );
+
+ // read functions for history contents
+ this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.index( history.id );
+ }, 403, 'History is not accessible to the current user', 'hda index failed with error' );
+ this.api.assertRaises( function(){
+ this.api.hdas.show( history.id, hdas[0].id );
+ }, 403, 'History is not accessible to the current user', 'hda show failed with error' );
+
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' from an inaccessible history should fail for: ' + history.name );
+ this.api.assertRaises( function(){
+ var returned = this.api.hdas.create( this.api.histories.show( 'current' ).id, {
+ source : 'hda',
+ content : hdas[0].id
+ });
+ this.debug( this.jsonStr( returned ) );
+ }, 403, 'API authentication required for this request', 'hda copy from failed with error' );
+
+}
+
+function testAnonWriteFunctions( history, hdas ){
+ this.test.comment( '---- testing write/ownership functions for history: ' + history.name );
+
+ this.test.comment( 'update should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.update( history.id, { deleted: true });
+ }, 403, 'API authentication required for this request', 'update authentication required' );
+ this.test.comment( 'delete should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( history.id );
+ }, 403, 'API authentication required for this request', 'delete authentication required' );
+ this.test.comment( 'set_as_current should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.set_as_current( history.id );
+ }, 403, 'API authentication required for this request', 'set_as_current failed with error' );
+
+ this.test.comment( 'hda updating should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
+ // anon hda update fails w/ this msg if trying to update non-current history hda
+ }, 403, 'You must be logged in to update this history', 'hda update failed with error' );
+ this.test.comment( 'hda deletion should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( history.id, hdas[0].id );
+ }, 403, 'API authentication required for this request', 'hda delete failed with error' );
+
+ this.test.comment( 'copying hda into history should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( history.id, {
+ source : 'hda',
+ // should error before it checks the id
+ content : 'bler'
+ });
+ }, 403, 'API authentication required for this request', 'hda copy to failed' );
+}
+
+function testAnonInaccessible( history, hdas ){
+ testAnonReadFunctionsOnInaccessible.call( this, history, hdas );
+ testAnonWriteFunctions.call( this, history, hdas );
+}
+
+function testAnonAccessible( history, hdas ){
+ testAnonReadFunctionsOnAccessible.call( this, history, hdas );
+ testAnonWriteFunctions.call( this, history, hdas );
+}
+
+spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ testAnonInaccessible.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
+ testAnonAccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAnonAccessible.call( spaceghost, publishedHistory, publishedHdas );
+});
+
+
+// ------------------------------------------------------------------------------------------- user1 revoke perms
+spaceghost.user.loginOrRegisterUser( email, password );
+spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ this.test.comment( 'revoking perms should prevent access' );
+ this.api.histories.update( accessibleHistory.id, {
+ importable : false
+ });
+ var returned = this.api.histories.show( accessibleHistory.id );
+
+ this.api.histories.update( publishedHistory.id, {
+ importable : false,
+ published : false
+ });
+ returned = this.api.histories.show( publishedHistory.id );
+});
+spaceghost.user.logout();
+
+
+// ------------------------------------------------------------------------------------------- anon retry perms
+spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ testAnonInaccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAnonInaccessible.call( spaceghost, publishedHistory, publishedHdas );
+});
+
+
+// ===================================================================
+spaceghost.run( function(){
+});
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/api-anon-history-tests.js
--- /dev/null
+++ b/test/casperjs/api-anon-history-tests.js
@@ -0,0 +1,159 @@
+/* Utility to load a specific page and output html, page text, or a screenshot
+ * Optionally wait for some time, text, or dom selector
+ */
+try {
+ //...if there's a better way - please let me know, universe
+ var scriptDir = require( 'system' ).args[3]
+ // remove the script filename
+ .replace( /[\w|\.|\-|_]*$/, '' )
+ // if given rel. path, prepend the curr dir
+ .replace( /^(?!\/)/, './' ),
+ spaceghost = require( scriptDir + 'spaceghost' ).create({
+ // script options here (can be overridden by CLI)
+ //verbose: true,
+ //logLevel: debug,
+ scriptDir: scriptDir
+ });
+
+} catch( error ){
+ console.debug( error );
+ phantom.exit( 1 );
+}
+spaceghost.start();
+
+
+// =================================================================== SET UP
+var utils = require( 'utils' );
+
+// =================================================================== TESTS
+spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( '.history-name' );
+spaceghost.then( function(){
+
+ // ------------------------------------------------------------------------------------------- anon allowed
+ this.test.comment( 'index should get a list of histories' );
+ var index = this.api.histories.index();
+ this.test.assert( utils.isArray( index ), "index returned an array: length " + index.length );
+ this.test.assert( index.length === 1, 'Has at least one history' );
+
+ this.test.comment( 'show should get a history details object' );
+ var historyShow = this.api.histories.show( index[0].id );
+ //this.debug( this.jsonStr( historyShow ) );
+ this.test.assert( historyShow.id === index[0].id, 'Is the first history' );
+ this.test.assert( this.hasKeys( historyShow, [ 'id', 'name', 'user_id' ] ) );
+
+ this.test.comment( 'Calling show with "current" should return the current history' );
+ var current = this.api.histories.show( 'current' );
+ //this.debug( this.jsonStr( current ) );
+ this.test.assert( current.id === index[0].id, 'Is the first history' );
+ this.test.assert( current.id === historyShow.id, 'current returned same id' );
+
+
+ // ------------------------------------------------------------------------------------------- anon forbidden
+ //TODO: why not return the current history?
+ this.test.comment( 'calling show with "most_recently_used" should return None for an anon user' );
+ var recent = this.api.histories.show( 'most_recently_used' );
+ this.test.assert( recent === null, 'most_recently_used returned None' );
+
+ this.test.comment( 'Calling set_as_current should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.set_as_current( current.id );
+ }, 403, 'API authentication required for this request', 'set_as_current failed with error' );
+
+ this.test.comment( 'Calling create should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.create({ current: true });
+ }, 403, 'API authentication required for this request', 'create failed with error' );
+
+ this.test.comment( 'Calling delete should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( current.id );
+ }, 403, 'API authentication required for this request', 'create failed with error' );
+
+ this.test.comment( 'Calling update should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.histories.update( current.id, {} );
+ }, 403, 'API authentication required for this request', 'update failed with error' );
+
+ //TODO: need these two in api.js
+ //this.test.comment( 'Calling archive_import should fail for an anonymous user' );
+ //this.api.assertRaises( function(){
+ // this.api.histories.archive_import( current.id, {} );
+ //}, 403, 'API authentication required for this request', 'archive_import failed with error' );
+
+ //this.test.comment( 'Calling archive_download should fail for an anonymous user' );
+ //this.api.assertRaises( function(){
+ // this.api.histories.archive_download( current.id, {} );
+ //}, 403, 'API authentication required for this request', 'archive_download failed with error' );
+
+ // test server bad id protection
+ spaceghost.test.comment( 'A bad id should throw an error' );
+ this.api.assertRaises( function(){
+ this.api.histories.show( '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
+
+});
+
+// ------------------------------------------------------------------------------------------- hdas
+spaceghost.thenOpen( spaceghost.baseUrl ).waitForSelector( '.history-name' );
+//TODO: can't use this - get a 400 when tools checks for history: 'logged in to manage'
+//spaceghost.then( function(){
+// this.api.tools.thenUpload( spaceghost.api.histories.show( 'current' ).id, {
+// filepath: this.options.scriptDir + '/../../test-data/1.sam'
+// });
+//});
+spaceghost.then( function(){
+ spaceghost.tools.uploadFile( '../../test-data/1.sam', function( uploadInfo ){
+ this.test.assert( uploadInfo.hdaElement !== null, "Convenience function produced hda" );
+ var state = this.historypanel.getHdaState( '#' + uploadInfo.hdaElement.attributes.id );
+ this.test.assert( state === 'ok', "Convenience function produced hda in ok state" );
+ });
+});
+
+spaceghost.then( function(){
+ var current = this.api.histories.show( 'current' );
+
+ // ------------------------------------------------------------------------------------------- anon allowed
+ this.test.comment( 'anonymous users can index hdas in their current history' );
+ var hdaIndex = this.api.hdas.index( current.id );
+ this.test.assert( hdaIndex.length === 1, 'indexed hdas' );
+
+ this.test.comment( 'anonymous users can show hdas in their current history' );
+ var hda = this.api.hdas.show( current.id, hdaIndex[0].id );
+ this.test.assert( this.hasKeys( hda, [ 'id', 'name' ] ), 'showed hda: ' + hda.name );
+
+ this.test.comment( 'anonymous users can hide hdas in their current history' );
+ var changed = this.api.hdas.update( current.id, hda.id, { visible: false });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.visible === false, 'successfully hidden' );
+
+ this.test.comment( 'anonymous users can mark their hdas as deleted in their current history' );
+ changed = this.api.hdas.update( current.id, hda.id, { deleted: true });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.test.assert( hda.deleted, 'successfully deleted' );
+
+ // ------------------------------------------------------------------------------------------- anon forbidden
+ //TODO: should be allowed...
+ this.test.comment( 'Calling create should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.hdas.create( current.id, { source: 'hda', content: 'doesntmatter' });
+ }, 403, 'API authentication required for this request', 'create failed with error' );
+
+ //TODO: should be allowed (along with purge) and automatically creates new history (as UI)
+ this.test.comment( 'Calling delete should fail for an anonymous user' );
+ this.api.assertRaises( function(){
+ this.api.hdas.delete_( current.id, hda.id );
+ }, 403, 'API authentication required for this request', 'delete failed with error' );
+
+ //TODO: only sharing, tags, annotations should be blocked/prevented
+ this.test.comment( 'Calling update with keys other than "visible" or "deleted" should fail silently' );
+ changed = this.api.hdas.update( current.id, hda.id, { tags: [ 'one' ] });
+ hda = this.api.hdas.show( current.id, hda.id );
+ this.debug( this.jsonStr( hda.tags ) );
+
+ this.test.assert( hda.tags.length === 0, 'tags were not set' );
+
+});
+
+// ===================================================================
+spaceghost.run( function(){
+});
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/api-hda-tests.js
--- a/test/casperjs/api-hda-tests.js
+++ b/test/casperjs/api-hda-tests.js
@@ -55,6 +55,7 @@
'metadata_comment_lines', 'metadata_data_lines'
];
+// ------------------------------------------------------------------------------------------- logged in user
spaceghost.then( function(){
// ------------------------------------------------------------------------------------------- INDEX
@@ -299,7 +300,7 @@
this.test.comment( 'create should error with "Please define the source" when the param "from_ld_id" is not used' );
this.api.assertRaises( function(){
this.api.hdas.create( lastHistory.id, { bler: 'bler' } );
- }, 400, 'Please define the source', 'create with no source failed' );
+ }, 400, "must be either 'library' or 'hda'", 'create with no source failed' );
this.test.comment( 'updating using a nonsense key should fail silently' );
returned = this.api.hdas.update( lastHistory.id, hdaShow.id, {
@@ -310,15 +311,15 @@
spaceghost.test.comment( 'A bad id should throw an error when using show' );
this.api.assertRaises( function(){
this.api.hdas.show( lastHistory.id, '1234123412341234' );
- }, 500, 'unable to decode', 'Bad Request with invalid id: show' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: show' );
spaceghost.test.comment( 'A bad id should throw an error when using update' );
this.api.assertRaises( function(){
this.api.hdas.update( lastHistory.id, '1234123412341234', {} );
- }, 400, 'invalid literal for int', 'Bad Request with invalid id: update' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: update' );
spaceghost.test.comment( 'A bad id should throw an error when using delete' );
this.api.assertRaises( function(){
this.api.hdas.delete_( lastHistory.id, '1234123412341234' );
- }, 500, 'invalid literal for int', 'Bad Request with invalid id: delete' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: delete' );
spaceghost.test.comment( 'A bad id should throw an error when using undelete' );
this.test.comment( 'updating by attempting to change type should cause an error' );
@@ -362,6 +363,8 @@
/*
*/
});
+//spaceghost.user.logout();
+
// ===================================================================
spaceghost.run( function(){
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/api-history-permission-tests.js
--- a/test/casperjs/api-history-permission-tests.js
+++ b/test/casperjs/api-history-permission-tests.js
@@ -60,6 +60,7 @@
this.test.assert( inaccessibleHistory.published === false,
'initial published is false: ' + inaccessibleHistory.published );
this.api.histories.update( inaccessibleHistory.id, { name: 'inaccessible' });
+ inaccessibleHistory = this.api.histories.show( 'current' );
this.test.comment( 'Setting importable to true should create a slug, username_and_slug, and importable === true' );
accessibleHistory = this.api.histories.create({ name: 'accessible' });
@@ -78,7 +79,7 @@
this.test.assert( accessibleHistory.username_and_slug === accessibleLink,
'username_and_slug is proper: ' + accessibleHistory.username_and_slug );
- this.test.comment( 'Setting published to true should create make accessible and published === true' );
+ this.test.comment( 'Setting published to true should make accessible and published === true' );
publishedHistory = this.api.histories.create({ name: 'published' });
returned = this.api.histories.update( publishedHistory.id, {
published : true
@@ -110,6 +111,7 @@
inaccessibleHdas = this.api.hdas.index( inaccessibleHistory.id ),
accessibleHdas = this.api.hdas.index( accessibleHistory.id ),
publishedHdas = this.api.hdas.index( publishedHistory.id );
+ this.test.comment( '---- adding datasets' );
this.test.assert( inaccessibleHdas.length === 1,
'uploaded file to inaccessible: ' + inaccessibleHdas.length );
this.test.assert( accessibleHdas.length === 1,
@@ -120,149 +122,119 @@
spaceghost.user.logout();
//// ------------------------------------------------------------------------------------------- log in user2
-function ensureInaccessibility( history, hdas ){
+function testReadFunctionsOnAccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for ACCESSIBLE history: ' + history.name );
- this.test.comment( 'all four CRUD API calls should fail for user2 with history: ' + history.name );
+ // read functions for history
+ this.test.comment( 'show should work for history: ' + history.name );
+ this.test.assert( this.api.histories.show( history.id ).id === history.id,
+ 'show worked' );
+ this.test.comment( 'copying should work for history: ' + history.name );
+ var returned = this.api.histories.create({ history_id : history.id });
+ this.test.assert( returned.name === "Copy of '" + history.name + "'",
+ 'copied name matches: ' + returned.name );
+
+ // read functions for history contents
+ this.test.comment( 'index of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.index( history.id ).length === 1,
+ 'hda index worked' );
+ this.test.comment( 'showing of history contents should work for history: ' + history.name );
+ this.test.assert( this.api.hdas.show( history.id, hdas[0].id ).id === hdas[0].id,
+ 'hda show worked' );
+
+ this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
+ + ' should work from accessible history: ' + history.name );
+ returned = this.api.hdas.create( this.api.histories.show( 'current' ).id, {
+ source : 'hda',
+ content : hdas[0].id
+ });
+ this.test.assert( returned.name === hdas[0].name, 'successful hda copy from: ' + returned.name );
+}
+
+function testReadFunctionsOnInaccessible( history, hdas ){
+ this.test.comment( '---- testing read/accessibility functions for INACCESSIBLE history: ' + history.name );
+
+ // read functions for history
+ this.test.comment( 'show should fail for history: ' + history.name );
this.api.assertRaises( function(){
this.api.histories.show( history.id );
- }, 400, 'History is not accessible to the current user', 'show failed with error' );
+ }, 403, 'History is not accessible to the current user', 'show failed with error' );
+ this.test.comment( 'copying should fail for history: ' + history.name );
this.api.assertRaises( function(){
this.api.histories.create({ history_id : history.id });
}, 403, 'History is not accessible to the current user', 'copy failed with error' );
- this.api.assertRaises( function(){
- this.api.histories.update( history.id, { deleted: true });
- }, 500, 'History is not owned by the current user', 'update failed with error' );
- this.api.assertRaises( function(){
- this.api.histories.delete_( history.id );
- }, 400, 'History is not owned by the current user', 'delete failed with error' );
- this.test.comment( 'all four HDA CRUD API calls should fail for user2 with history: ' + history.name );
+ // read functions for history contents
+ this.test.comment( 'index and show of history contents should fail for history: ' + history.name );
this.api.assertRaises( function(){
this.api.hdas.index( history.id );
- }, 500, 'History is not accessible to the current user', 'index failed with error' );
+ }, 403, 'History is not accessible to the current user', 'hda index failed with error' );
this.api.assertRaises( function(){
this.api.hdas.show( history.id, hdas[0].id );
- }, 500, 'History is not accessible to the current user', 'show failed with error' );
- this.api.assertRaises( function(){
- this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
- }, 500, 'HistoryDatasetAssociation is not owned by current user', 'update failed with error' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( history.id, hdas[0].id );
- }, 500, 'HistoryDatasetAssociation is not owned by current user', 'delete failed with error' );
+ }, 403, 'History is not accessible to the current user', 'hda show failed with error' );
this.test.comment( 'Attempting to copy an accessible hda (default is accessible)'
- + 'from an inaccessible history should fail' );
+ + ' from an inaccessible history should fail for: ' + history.name );
this.api.assertRaises( function(){
var returned = this.api.hdas.create( this.api.histories.show( 'current' ).id, {
source : 'hda',
content : hdas[0].id
});
this.debug( this.jsonStr( returned ) );
- }, 403, 'History is not accessible to the current user', 'copy failed with error' );
+ }, 403, 'History is not accessible to the current user', 'hda copy from failed with error' );
}
-spaceghost.user.loginOrRegisterUser( email2, password2 );
-spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- // ----------------------------------------------------------------------------------------- user2 + inaccessible
- ensureInaccessibility.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
-
- // ----------------------------------------------------------------------------------------- user2 + accessible
- this.test.comment( 'show should work for the importable history' );
- this.test.assert( this.api.histories.show( accessibleHistory.id ).id === accessibleHistory.id,
- 'show worked' );
+function testWriteFunctions( history, hdas ){
+ this.test.comment( '---- testing write/ownership functions for history: ' + history.name );
- this.test.comment( 'create/copy should work for the importable history' );
- var returned = this.api.histories.create({ history_id : accessibleHistory.id });
- this.test.assert( returned.name === "Copy of '" + accessibleHistory.name + "'",
- 'copied name matches: ' + returned.name );
+ this.test.comment( 'update should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.update( history.id, { deleted: true });
+ }, 403, 'History is not owned by the current user', 'update failed with error' );
+ this.test.comment( 'delete should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.delete_( history.id );
+ }, 403, 'History is not owned by the current user', 'delete failed with error' );
+ this.test.comment( 'set_as_current should fail for history: ' + history.name );
+ this.api.assertRaises( function(){
+ this.api.histories.set_as_current( history.id );
+ }, 403, 'History is not owned by the current user', 'set_as_current failed with error' );
- this.test.comment( 'update should fail for the importable history' );
+ this.test.comment( 'hda updating should fail for history: ' + history.name );
this.api.assertRaises( function(){
- this.api.histories.update( accessibleHistory.id, { deleted: true });
- }, 500, 'History is not owned by the current user', 'update failed with error' );
- this.test.comment( 'delete should fail for the importable history' );
+ this.api.hdas.update( history.id, hdas[0].id, { deleted: true });
+ }, 403, 'HistoryDatasetAssociation is not owned by the current user', 'hda update failed with error' );
+ this.test.comment( 'hda deletion should fail for history: ' + history.name );
this.api.assertRaises( function(){
- this.api.histories.delete_( accessibleHistory.id );
- }, 400, 'History is not owned by the current user', 'delete failed with error' );
+ this.api.hdas.delete_( history.id, hdas[0].id );
+ }, 403, 'HistoryDatasetAssociation is not owned by the current user', 'hda delete failed with error' );
- this.test.comment( 'indexing should work for the contents of the importable history' );
- this.test.assert( this.api.hdas.index( accessibleHistory.id ).length === 1,
- 'index worked' );
- this.test.comment( 'showing should work for the contents of the importable history' );
- this.test.assert( this.api.hdas.show( accessibleHistory.id, accessibleHdas[0].id ).id === accessibleHdas[0].id,
- 'show worked' );
- this.test.comment( 'updating should fail for the contents of the importable history' );
+ this.test.comment( 'copying hda into history should fail for history: ' + history.name );
this.api.assertRaises( function(){
- this.api.hdas.update( accessibleHistory.id, accessibleHdas[0].id, { deleted: true });
- }, 500, 'HistoryDatasetAssociation is not owned by current user', 'update failed with error' );
- this.test.comment( 'deleting should fail for the contents of the importable history' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( accessibleHistory.id, accessibleHdas[0].id );
- }, 500, 'HistoryDatasetAssociation is not owned by current user', 'delete failed with error' );
- this.test.comment( 'copying a dataset from the importable history should work' );
- returned = this.api.hdas.create( this.api.histories.show( 'current' ).id, {
- source : 'hda',
- content : accessibleHdas[0].id
- });
- this.test.assert( returned.name === accessibleHdas[0].name, 'successful copy from: ' + returned.name );
-
- this.test.comment( 'copying a dataset into the importable history should fail' );
- this.api.assertRaises( function(){
- this.api.hdas.create( accessibleHistory.id, {
+ this.api.hdas.create( history.id, {
source : 'hda',
// should error before it checks the id
content : 'bler'
});
- }, 400, 'History is not owned by the current user', 'copy to failed' );
+ }, 403, 'History is not owned by the current user', 'hda copy to failed' );
+}
- //// ----------------------------------------------------------------------------------------- user2 + published
- this.test.comment( 'show should work for the published history' );
- this.test.assert( this.api.histories.show( publishedHistory.id ).id === publishedHistory.id,
- 'show worked' );
- this.test.comment( 'create/copy should work for the published history' );
- returned = this.api.histories.create({ history_id : publishedHistory.id });
- this.test.assert( returned.name === "Copy of '" + publishedHistory.name + "'",
- 'copied name matches: ' + returned.name );
- this.test.comment( 'update should fail for the published history' );
- this.api.assertRaises( function(){
- this.api.histories.update( publishedHistory.id, { deleted: true });
- }, 500, 'History is not owned by the current user', 'update failed with error' );
- this.test.comment( 'delete should fail for the published history' );
- this.api.assertRaises( function(){
- this.api.histories.delete_( publishedHistory.id );
- }, 400, 'History is not owned by the current user', 'delete failed with error' );
+function testInaccessible( history, hdas ){
+ testReadFunctionsOnInaccessible.call( this, history, hdas );
+ testWriteFunctions.call( this, history, hdas );
+}
- this.test.comment( 'indexing should work for the contents of the published history' );
- this.test.assert( this.api.hdas.index( publishedHistory.id ).length === 1,
- 'index worked' );
- this.test.comment( 'showing should work for the contents of the published history' );
- this.test.assert( this.api.hdas.show( publishedHistory.id, publishedHdas[0].id ).id === publishedHdas[0].id,
- 'show worked' );
- this.test.comment( 'updating should fail for the contents of the published history' );
- this.api.assertRaises( function(){
- this.api.hdas.update( publishedHistory.id, publishedHdas[0].id, { deleted: true });
- }, 500, 'HistoryDatasetAssociation is not owned by current user', 'update failed with error' );
- this.test.comment( 'deleting should fail for the contents of the published history' );
- this.api.assertRaises( function(){
- this.api.hdas.delete_( publishedHistory.id, publishedHdas[0].id );
- }, 500, 'HistoryDatasetAssociation is not owned by current user', 'delete failed with error' );
+function testAccessible( history, hdas ){
+ testReadFunctionsOnAccessible.call( this, history, hdas );
+ testWriteFunctions.call( this, history, hdas );
+}
- this.test.comment( 'copying a dataset from the published history should work' );
- returned = this.api.hdas.create( this.api.histories.show( 'current' ).id, {
- source : 'hda',
- content : publishedHdas[0].id
- });
- this.test.assert( returned.name === publishedHdas[0].name, 'successful copy from: ' + returned.name );
-
- this.test.comment( 'copying a dataset into the published history should fail' );
- this.api.assertRaises( function(){
- this.api.hdas.create( publishedHistory.id, {
- source : 'hda',
- // should error before it checks the id
- content : 'bler'
- });
- }, 400, 'History is not owned by the current user', 'copy to failed' );
+spaceghost.user.loginOrRegisterUser( email2, password2 );
+spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
+ testInaccessible.call( spaceghost, inaccessibleHistory, inaccessibleHdas );
+ testAccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testAccessible.call( spaceghost, publishedHistory, publishedHdas );
});
spaceghost.user.logout();
@@ -294,9 +266,11 @@
//// ------------------------------------------------------------------------------------------- user2 retry perms
spaceghost.user.loginOrRegisterUser( email2, password2 );
spaceghost.thenOpen( spaceghost.baseUrl ).then( function(){
- ensureInaccessibility.call( spaceghost, accessibleHistory, accessibleHdas );
- ensureInaccessibility.call( spaceghost, publishedHistory, publishedHdas );
+ testInaccessible.call( spaceghost, accessibleHistory, accessibleHdas );
+ testInaccessible.call( spaceghost, publishedHistory, publishedHdas );
});
+spaceghost.user.logout();
+
// ===================================================================
spaceghost.run( function(){
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/api-history-tests.js
--- a/test/casperjs/api-history-tests.js
+++ b/test/casperjs/api-history-tests.js
@@ -316,7 +316,11 @@
spaceghost.test.comment( 'A bad id should throw an error when using update' );
this.api.assertRaises( function(){
this.api.histories.update( '1234123412341234', {} );
- }, 500, 'unable to decode', 'Bad Request with invalid id: update' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: update' );
+ spaceghost.test.comment( 'A bad id should throw an error when using set_as_current' );
+ this.api.assertRaises( function(){
+ this.api.histories.set_as_current( '1234123412341234' );
+ }, 400, 'unable to decode', 'Bad Request with invalid id: set_as_current' );
spaceghost.test.comment( 'A bad id should throw an error when using delete' );
this.api.assertRaises( function(){
this.api.histories.delete_( '1234123412341234' );
@@ -346,6 +350,11 @@
returned = spaceghost.api.histories.update( newFirstHistory.id, { tags: badVal });
}, 400, 'tags must be a list', 'type validation error' );
});
+
+ this.test.comment( 'calling show with /deleted should raise a bad request' );
+ this.api.assertRaises( function(){
+ this.api.histories.show( newFirstHistory.id, true );
+ }, 400, 'is not deleted', 'Bad Request returned for non-deleted' );
/*
*/
//this.debug( this.jsonStr( historyShow ) );
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/casperjs_runner.py
--- a/test/casperjs/casperjs_runner.py
+++ b/test/casperjs/casperjs_runner.py
@@ -377,19 +377,19 @@
class Test_04_HDAs( CasperJSTestCase ):
"""Tests for HistoryDatasetAssociation fetching, rendering, and modeling.
"""
- #def test_00_HDA_states( self ):
- # """Test structure rendering of HDAs in all the possible HDA states
- # """
- # self.run_js_script( 'hda-state-tests.js' )
+ def test_00_HDA_states( self ):
+ """Test structure rendering of HDAs in all the possible HDA states
+ """
+ self.run_js_script( 'hda-state-tests.js' )
class Test_05_API( CasperJSTestCase ):
"""Tests for API functionality and security.
"""
- #def test_00_history_api( self ):
- # """Test history API.
- # """
- # self.run_js_script( 'api-history-tests.js' )
+ def test_00_history_api( self ):
+ """Test history API.
+ """
+ self.run_js_script( 'api-history-tests.js' )
def test_01_hda_api( self ):
"""Test HDA API.
@@ -401,6 +401,16 @@
"""
self.run_js_script( 'api-history-permission-tests.js' )
+ def test_03_anon_history_api( self ):
+ """Test API for histories using anonymous user.
+ """
+ self.run_js_script( 'api-anon-history-tests.js' )
+
+ def test_04_anon_history_api( self ):
+ """Test API permissions for importable, published histories using anonymous user.
+ """
+ self.run_js_script( 'api-anon-history-permission-tests.js' )
+
# ==================================================================== MAIN
if __name__ == '__main__':
diff -r b6d04f39a37fd73abd9c0c5e9695d74330786f47 -r c4f468e43b93406804bd7665a2755b16f8bac463 test/casperjs/modules/api.js
--- a/test/casperjs/modules/api.js
+++ b/test/casperjs/modules/api.js
@@ -75,8 +75,8 @@
if( resp.status !== 200 ){
// grrr... this doesn't lose the \n\r\t
//throw new APIError( resp.responseText.replace( /[\s\n\r\t]+/gm, ' ' ).replace( /"/, '' ) );
- this.spaceghost.debug( 'API error: code: ' + resp.status + ', responseText: ' + resp.responseText );
- this.spaceghost.debug( '\t responseJSON: ' + this.spaceghost.jsonStr( resp.responseJSON ) );
+ this.spaceghost.debug( 'API error: code: ' + resp.status + ', response:\n' +
+ ( resp.responseJSON? this.spaceghost.jsonStr( resp.responseJSON ) : resp.responseText ) );
throw new APIError( resp.responseText, resp.status );
}
return JSON.parse( resp.responseText );
@@ -95,8 +95,6 @@
try {
testFn.call( this.spaceghost );
} catch( err ){
- this.spaceghost.debug( err.name + ': ' + err.status );
- this.spaceghost.debug( err.message );
if( ( err.name === 'APIError' )
&& ( err.status && err.status === statusExpected )
&& ( err.message.indexOf( errMsgContains ) !== -1 ) ){
@@ -525,14 +523,13 @@
}
var response = this.api.spaceghost.evaluate( function( url, historyId, inputs ){
var file = $( 'input[name="casperjs-upload-file"]' )[0].files[0],
- formData = new FormData(),
- response;
+ formData = new FormData();
formData.append( 'files_0|file_data', file );
formData.append( 'history_id', historyId );
formData.append( 'tool_id', 'upload1' );
formData.append( 'inputs', JSON.stringify( inputs ) );
- $.ajax({
+ return $.ajax({
url : url,
async : false,
type : 'POST',
@@ -543,18 +540,17 @@
processData : false,
// if we don't add this, payload isn't processed as JSON
headers : { 'Accept': 'application/json' }
- }).done(function( resp ){
- response = resp;
});
- // this works only bc jq is async
- return response;
}, utils.format( this.urlTpls.create ), historyId, inputs );
- if( !response ){
- throw new APIError( 'Failed to upload: ' + options.filepath, 0 );
+ if( response.status !== 200 ){
+ // grrr... this doesn't lose the \n\r\t
+ //throw new APIError( response.responseText.replace( /[\s\n\r\t]+/gm, ' ' ).replace( /"/, '' ) );
+ this.api.spaceghost.debug( 'API error: code: ' + response.status + ', response:\n' +
+ ( response.responseJSON? this.api.spaceghost.jsonStr( response.responseJSON ) : response.responseText ) );
+ throw new APIError( response.responseText, response.status );
}
-
- return response;
+ return JSON.parse( response.responseText );
};
/** amount of time allowed to upload a file (before erroring) */
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