galaxy-commits
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
- 15302 discussions
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/75be6c49a65d/
Changeset: 75be6c49a65d
User: guerler
Date: 2014-05-15 04:49:44
Summary: Charts: Fix style
Affected #: 2 files
diff -r ac52aab8cb0e0ae989b3429b895743849dfb7e3a -r 75be6c49a65d8d52920696216ffb5af74a3fdd9c config/plugins/visualizations/charts/static/app.css
--- a/config/plugins/visualizations/charts/static/app.css
+++ b/config/plugins/visualizations/charts/static/app.css
@@ -39,9 +39,7 @@
.charts-viewport .info {
position: absolute;
- margin-left: 10px;
- margin-top: 10px;
- margin-bottom: 50px;
+ margin: 10px 20px 50px 10px;
}
.charts-viewport .text {
diff -r ac52aab8cb0e0ae989b3429b895743849dfb7e3a -r 75be6c49a65d8d52920696216ffb5af74a3fdd9c 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
@@ -62,10 +62,10 @@
$container.show()
break;
case 'failed':
- $icon.addClass('fa fa-warning');
+ $icon.addClass('icon fa fa-warning');
break;
default:
- $icon.addClass('fa fa-spinner fa-spin');
+ $icon.addClass('icon fa fa-spinner fa-spin');
}
});
},
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
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ac52aab8cb0e/
Changeset: ac52aab8cb0e
User: guerler
Date: 2014-05-15 04:21:36
Summary: Charts: Update panel
Affected #: 1 file
diff -r f05fe632cbc70d4694b5a4aa5e30b4f003952aa1 -r ac52aab8cb0e0ae989b3429b895743849dfb7e3a config/plugins/visualizations/charts/static/views/types.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/views/types.js
@@ -0,0 +1,133 @@
+define(['utils/utils', 'plugin/library/ui'], function(Utils, Ui) {
+
+return Backbone.View.extend(
+{
+ // defaults options
+ optionsDefault: {
+ onchange : null,
+ ondblclick : null
+ },
+
+ // events
+ events : {
+ 'click' : '_onclick',
+ 'dblclick' : '_ondblclick'
+ },
+
+ // initialize
+ initialize : function(app, options) {
+
+ // link app
+ this.app = app;
+
+ // configure options
+ this.options = Utils.merge(options, this.optionsDefault);
+
+ // create new element
+ var $el = $('<div class="charts-grid"/>');
+
+ // set element
+ this.setElement($el);
+
+ // load chart types into categories
+ var categories = {};
+ var types = app.types.attributes;
+ for (var id in types) {
+ var type = types[id];
+ var category = type.category;
+ if (!categories[category]) {
+ categories[category] = {};
+ }
+ categories[category][id] = type;
+ }
+
+ // add categories and charts to screen
+ for (var category in categories) {
+ // create empty element
+ var $el = $('<div style="clear: both;"/>')
+
+ // add header label
+ $el.append(Utils.wrap(this._template_header({title: category})));
+
+ // add chart types
+ for (var id in categories[category]) {
+ var type = categories[category][id];
+ $el.append(Utils.wrap(this._template_item({
+ id : id,
+ title : type.title,
+ url : config.app_root + 'charts/' + id + '/logo.png'
+ })));
+ }
+
+ // add to view
+ this.$el.append(Utils.wrap($el));
+ }
+ },
+
+ // value
+ value: function(new_value) {
+ // get current element
+ var before = this.$el.find('.current').attr('id');
+
+ // check if new_value is defined
+ if (new_value !== undefined) {
+
+ // remove current class
+ this.$el.find('.current').removeClass('current');
+
+ // add current class
+ this.$el.find('#' + new_value).addClass('current');
+ }
+
+ // get current id/value
+ var after = this.$el.find('.current').attr('id');
+ if(after === undefined) {
+ return null;
+ } else {
+ // fire onchange
+ if (after != before && this.options.onchange) {
+ this.options.onchange(new_value);
+ }
+
+ // return current value
+ return after;
+ }
+ },
+
+ // onclick
+ _onclick: function(e) {
+ var old_value = this.value();
+ var new_value = $(e.target).closest('.item').attr('id');
+ if (new_value != '') {
+ if (new_value && old_value != new_value) {
+ this.value(new_value);
+ }
+ }
+ },
+
+ // ondblclick
+ _ondblclick: function(e) {
+ var value = this.value();
+ if (value && this.options.ondblclick) {
+ this.options.ondblclick(value);
+ }
+ },
+
+ // template
+ _template_header: function(options) {
+ return '<div class="header">' +
+ '• ' + options.title +
+ '<div>';
+ },
+
+ // template
+ _template_item: function(options) {
+ return '<div id="' + options.id + '" class="item">' +
+ '<img class="image" src="' + options.url + '">' +
+ '<div class="title">' + options.title + '</div>' +
+ '<div>';
+ }
+
+});
+
+});
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: Update boxplots and stacked bar
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f05fe632cbc7/
Changeset: f05fe632cbc7
User: guerler
Date: 2014-05-15 04:18:17
Summary: Charts: Update boxplots and stacked bar
Affected #: 5 files
diff -r 2b4c26870efbc19441f02da19659c830cc8b591a -r f05fe632cbc70d4694b5a4aa5e30b4f003952aa1 config/plugins/visualizations/charts/static/charts/highcharts_boxplot/logo.png
Binary file config/plugins/visualizations/charts/static/charts/highcharts_boxplot/logo.png has changed
diff -r 2b4c26870efbc19441f02da19659c830cc8b591a -r f05fe632cbc70d4694b5a4aa5e30b4f003952aa1 config/plugins/visualizations/charts/static/charts/highcharts_boxplot/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/highcharts_boxplot/wrapper.js
@@ -0,0 +1,122 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// widget
+return Backbone.View.extend(
+{
+ // highcharts configuration
+ hc_config : {
+ chart: {
+ type: 'boxplot'
+ },
+
+ title: {
+ text: ''
+ },
+
+ legend: {
+ enabled: false
+ },
+
+ credits: {
+ enabled: false
+ },
+
+ plotOptions: {
+ series: {
+ animation: false
+ }
+ },
+
+ xAxis: {
+ categories: [],
+ title: {
+ text: ''
+ }
+ },
+
+ yAxis: {
+ title: {
+ text: ''
+ }
+ },
+
+ series: [{
+ name: 'Details:',
+ data: [],
+ tooltip: {
+ headerFormat: '<em>{point.key}</em><br/>'
+ }
+ }]
+ },
+
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ // configure request
+ var index = 0;
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = null;
+ group.columns = {
+ x: {
+ index: index++
+ }
+ }
+ }
+
+ // set axis labels
+ this.hc_config.xAxis.title.text = chart.settings.get('x_axis_label');
+ this.hc_config.yAxis.title.text = chart.settings.get('y_axis_label');
+
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function() {
+
+ // reset data/categories
+ var data = [];
+ var categories = [];
+
+ // loop through data groups
+ for (var key in request_dictionary.groups) {
+ // get group
+ var group = request_dictionary.groups[key];
+
+ // add category
+ categories.push(group.key);
+
+ // format chart data
+ var point = [];
+ for (var key in group.values) {
+ point.push(group.values[key].x);
+ }
+
+ // add to data
+ data.push (point);
+ }
+
+ // categories
+ self.hc_config.xAxis.categories = categories;
+
+ // update data
+ self.hc_config.series[0].data = data;
+
+ // draw plot
+ self.options.canvas[0].highcharts(self.hc_config);
+
+ // set chart state
+ chart.state('ok', 'Box plot drawn.');
+
+ // unregister process
+ chart.deferred.done(process_id);
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 2b4c26870efbc19441f02da19659c830cc8b591a -r f05fe632cbc70d4694b5a4aa5e30b4f003952aa1 config/plugins/visualizations/charts/static/charts/nvd3_bar_stacked/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar_stacked/config.js
@@ -0,0 +1,8 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Stacked',
+ category : 'Bar diagrams'
+});
+
+});
\ No newline at end of file
diff -r 2b4c26870efbc19441f02da19659c830cc8b591a -r f05fe632cbc70d4694b5a4aa5e30b4f003952aa1 config/plugins/visualizations/charts/static/charts/nvd3_bar_stacked/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_bar_stacked/logo.png has changed
diff -r 2b4c26870efbc19441f02da19659c830cc8b591a -r f05fe632cbc70d4694b5a4aa5e30b4f003952aa1 config/plugins/visualizations/charts/static/charts/nvd3_bar_stacked/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar_stacked/wrapper.js
@@ -0,0 +1,23 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary, function(nvd3_model) {
+ nvd3_model.stacked(true);
+ });
+ }
+});
+
+});
\ 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: guerler: Charts: Add new selection panel, improve modularity, activate basic heat map
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2b4c26870efb/
Changeset: 2b4c26870efb
User: guerler
Date: 2014-05-15 04:11:59
Summary: Charts: Add new selection panel, improve modularity, activate basic heat map
Affected #: 67 files
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/app.css
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/app.css
@@ -0,0 +1,69 @@
+.charts-grid .item {
+ padding: 5px;
+ margin: 5px;
+ float: left;
+ cursor: pointer;
+ border-radius:5px
+}
+
+.charts-grid .current {
+ border-color:#66afe9;
+ background-color:#EEEEFF;
+ outline:0;
+ -webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow:inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.charts-grid .image {
+ padding: 10px;
+ width: 100px;
+}
+
+.charts-grid .title {
+ text-align: center;
+ font-size: 0.9em;
+ word-wrap: break-work;
+ font-weight: bold;
+ width: 100px;
+}
+
+.charts-grid .header {
+ font-size: 0.9em;
+ font-weight: bold;
+}
+
+.charts-viewport {
+ height: inherit;
+ min-height: 50px;
+}
+
+.charts-viewport .info {
+ position: absolute;
+ margin-left: 10px;
+ margin-top: 10px;
+ margin-bottom: 50px;
+}
+
+.charts-viewport .text {
+ position: relative;
+ margin-left: 5px;
+ top: -1px;
+ font-size: 1.0em;
+}
+
+.charts-viewport .icon {
+ font-size: 1.2em;
+ display: inline-block;
+}
+
+.charts-viewport .container {
+ float: left;
+ display: block;
+ height: 100%;
+}
+
+.charts-viewport .canvas {
+ display: block;
+ width:100%;
+ height: inherit;
+}
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a 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.
-define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},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"),this.options.closing_callback&&this.options.closing_callback()},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:e}}),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-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:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<div class="'+e.cls+'">'+e.title+"</div>"},value:function(){return options.title}}),i=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}}),s=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>"}}),o=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}}),u=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>"}}),a=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>"}}),f=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>"}}),l=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>"}}),c=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}}),h=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:i,Icon:s,ButtonIcon:o,Input:h,Anchor:u,Message:a,Searchbox:f,Title:l,Text:r,Select:t,ButtonMenu:c}}),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)},request:function(e,t,n,r,i){var s=this;e.state("wait","Requesting job results...");var o=e.get("dataset_id_job");o!=""?s._wait(e,r,i):s._submit(e,t,n,r,i)},cleanup:function(t){var n=this,r=t.get("dataset_id_job");r!=""&&(e.request("PUT",config.root+"api/histories/none/contents/"+r,{deleted:!0},function(){n._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:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,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","Your job has been queued. You may close the browser window. The job will run in the background."),t.set("dataset_id_job",n.id),this.app.storage.save(),o._wait(t,i,s)}},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 'charts' tool. Please make sure it is installed. "+n),s&&s()})},_wait:function(t,n,r){var i=this;e.request("GET",config.root+"api/datasets/"+t.get("dataset_id_job"),{},function(e){var s=!1;switch(e.state){case"ok":t.state("wait","Job completed successfully..."),n&&n(e),s=!0;break;case"error":t.state("failed","Job has failed. Please check the history for details."),r&&r(e),s=!0;break;case"running":t.state("wait","Your job is running. You may close the browser window. The job will continue in the background.")}s||setTimeout(function(){i._wait(t,n,r)},i.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshContents()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},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._get(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)}})}},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.end+"_"+t},_get:function(e,t){e.start||(e.start=0),e.end||(e.end=this.app.config.get("query_limit"));var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f])continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,end:e.end,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){console.debug("Datasets::_fill_from_cache() - Filling request from cache.");for(var t in e.groups){var n=e.groups[t];n.values=[];for(var r in n.columns){var i=n.columns[r],s=this._block_id(e,i.index),o=this.cache[s];for(k in o){var u=n.values[k];u===undefined&&(u={x:parseInt(k)+e.start},n.values[k]=u);var a=o[k];isNaN(a)&&!i.is_label&&(a=0),u[r]=a}}}},_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=0;t.columns&&(o=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+o+" column(s)")),o==0&&console.debug("Datasets::_fetch() - No columns requested");var u="";for(var a in t.columns)u+=t.columns[a]+",";u=u.substring(0,u.length-1);var f=this;e.request("GET",config.root+"api/datasets/"+t.dataset_id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:u},function(e){var t=new Array(o);for(var r=0;r<o;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var s in i){var u=i[s];u!==undefined&&u!=2147483647&&t[s].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)})}})}),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){this.process[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({container_list:[],canvas_list:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,80),this._createContainer("div");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=r.$el.find("container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info")),t.hide();var i=r.chart.get("state");switch(i){case"ok":e.hide(),t.show();break;case"failed":n.addClass("fa fa-warning");break;default:n.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_createContainer:function(e,t){t=t||1;for(var n in this.container_list)this.container_list[n].remove();this.container_list=[],this.canvas_list=[];for(var n=0;n<t;n++){var r=$(this._templateContainer(e,parseInt(100/t)));this.$el.append(r),this.container_list[n]=r,e=="svg"?this.canvas_list[n]=d3.select(r.find("#canvas")[0]):this.canvas_list[n]=r.find("#canvas")}},_draw:function(e){var t=this,n=e.deferred.register(),r=e.get("type");this.chart_settings=this.app.types.get(r);var i=this.chart_settings.use_panels,s=1;i&&(s=e.groups.length),this._createContainer(this.chart_settings.tag,s),e.state("wait","Please wait...");if(!this.chart_settings.execute||this.chart_settings.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+r+"/"+r],function(r){var i=new r(t.app,{canvas:t.canvas_list});t.chart_settings.execute?t.app.jobs.request(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){i.draw(n,e,t._defaultRequestDictionary(e))},function(){e.deferred.done(n)}):i.draw(n,e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){for(var i in r.chart_settings.columns)t+=i+"_"+ ++n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.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={groups:[]};this.chart_settings.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var n=0,r=this;return e.groups.each(function(e){var i={};for(var s in r.chart_settings.columns){var o=r.chart_settings.columns[s];i[s]={index:e.get(s),is_label:o.is_label}}t.groups.push({key:++n+":"+e.get("key"),columns:i})}),t},_template:function(){return'<div style="height: inherit; 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>'},_templateContainer:function(e,t){return'<div class="container" style="float: left; display: block; width:'+t+'%; height: 100%;">'+'<div id="menu"/>'+"<"+e+' id="canvas" class="canvas" style="display: block; width:100%; height: inherit;">'+"</div>"}})}),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-edit",tooltip:"Customize this chart",title:"Editor",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)},_screenshot:function(){var e=new XMLSerializer,t=e.serializeToString(this.viewport_view.svg.node()),n="data:image/svg+xml;base64,"+btoa(t);window.location.href="data:application/x-download/;charset=utf-8,"+encodeURIComponent(t)},_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,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},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({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){for(var t in s){var n=i.columns[t].is_label,o=[],u=e.metadata_column_types;for(var a in u)(!n&&(u[a]=="int"||u[a]=="float")||n)&&o.push({label:"Column: "+(parseInt(a)+1)+" ["+u[a]+"]",value:a});s[t].update(o),s[t].show()}r.chart.state("ok","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({list:[],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(),this.list=[];for(var n in e)this._add(n,e[n],t);for(var n in this.list){var r=this.list[n].options.onchange;r&&r()}},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:e,placeholder:n.placeholder,onchange:function(){r.set(e,s.value())}});break;case"select":s=new t.Select.View({id:e,data:n.data,onchange:function(){var t=s.value();r.set(e,t);var o=_.findWhere(n.data,{value:t});o&&(o.show&&i.$el.find("#"+o.show).fadeIn("fast"),o.hide&&i.$el.find("#"+o.hide).fadeOut("fast"))}});break;case"separator":s=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),u.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(u)}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,onchange:function(e){u.chart.settings.clear(),u.chart.set({type:e}),u.chart.set("modified",!0)},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"}),this.table.addHeader("No."),this.table.addHeader("Type"),this.table.addHeader("Processing*"),this.table.appendHeader();var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),this.table.add(h.title),h.execute?this.table.add((new n.Icon({icon:"fa-check"})).$el,"10%","center"):this.table.add(""),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)),p.append((new n.Text({title:"*Certain chart types pre-process data before rendering the visualization. The pre-processing is done using the charts tool available in the Toolshed.",cls:"toolParamHelp"})).$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","nvd3_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:5e3,query_timeout:500}})}),define("plugin/charts/nvd3/config",[],function(){return{title:"",library:"nvd3.js",tag:"svg",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:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"x_axis_tick"},{label:"Auto",value:"auto",hide:"x_axis_tick"},{label:"Float",value:"f",show:"x_axis_tick"},{label:"Exponent",value:"e",show:"x_axis_tick"},{label:"Integer",value:"d",hide:"x_axis_tick"},{label:"Percentage",value:"p",show:"x_axis_tick"},{label:"Rounded",value:"r",show:"x_axis_tick"},{label:"SI-prefix",value:"s",show:"x_axis_tick"}]},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:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"y_axis_tick"},{label:"Auto",value:"auto",hide:"y_axis_tick"},{label:"Float",value:"f",show:"y_axis_tick"},{label:"Exponent",value:"e",show:"y_axis_tick"},{label:"Integer",value:"d",hide:"y_axis_tick"},{label:"Percentage",value:"p",show:"y_axis_tick"},{label:"Rounded",value:"r",show:"y_axis_tick"},{label:"SI-prefix",value:"s",show:"y_axis_tick"}]},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/nvd3_bardiagram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/nvd3_histogram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:"histogram",columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_tick:{init:".2"}}})}),define("plugin/charts/nvd3_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/nvd3_line/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/nvd3_linewithfocus/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/nvd3_piechart/config",[],function(){return{title:"Pie chart",library:"nvd3.js",tag:"svg",use_panels:!0,columns:{label:{title:"Labels",is_label:!0},y:{title:"Values"}},settings:{show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/nvd3_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/nvd3_stackedarea/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/highcharts_boxplot/config",[],function(){return{title:"Box plot",library:"highcharts.js",tag:"div",execute:"boxplot",columns:{y:{title:"Observations"}},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"},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"}}}}),define("plugin/charts/heatmap/config",[],function(){return{title:"Heatmap",library:"",tag:"div",use_panels:!0,execute:"heatmap",columns:{row_label:{title:"Row labels",is_label:!0},col_label:{title:"Column labels",is_label:!0},value:{title:"Observations"}},settings:{color_set:{title:"Color scheme",info:"Select a color scheme for your heatmap",type:"select",init:"ocean",data:[{label:"Cold-to-Hot",value:"hot"},{label:"Cool",value:"cool"},{label:"Copper",value:"copper"},{label:"Gebco",value:"gebco"},{label:"Globe",value:"globe"},{label:"Gray scale",value:"gray"},{label:"Haxby",value:"haxby"},{label:"Jet",value:"jet"},{label:"No-Green",value:"no_green"},{label:"Ocean",value:"ocean"},{label:"Polar",value:"polar"},{label:"Rainbow",value:"rainbow"},{label:"Red-to-Green",value:"redgreen"},{label:"Red-to-green (saturated)",value:"red2green"},{label:"Relief",value:"relief"},{label:"Seismograph",value:"seis"},{label:"Sealand",value:"sealand"},{label:"Split",value:"split"},{label:"Topo",value:"topo"},{label:"Wysiwyg",value:"wysiwyg"}]},sorting:{title:"Sorting",info:"How should the columns be clustered?",type:"select",init:"hclust",data:[{label:"Read from dataset",value:"hclust"},{label:"Sort column and row labels",value:"byboth"},{label:"Sort column labels",value:"bycolumns"},{label:"Sort by rows",value:"byrow"}]}},menu:function(){return{color_set:this.settings.color_set}}}}),define("plugin/charts/types",["plugin/charts/nvd3_bardiagram/config","plugin/charts/nvd3_histogram/config","plugin/charts/nvd3_horizontal/config","plugin/charts/nvd3_line/config","plugin/charts/nvd3_linewithfocus/config","plugin/charts/nvd3_piechart/config","plugin/charts/nvd3_scatterplot/config","plugin/charts/nvd3_stackedarea/config","plugin/charts/highcharts_boxplot/config","plugin/charts/heatmap/config"],function(e,t,n,r,i,s,o,u,a,f){return Backbone.Model.extend({defaults:{nvd3_bardiagram:e,nvd3_horizontal:n,nvd3_histogram:t,nvd3_line:r,nvd3_linewithfocus:i,nvd3_piechart:s,nvd3_scatterplot:o,nvd3_stackedarea:u,highcharts_boxplot:a}})}),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
+define("mvc/ui/ui-modal",[],function(){var e=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1,closing_callback:null},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"),this.options.closing_callback&&this.options.closing_callback()},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:e}}),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-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:{url:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},_template:function(e){return'<img src="'+e.url+'"/>'}}),r=Backbone.View.extend({optionsDefault:{title:"",cls:""},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 class="'+e.cls+'"><b>'+e.title+"</b></label>"},value:function(){return options.title}}),i=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<div class="'+e.cls+'">'+e.title+"</div>"},value:function(){return options.title}}),s=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}}),o=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}}),u=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>"}}),a=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>"}}),f=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>"}}),l=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>"}}),c=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>"}}),h=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}}),p=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:r,Image:n,Button:s,Icon:u,ButtonIcon:o,Input:p,Anchor:a,Message:f,Searchbox:l,Title:c,Text:i,Select:t,ButtonMenu:h}}),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)},request:function(e,t,n,r,i){var s=this;e.state("wait","Requesting job results...");var o=e.get("dataset_id_job");o!=""?s._wait(e,r,i):s._submit(e,t,n,r,i)},cleanup:function(t){var n=this,r=t.get("dataset_id_job");r!=""&&(e.request("PUT",config.root+"api/histories/none/contents/"+r,{deleted:!0},function(){n._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:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,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","Your job has been queued. You may close the browser window. The job will run in the background."),t.set("dataset_id_job",n.id),this.app.storage.save(),o._wait(t,i,s)}},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 'charts' tool. Please make sure it is installed. "+n),s&&s()})},_wait:function(t,n,r){var i=this;e.request("GET",config.root+"api/datasets/"+t.get("dataset_id_job"),{},function(e){var s=!1;switch(e.state){case"ok":t.state("wait","Job completed successfully..."),n&&n(e),s=!0;break;case"error":t.state("failed","Job has failed. Please check the history for details."),r&&r(e),s=!0;break;case"running":t.state("wait","Your job is running. You may close the browser window. The job will continue in the background.")}s||setTimeout(function(){i._wait(t,n,r)},i.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshContents()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},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._get(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)}})}},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.end+"_"+t},_get:function(e,t){e.start||(e.start=0),e.end||(e.end=this.app.config.get("query_limit"));var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f])continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,end:e.end,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){console.debug("Datasets::_fill_from_cache() - Filling request from cache.");for(var t in e.groups){var n=e.groups[t];n.values=[];for(var r in n.columns){var i=n.columns[r],s=this._block_id(e,i.index),o=this.cache[s];for(k in o){var u=n.values[k];u===undefined&&(u={x:parseInt(k)+e.start},n.values[k]=u);var a=o[k];isNaN(a)&&!i.is_label&&(a=0),u[r]=a}}}},_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=0;t.columns&&(o=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+o+" column(s)")),o==0&&console.debug("Datasets::_fetch() - No columns requested");var u="";for(var a in t.columns)u+=t.columns[a]+",";u=u.substring(0,u.length-1);var f=this;e.request("GET",config.root+"api/datasets/"+t.dataset_id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:u},function(e){var t=new Array(o);for(var r=0;r<o;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var s in i){var u=i[s];u!==undefined&&u!=2147483647&&t[s].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)})}})}),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){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},ready:function(){return this.counter==0}})});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({container_list:[],canvas_list:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,80),this._createContainer("div");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=r.$el.find("container"),n=e.find("#icon");n.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info")),t.hide();var i=r.chart.get("state");switch(i){case"ok":e.hide(),t.show();break;case"failed":n.addClass("fa fa-warning");break;default:n.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_createContainer:function(e,t){t=t||1;for(var n in this.container_list)this.container_list[n].remove();this.container_list=[],this.canvas_list=[];for(var n=0;n<t;n++){var r=$(this._templateContainer(e,parseInt(100/t)));this.$el.append(r),this.container_list[n]=r,e=="svg"?this.canvas_list[n]=d3.select(r.find("#canvas")[0]):this.canvas_list[n]=r.find("#canvas")}},_draw:function(e){var t=this,n=e.deferred.register(),r=e.get("type");this.chart_settings=this.app.types.get(r);var i=this.chart_settings.use_panels,s=1;i&&(s=e.groups.length),this._createContainer(this.chart_settings.tag,s),e.state("wait","Please wait...");if(!this.chart_settings.execute||this.chart_settings.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+r+"/wrapper"],function(r){var i=new r(t.app,{canvas:t.canvas_list});t.chart_settings.execute?t.app.jobs.request(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){i.draw(n,e,t._defaultRequestDictionary(e))},function(){e.deferred.done(n)}):i.draw(n,e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){for(var i in r.chart_settings.columns)t+=i+"_"+ ++n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.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={groups:[]};this.chart_settings.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var n=0,r=this;return e.groups.each(function(e){var i={};for(var s in r.chart_settings.columns){var o=r.chart_settings.columns[s];i[s]={index:e.get(s),is_label:o.is_label}}t.groups.push({key:++n+":"+e.get("key"),columns:i})}),t},_template:function(){return'<div class="charts-viewport"><div id="info" class="info"><span id="icon" class="icon" /><span id="text" class="text" /></div></div>'},_templateContainer:function(e,t){return'<div class="container" style="width:'+t+'%;">'+'<div id="menu"/>'+"<"+e+' id="canvas" class="canvas">'+"</div>"}})}),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-edit",tooltip:"Customize this chart",title:"Editor",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)},_screenshot:function(){var e=new XMLSerializer,t=e.serializeToString(this.viewport_view.svg.node()),n="data:image/svg+xml;base64,"+btoa(t);window.location.href="data:application/x-download/;charset=utf-8,"+encodeURIComponent(t)},_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,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},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!=""&&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({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){for(var t in s){var n=i.columns[t].is_label,o=[],u=e.metadata_column_types;for(var a in u)(!n&&(u[a]=="int"||u[a]=="float")||n)&&o.push({label:"Column: "+(parseInt(a)+1)+" ["+u[a]+"]",value:a});s[t].update(o),s[t].show()}r.chart.state("ok","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({list:[],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(),this.list=[];for(var n in e)this._add(n,e[n],t);for(var n in this.list){var r=this.list[n].options.onchange;r&&r()}},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:e,placeholder:n.placeholder,onchange:function(){r.set(e,s.value())}});break;case"select":s=new t.Select.View({id:e,data:n.data,onchange:function(){var t=s.value();r.set(e,t);var o=_.findWhere(n.data,{value:t});o&&(o.show&&i.$el.find("#"+o.show).fadeIn("fast"),o.hide&&i.$el.find("#"+o.hide).fadeOut("fast"))}});break;case"separator":s=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),u.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(u)}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.category+" - "+t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/types",["utils/utils","plugin/library/ui"],function(e,t){return Backbone.View.extend({optionsDefault:{onchange:null,ondblclick:null},events:{click:"_onclick",dblclick:"_ondblclick"},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault);var r=$('<div class="charts-grid"/>');this.setElement(r);var i={},s=t.types.attributes;for(var o in s){var u=s[o],a=u.category;i[a]||(i[a]={}),i[a][o]=u}for(var a in i){var r=$('<div style="clear: both;"/>');r.append(e.wrap(this._template_header({title:a})));for(var o in i[a]){var u=i[a][o];r.append(e.wrap(this._template_item({id:o,title:u.title,url:config.app_root+"charts/"+o+"/logo.png"})))}this.$el.append(e.wrap(r))}},value:function(e){var t=this.$el.find(".current").attr("id");e!==undefined&&(this.$el.find(".current").removeClass("current"),this.$el.find("#"+e).addClass("current"));var n=this.$el.find(".current").attr("id");return n===undefined?null:(n!=t&&this.options.onchange&&this.options.onchange(e),n)},_onclick:function(e){var t=this.value(),n=$(e.target).closest(".item").attr("id");n!=""&&n&&t!=n&&this.value(n)},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_template_header:function(e){return'<div class="header">• '+e.title+"<div>"},_template_item:function(e){return'<div id="'+e.id+'" class="item">'+'<img class="image" src="'+e.url+'">'+'<div class="title">'+e.title+"</div>"+"<div>"}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings","plugin/views/types"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(i,s){var o=this;this.app=i,this.chart=this.app.chart,this.options=r.merge(s,this.optionsDefault),this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new t.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){o.app.go("viewer"),o._saveChart()}}),back:new t.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){o.app.go("viewer"),o.app.storage.load()}})}}),this.types=new a(i,{onchange:function(e){o.chart.settings.clear(),o.chart.set({type:e}),o.chart.set("modified",!0)},ondblclick:function(e){o.app.go("viewer"),o._saveChart()}}),this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=o._addGroupModel();o.tabs.show(e.id)}}),this.title=new t.Input({placeholder:"Chart title",onchange:function(){o.chart.set("title",o.title.value())}});var f=$("<div/>");f.append(r.wrap((new t.Label({title:"Provide a chart title:"})).$el)),f.append(r.wrap(this.title.$el)),f.append(r.wrap((new t.Label({title:"Select a chart type:"})).$el)),f.append(r.wrap(this.types.$el)),this.tabs.add({id:"main",title:"Start",$el:f}),this.settings=new u(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 o=this;this.chart.on("change:title",function(e){o._refreshTitle()}),this.chart.on("change:type",function(e){o.types.value(e.get("type"))}),this.chart.on("reset",function(e){o._resetChart()}),this.app.chart.on("redraw",function(e){o.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){o._addGroup(e)}),this.app.chart.groups.on("remove",function(e){o._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){o._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){o._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 s({id:r.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new o(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",r.uuid()),this.chart.set("type","nvd3_bar"),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.types.value(),title:this.title.value(),date:r.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:5e3,query_timeout:500}})}),define("plugin/charts/nvd3/config",[],function(){return{title:"",category:"",library:"nvd3.js",tag:"svg",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:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"x_axis_tick"},{label:"Auto",value:"auto",hide:"x_axis_tick"},{label:"Float",value:"f",show:"x_axis_tick"},{label:"Exponent",value:"e",show:"x_axis_tick"},{label:"Integer",value:"d",hide:"x_axis_tick"},{label:"Percentage",value:"p",show:"x_axis_tick"},{label:"Rounded",value:"r",show:"x_axis_tick"},{label:"SI-prefix",value:"s",show:"x_axis_tick"}]},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:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"y_axis_tick"},{label:"Auto",value:"auto",hide:"y_axis_tick"},{label:"Float",value:"f",show:"y_axis_tick"},{label:"Exponent",value:"e",show:"y_axis_tick"},{label:"Integer",value:"d",hide:"y_axis_tick"},{label:"Percentage",value:"p",show:"y_axis_tick"},{label:"Rounded",value:"r",show:"y_axis_tick"},{label:"SI-prefix",value:"s",show:"y_axis_tick"}]},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/nvd3_bar/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Bar diagrams"})}),define("plugin/charts/nvd3_bar_stacked/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked",category:"Bar diagrams"})}),define("plugin/charts/nvd3_bar_horizontal/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/nvd3_bar_horizontal_stacked/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked horizontal",category:"Bar diagrams",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/nvd3_histogram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",category:"Data processing (requires 'charts' tool from Toolshed)",execute:"histogram",columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_tick:{init:".2"}}})}),define("plugin/charts/nvd3_line/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart",category:"Others"})}),define("plugin/charts/nvd3_line_focus/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus",category:"Others"})}),define("plugin/charts/nvd3_pie/config",[],function(){return{title:"Pie chart",library:"nvd3.js",category:"Area charts",tag:"svg",use_panels:!0,columns:{label:{title:"Labels",is_label:!0},y:{title:"Values"}},settings:{show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/nvd3_scatter/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",category:"Others",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/nvd3_stackedarea/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Regular",category:"Area charts"})}),define("plugin/charts/nvd3_stackedarea_full/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Expanded",category:"Area charts"})}),define("plugin/charts/nvd3_stackedarea_stream/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stream",category:"Area charts"})}),define("plugin/charts/highcharts_boxplot/config",[],function(){return{title:"Box plot",category:"Data processing (requires 'charts' tool from Toolshed)",library:"highcharts.js",tag:"div",execute:"boxplot",columns:{y:{title:"Observations"}},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"},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"}}}}),define("plugin/charts/heatmap/config",[],function(){return{title:"Heatmap",category:"Data processing (requires 'charts' tool from Toolshed)",library:"",tag:"div",use_panels:!0,execute:"heatmap",columns:{row_label:{title:"Row labels",is_label:!0},col_label:{title:"Column labels",is_label:!0},value:{title:"Observations"}},settings:{color_set:{title:"Color scheme",info:"Select a color scheme for your heatmap",type:"select",init:"ocean",data:[{label:"Cold-to-Hot",value:"hot"},{label:"Cool",value:"cool"},{label:"Copper",value:"copper"},{label:"Gebco",value:"gebco"},{label:"Globe",value:"globe"},{label:"Gray scale",value:"gray"},{label:"Haxby",value:"haxby"},{label:"Jet",value:"jet"},{label:"No-Green",value:"no_green"},{label:"Ocean",value:"ocean"},{label:"Polar",value:"polar"},{label:"Rainbow",value:"rainbow"},{label:"Red-to-Green",value:"redgreen"},{label:"Red-to-green (saturated)",value:"red2green"},{label:"Relief",value:"relief"},{label:"Seismograph",value:"seis"},{label:"Sealand",value:"sealand"},{label:"Split",value:"split"},{label:"Topo",value:"topo"},{label:"Wysiwyg",value:"wysiwyg"}]},sorting:{title:"Sorting",info:"How should the columns be clustered?",type:"select",init:"hclust",data:[{label:"Read from dataset",value:"hclust"},{label:"Sort column and row labels",value:"byboth"},{label:"Sort column labels",value:"bycolumns"},{label:"Sort by rows",value:"byrow"}]}},menu:function(){return{color_set:this.settings.color_set}}}}),define("plugin/charts/types",["plugin/charts/nvd3_bar/config","plugin/charts/nvd3_bar_stacked/config","plugin/charts/nvd3_bar_horizontal/config","plugin/charts/nvd3_bar_horizontal_stacked/config","plugin/charts/nvd3_histogram/config","plugin/charts/nvd3_line/config","plugin/charts/nvd3_line_focus/config","plugin/charts/nvd3_pie/config","plugin/charts/nvd3_scatter/config","plugin/charts/nvd3_stackedarea/config","plugin/charts/nvd3_stackedarea_full/config","plugin/charts/nvd3_stackedarea_stream/config","plugin/charts/highcharts_boxplot/config","plugin/charts/heatmap/config"],function(e,t,n,r,i,s,o,u,a,f,l,c,h,p){return Backbone.Model.extend({defaults:{nvd3_bar:e,nvd3_bar_stacked:t,nvd3_bar_horizontal:n,nvd3_bar_horizontal_stacked:r,nvd3_stackedarea:f,nvd3_stackedarea_full:l,nvd3_stackedarea_stream:c,nvd3_line:s,nvd3_line_focus:o,nvd3_scatter:a,nvd3_pie:u,nvd3_histogram:i,highcharts_boxplot:h,heatmap:p}})}),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 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/heatmap/config.js
--- a/config/plugins/visualizations/charts/static/charts/heatmap/config.js
+++ b/config/plugins/visualizations/charts/static/charts/heatmap/config.js
@@ -2,6 +2,7 @@
return {
title : 'Heatmap',
+ category : 'Data processing (requires \'charts\' tool from Toolshed)',
library : '',
tag : 'div',
use_panels : true,
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/heatmap/heatmap.js
--- a/config/plugins/visualizations/charts/static/charts/heatmap/heatmap.js
+++ /dev/null
@@ -1,71 +0,0 @@
-// dependencies
-define(['utils/utils', 'plugin/charts/heatmap/heatmap-plugin', 'plugin/charts/heatmap/heatmap-parameters'],
-function(Utils, HeatmapPlugin, HeatmapParameters) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- // link this
- var self = this;
-
- // loop through data groups
- var index = 0;
- for (var group_index in request_dictionary.groups) {
-
- // configure request
- for (var i in request_dictionary.groups) {
- var group = request_dictionary.groups[i];
- group.columns = null;
- group.columns = {
- row_label: {
- index : index++,
- is_label : true
- },
- col_label: {
- index : index++,
- is_label : true
- },
- value: {
- index : index++
- }
- }
- }
-
- // request data
- this.app.datasets.request(request_dictionary, function() {
-
- // get group
- var group = request_dictionary.groups[group_index];
- var div = self.options.canvas[group_index];
-
- // draw plot
- var heatmap = new HeatmapPlugin({
- 'title' : group.key,
- 'colors' : HeatmapParameters.colorSets[chart.settings.get('color_set')],
- 'data' : group.values,
- 'div' : div
- });
-
- // check if done
- if (group_index == request_dictionary.groups.length - 1) {
- // set chart state
- chart.state('ok', 'Heat map drawn.');
-
- // unregister process
- chart.deferred.done(process_id);
- }
- });
- }
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/heatmap/logo.png
Binary file config/plugins/visualizations/charts/static/charts/heatmap/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/heatmap/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/heatmap/wrapper.js
@@ -0,0 +1,71 @@
+// dependencies
+define(['utils/utils', 'plugin/charts/heatmap/heatmap-plugin', 'plugin/charts/heatmap/heatmap-parameters'],
+function(Utils, HeatmapPlugin, HeatmapParameters) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ // link this
+ var self = this;
+
+ // loop through data groups
+ var index = 0;
+ for (var group_index in request_dictionary.groups) {
+
+ // configure request
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = null;
+ group.columns = {
+ row_label: {
+ index : index++,
+ is_label : true
+ },
+ col_label: {
+ index : index++,
+ is_label : true
+ },
+ value: {
+ index : index++
+ }
+ }
+ }
+
+ // request data
+ this.app.datasets.request(request_dictionary, function() {
+
+ // get group
+ var group = request_dictionary.groups[group_index];
+ var div = self.options.canvas[group_index];
+
+ // draw plot
+ var heatmap = new HeatmapPlugin({
+ 'title' : group.key,
+ 'colors' : HeatmapParameters.colorSets[chart.settings.get('color_set')],
+ 'data' : group.values,
+ 'div' : div
+ });
+
+ // check if done
+ if (group_index == request_dictionary.groups.length - 1) {
+ // set chart state
+ chart.state('ok', 'Heat map drawn.');
+
+ // unregister process
+ chart.deferred.done(process_id);
+ }
+ });
+ }
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/highcharts_boxplot/config.js
--- a/config/plugins/visualizations/charts/static/charts/highcharts_boxplot/config.js
+++ b/config/plugins/visualizations/charts/static/charts/highcharts_boxplot/config.js
@@ -1,16 +1,17 @@
define([], function() {
return {
- title : 'Box plot',
- library : 'highcharts.js',
- tag : 'div',
- execute : 'boxplot',
- columns : {
+ title : 'Box plot',
+ category : 'Data processing (requires \'charts\' tool from Toolshed)',
+ library : 'highcharts.js',
+ tag : 'div',
+ execute : 'boxplot',
+ columns : {
y : {
title : 'Observations'
}
},
- settings : {
+ settings : {
separator_label : {
title : 'X axis',
type : 'separator'
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/highcharts_boxplot/highcharts_boxplot.js
--- a/config/plugins/visualizations/charts/static/charts/highcharts_boxplot/highcharts_boxplot.js
+++ /dev/null
@@ -1,122 +0,0 @@
-// dependencies
-define(['utils/utils'], function(Utils) {
-
-// widget
-return Backbone.View.extend(
-{
- // highcharts configuration
- hc_config : {
- chart: {
- type: 'boxplot'
- },
-
- title: {
- text: ''
- },
-
- legend: {
- enabled: false
- },
-
- credits: {
- enabled: false
- },
-
- plotOptions: {
- series: {
- animation: false
- }
- },
-
- xAxis: {
- categories: [],
- title: {
- text: ''
- }
- },
-
- yAxis: {
- title: {
- text: ''
- }
- },
-
- series: [{
- name: 'Details:',
- data: [],
- tooltip: {
- headerFormat: '<em>{point.key}</em><br/>'
- }
- }]
- },
-
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- // configure request
- var index = 0;
- for (var i in request_dictionary.groups) {
- var group = request_dictionary.groups[i];
- group.columns = null;
- group.columns = {
- x: {
- index: index++
- }
- }
- }
-
- // set axis labels
- this.hc_config.xAxis.title.text = chart.settings.get('x_axis_label');
- this.hc_config.yAxis.title.text = chart.settings.get('y_axis_label');
-
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function() {
-
- // reset data/categories
- var data = [];
- var categories = [];
-
- // loop through data groups
- for (var key in request_dictionary.groups) {
- // get group
- var group = request_dictionary.groups[key];
-
- // add category
- categories.push(group.key);
-
- // format chart data
- var point = [];
- for (var key in group.values) {
- point.push(group.values[key].x);
- }
-
- // add to data
- data.push (point);
- }
-
- // categories
- self.hc_config.xAxis.categories = categories;
-
- // update data
- self.hc_config.series[0].data = data;
-
- // draw plot
- self.options.canvas[0].highcharts(self.hc_config);
-
- // set chart state
- chart.state('ok', 'Box plot drawn.');
-
- // unregister process
- chart.deferred.done(process_id);
- });
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3/config.js
+++ b/config/plugins/visualizations/charts/static/charts/nvd3/config.js
@@ -2,6 +2,7 @@
return {
title : '',
+ category : '',
library : 'nvd3.js',
tag : 'svg',
columns : {
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a 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
@@ -31,9 +31,7 @@
.axisLabelDistance(30);
// controls
- if (chart.groups.length == 1) {
- nvd3_model.options({ showControls: false });
- }
+ nvd3_model.options({showControls: false});
// legend
var legend_visible = true;
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar/config.js
@@ -0,0 +1,8 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Regular',
+ category : 'Bar diagrams'
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_bar/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar/wrapper.js
@@ -0,0 +1,21 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary);
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal/config.js
@@ -0,0 +1,13 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Horizontal',
+ category : 'Bar diagrams',
+ settings : {
+ x_axis_type : {
+ init : 'hide'
+ }
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal/wrapper.js
@@ -0,0 +1,21 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.multiBarHorizontalChart(), chart, request_dictionary);
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal_stacked/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal_stacked/config.js
@@ -0,0 +1,13 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Stacked horizontal',
+ category : 'Bar diagrams',
+ settings : {
+ x_axis_type : {
+ init : 'hide'
+ }
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal_stacked/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal_stacked/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal_stacked/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_bar_horizontal_stacked/wrapper.js
@@ -0,0 +1,23 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.multiBarHorizontalChart(), chart, request_dictionary, function(nvd3_model) {
+ nvd3_model.stacked(true);
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bardiagram/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_bardiagram/config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-define(['plugin/charts/nvd3/config'], function(nvd3_config) {
-
-return $.extend(true, {}, nvd3_config, {
- title : 'Bar diagram',
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_bardiagram/nvd3_bardiagram.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_bardiagram/nvd3_bardiagram.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary);
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_histogram/config.js
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_histogram/config.js
@@ -1,14 +1,16 @@
+
define(['plugin/charts/nvd3/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
- title : 'Histogram',
- execute : 'histogram',
- columns : {
+ title : 'Histogram',
+ category : 'Data processing (requires \'charts\' tool from Toolshed)',
+ execute : 'histogram',
+ columns : {
y : {
title : 'Observations'
}
},
- settings : {
+ settings : {
x_axis_label : {
init : 'Breaks'
},
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_histogram/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram/nvd3_histogram.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_histogram/nvd3_histogram.js
+++ /dev/null
@@ -1,39 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- // configure request
- var index = 1;
- for (var i in request_dictionary.groups) {
- var group = request_dictionary.groups[i];
- group.columns = {
- x: {
- index: 0
- },
- y: {
- index: index++
- },
- }
- }
-
- // link this
- var self = this;
-
- // load nvd3
- var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary);
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_histogram/wrapper.js
@@ -0,0 +1,41 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ // configure request
+ var index = 1;
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = {
+ x: {
+ index: 0
+ },
+ y: {
+ index: index++
+ },
+ }
+ }
+
+ // link this
+ var self = this;
+
+ // load nvd3
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary, function(nvd3_model) {
+ nvd3_model.options({showControls: true});
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram_discrete/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_histogram_discrete/config.js
@@ -0,0 +1,28 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Histogram',
+ category : 'Histograms',
+ execute : 'histogram_discrete',
+ columns : {
+ y : {
+ title : 'Observations'
+ }
+ },
+ settings : {
+ x_axis_label : {
+ init : 'Breaks'
+ },
+ y_axis_label : {
+ init : 'Density'
+ },
+ y_axis_type : {
+ init : 'f'
+ },
+ y_axis_tick : {
+ init : '.2'
+ }
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram_discrete/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_histogram_discrete/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_histogram_discrete/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_histogram_discrete/wrapper.js
@@ -0,0 +1,39 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ // configure request
+ var index = 1;
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = {
+ x: {
+ index: 0
+ },
+ y: {
+ index: index++
+ },
+ }
+ }
+
+ // link this
+ var self = this;
+
+ // load nvd3
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.multiBarChart(), chart, request_dictionary);
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_horizontal/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_horizontal/config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-define(['plugin/charts/nvd3/config'], function(nvd3_config) {
-
-return $.extend(true, {}, nvd3_config, {
- title : 'Bar diagram (horizontal)',
- settings : {
- x_axis_type : {
- init : 'hide'
- }
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_horizontal/nvd3_horizontal.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_horizontal/nvd3_horizontal.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(process_id, nv.models.multiBarHorizontalChart(), chart, request_dictionary);
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_line/config.js
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_line/config.js
@@ -1,7 +1,8 @@
define(['plugin/charts/nvd3/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
- title : 'Line chart',
+ title : 'Line chart',
+ category : 'Others'
});
});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_line/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line/nvd3_line.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_line/nvd3_line.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(process_id, nv.models.lineChart(), chart, request_dictionary);
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_line/wrapper.js
@@ -0,0 +1,21 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.lineChart(), chart, request_dictionary);
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line_focus/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_line_focus/config.js
@@ -0,0 +1,8 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Line with focus',
+ category : 'Others'
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line_focus/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_line_focus/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_line_focus/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_line_focus/wrapper.js
@@ -0,0 +1,21 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.lineWithFocusChart(), chart, request_dictionary);
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_linewithfocus/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_linewithfocus/config.js
+++ /dev/null
@@ -1,7 +0,0 @@
-define(['plugin/charts/nvd3/config'], function(nvd3_config) {
-
-return $.extend(true, {}, nvd3_config, {
- title : 'Line with focus',
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_linewithfocus/nvd3_linewithfocus.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_linewithfocus/nvd3_linewithfocus.js
+++ /dev/null
@@ -1,21 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(process_id, nv.models.lineWithFocusChart(), chart, request_dictionary);
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_pie/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_pie/config.js
@@ -0,0 +1,115 @@
+define([], function() {
+
+return {
+ title : 'Pie chart',
+ library : 'nvd3.js',
+ category : 'Area charts',
+ tag : 'svg',
+ use_panels : true,
+ columns : {
+ label : {
+ title : 'Labels',
+ is_label : true
+ },
+ y : {
+ title : 'Values'
+ }
+ },
+
+ settings : {
+ show_legend : {
+ title : 'Show legend',
+ info : 'Would you like to add a legend?',
+ type : 'select',
+ init : 'false',
+ data : [
+ {
+ label : 'Yes',
+ value : 'true'
+ },
+ {
+ label : 'No',
+ value : 'false'
+ }
+ ]
+ },
+
+ donut_ratio : {
+ title : 'Donut ratio',
+ info : 'Determine how large the donut hole will be.',
+ type : 'select',
+ init : '0.5',
+ data : [
+ {
+ label : '50%',
+ value : '0.5'
+ },
+ {
+ label : '25%',
+ value : '0.25'
+ },
+ {
+ label : '10%',
+ value : '0.10'
+ },
+ {
+ label : '0%',
+ value : '0'
+ }
+ ]
+ },
+
+ label_separator : {
+ type : 'separator',
+ title : 'Label settings'
+ },
+
+ label_type : {
+ title : 'Donut label',
+ info : 'What would you like to show for each slice?',
+ type : 'select',
+ init : 'percent',
+ data : [
+ {
+ label : '-- Nothing --',
+ value : 'hide',
+ hide : 'label_outside'
+ },
+ {
+ label : 'Label column',
+ value : 'key',
+ show : 'label_outside'
+ },
+ {
+ label : 'Value column',
+ value : 'value',
+ show : 'label_outside'
+ },
+ {
+ label : 'Percentage',
+ value : 'percent',
+ show : 'label_outside'
+ }
+ ],
+ },
+
+ label_outside : {
+ title : 'Show outside',
+ info : 'Would you like to show labels outside the donut?',
+ type : 'select',
+ init : 'false',
+ data : [
+ {
+ label : 'Yes',
+ value : 'true'
+ },
+ {
+ label : 'No',
+ value : 'false'
+ }
+ ]
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_pie/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_pie/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_pie/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_pie/wrapper.js
@@ -0,0 +1,115 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function() {
+
+ // loop through data groups
+ for (var group_index in request_dictionary.groups) {
+ // get group
+ var group = request_dictionary.groups[group_index];
+
+ // draw group
+ self._draw_group(chart, group, self.options.canvas[group_index]);
+ }
+
+ // set chart state
+ chart.state('ok', 'Pie chart has been drawn.');
+
+ // unregister process
+ chart.deferred.done(process_id);
+ });
+ },
+
+ // draw group
+ _draw_group: function(chart, group, canvas) {
+
+ // add title
+ var title = canvas.append('text');
+
+ // configure title attributes
+ this._fix_title(chart, canvas, title, group.key);
+
+ // format chart data
+ var pie_data = [];
+ for (var key in group.values) {
+ var value = group.values[key];
+ pie_data.push ({
+ y : value.y,
+ x : value.label
+ });
+ }
+
+ // add graph to screen
+ var self = this;
+ nv.addGraph(function() {
+ // legend
+ var legend_visible = true;
+ if (chart.settings.get('show_legend') == 'false') {
+ legend_visible = false;
+ }
+
+ // legend
+ var label_outside = true;
+ if (chart.settings.get('label_outside') == 'false') {
+ label_outside = false;
+ }
+
+ // label type
+ var label_type = chart.settings.get('label_type');
+
+ // ratio
+ var donut_ratio = parseFloat(chart.settings.get('donut_ratio'))
+
+ // create chart model
+ var chart_3d = nv.models.pieChart()
+ .donut(true)
+ .labelThreshold(.05)
+ .showLegend(legend_visible)
+ .labelType(label_type)
+ .donutRatio(donut_ratio)
+ .donutLabelsOutside(label_outside);
+
+ // add data to canvas
+ canvas.datum(pie_data)
+ .call(chart_3d);
+
+ // add resize trigger
+ nv.utils.windowResize(function() {
+ // update chart
+ chart_3d.update();
+
+ // fix title
+ self._fix_title(chart, canvas, title, group.key);
+ });
+ });
+ },
+
+ // fix title
+ _fix_title: function(chart, canvas, title_element, title_text) {
+ // update title
+ var width = parseInt(canvas.style('width'));
+ var height = parseInt(canvas.style('height'));
+
+ // add title
+ title_element.attr('x', width / 2)
+ .attr('y', height - 10)
+ .attr('text-anchor', 'middle')
+ .text(title_text);
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_piechart/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_piechart/config.js
+++ /dev/null
@@ -1,114 +0,0 @@
-define([], function() {
-
-return {
- title : 'Pie chart',
- library : 'nvd3.js',
- tag : 'svg',
- use_panels : true,
- columns : {
- label : {
- title : 'Labels',
- is_label : true
- },
- y : {
- title : 'Values'
- }
- },
-
- settings : {
- show_legend : {
- title : 'Show legend',
- info : 'Would you like to add a legend?',
- type : 'select',
- init : 'false',
- data : [
- {
- label : 'Yes',
- value : 'true'
- },
- {
- label : 'No',
- value : 'false'
- }
- ]
- },
-
- donut_ratio : {
- title : 'Donut ratio',
- info : 'Determine how large the donut hole will be.',
- type : 'select',
- init : '0.5',
- data : [
- {
- label : '50%',
- value : '0.5'
- },
- {
- label : '25%',
- value : '0.25'
- },
- {
- label : '10%',
- value : '0.10'
- },
- {
- label : '0%',
- value : '0'
- }
- ]
- },
-
- label_separator : {
- type : 'separator',
- title : 'Label settings'
- },
-
- label_type : {
- title : 'Donut label',
- info : 'What would you like to show for each slice?',
- type : 'select',
- init : 'percent',
- data : [
- {
- label : '-- Nothing --',
- value : 'hide',
- hide : 'label_outside'
- },
- {
- label : 'Label column',
- value : 'key',
- show : 'label_outside'
- },
- {
- label : 'Value column',
- value : 'value',
- show : 'label_outside'
- },
- {
- label : 'Percentage',
- value : 'percent',
- show : 'label_outside'
- }
- ],
- },
-
- label_outside : {
- title : 'Show outside',
- info : 'Would you like to show labels outside the donut?',
- type : 'select',
- init : 'false',
- data : [
- {
- label : 'Yes',
- value : 'true'
- },
- {
- label : 'No',
- value : 'false'
- }
- ]
- }
- }
-};
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_piechart/nvd3_piechart.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_piechart/nvd3_piechart.js
+++ /dev/null
@@ -1,115 +0,0 @@
-// dependencies
-define(['utils/utils'], function(Utils) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function() {
-
- // loop through data groups
- for (var group_index in request_dictionary.groups) {
- // get group
- var group = request_dictionary.groups[group_index];
-
- // draw group
- self._draw_group(chart, group, self.options.canvas[group_index]);
- }
-
- // set chart state
- chart.state('ok', 'Pie chart has been drawn.');
-
- // unregister process
- chart.deferred.done(process_id);
- });
- },
-
- // draw group
- _draw_group: function(chart, group, canvas) {
-
- // add title
- var title = canvas.append('text');
-
- // configure title attributes
- this._fix_title(chart, canvas, title, group.key);
-
- // format chart data
- var pie_data = [];
- for (var key in group.values) {
- var value = group.values[key];
- pie_data.push ({
- y : value.y,
- x : value.label
- });
- }
-
- // add graph to screen
- var self = this;
- nv.addGraph(function() {
- // legend
- var legend_visible = true;
- if (chart.settings.get('show_legend') == 'false') {
- legend_visible = false;
- }
-
- // legend
- var label_outside = true;
- if (chart.settings.get('label_outside') == 'false') {
- label_outside = false;
- }
-
- // label type
- var label_type = chart.settings.get('label_type');
-
- // ratio
- var donut_ratio = parseFloat(chart.settings.get('donut_ratio'))
-
- // create chart model
- var chart_3d = nv.models.pieChart()
- .donut(true)
- .labelThreshold(.05)
- .showLegend(legend_visible)
- .labelType(label_type)
- .donutRatio(donut_ratio)
- .donutLabelsOutside(label_outside);
-
- // add data to canvas
- canvas.datum(pie_data)
- .call(chart_3d);
-
- // add resize trigger
- nv.utils.windowResize(function() {
- // update chart
- chart_3d.update();
-
- // fix title
- self._fix_title(chart, canvas, title, group.key);
- });
- });
- },
-
- // fix title
- _fix_title: function(chart, canvas, title_element, title_text) {
- // update title
- var width = parseInt(canvas.style('width'));
- var height = parseInt(canvas.style('height'));
-
- // add title
- title_element.attr('x', width / 2)
- .attr('y', height - 10)
- .attr('text-anchor', 'middle')
- .text(title_text);
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_scatter/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_scatter/config.js
@@ -0,0 +1,13 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Scatter plot',
+ category : 'Others',
+ columns : {
+ x : {
+ title : 'Values for x-axis'
+ }
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_scatter/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_scatter/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_scatter/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_scatter/wrapper.js
@@ -0,0 +1,25 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ nvd3.draw(process_id, nv.models.scatterChart(), chart, request_dictionary, function(nvd3_model) {
+ nvd3_model.showDistX(true)
+ .showDistY(true)
+ .color(d3.scale.category10().range());
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_scatterplot/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_scatterplot/config.js
+++ /dev/null
@@ -1,12 +0,0 @@
-define(['plugin/charts/nvd3/config'], function(nvd3_config) {
-
-return $.extend(true, {}, nvd3_config, {
- title : 'Scatter plot',
- columns : {
- x : {
- title : 'Values for x-axis'
- }
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_scatterplot/nvd3_scatterplot.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_scatterplot/nvd3_scatterplot.js
+++ /dev/null
@@ -1,25 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- var nvd3 = new NVD3(this.app, this.options);
- nvd3.draw(process_id, nv.models.scatterChart(), chart, request_dictionary, function(nvd3_model) {
- nvd3_model.showDistX(true)
- .showDistY(true)
- .color(d3.scale.category10().range());
- });
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/config.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/config.js
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/config.js
@@ -1,7 +1,8 @@
define(['plugin/charts/nvd3/config'], function(nvd3_config) {
return $.extend(true, {}, nvd3_config, {
- title : 'Stacked area'
+ title : 'Regular',
+ category : 'Area charts'
});
});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/nvd3_stackedarea.js
--- a/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/nvd3_stackedarea.js
+++ /dev/null
@@ -1,26 +0,0 @@
-// dependencies
-define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- draw : function(process_id, chart, request_dictionary)
- {
- var nvd3 = new NVD3(this.app, this.options);
- 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 })
- .clipEdge(true);
- });
- }
-});
-
-});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea/wrapper.js
@@ -0,0 +1,26 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ 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 })
+ .clipEdge(true);
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_full/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_full/config.js
@@ -0,0 +1,8 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Expanded',
+ category : 'Area charts'
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_full/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_full/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_full/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_full/wrapper.js
@@ -0,0 +1,27 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ 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 })
+ .clipEdge(true)
+ .style('expand');
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_stream/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_stream/config.js
@@ -0,0 +1,8 @@
+define(['plugin/charts/nvd3/config'], function(nvd3_config) {
+
+return $.extend(true, {}, nvd3_config, {
+ title : 'Stream',
+ category : 'Area charts'
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_stream/logo.png
Binary file config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_stream/logo.png has changed
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_stream/wrapper.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/nvd3_stackedarea_stream/wrapper.js
@@ -0,0 +1,27 @@
+// dependencies
+define(['plugin/charts/nvd3/nvd3'], function(NVD3) {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(process_id, chart, request_dictionary)
+ {
+ var nvd3 = new NVD3(this.app, this.options);
+ 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 })
+ .clipEdge(true)
+ .style('stream');
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/charts/types.js
--- a/config/plugins/visualizations/charts/static/charts/types.js
+++ b/config/plugins/visualizations/charts/static/charts/types.js
@@ -1,22 +1,30 @@
// dependencies
-define(['plugin/charts/nvd3_bardiagram/config',
+define(['plugin/charts/nvd3_bar/config',
+ 'plugin/charts/nvd3_bar_stacked/config',
+ 'plugin/charts/nvd3_bar_horizontal/config',
+ 'plugin/charts/nvd3_bar_horizontal_stacked/config',
'plugin/charts/nvd3_histogram/config',
- 'plugin/charts/nvd3_horizontal/config',
'plugin/charts/nvd3_line/config',
- 'plugin/charts/nvd3_linewithfocus/config',
- 'plugin/charts/nvd3_piechart/config',
- 'plugin/charts/nvd3_scatterplot/config',
+ 'plugin/charts/nvd3_line_focus/config',
+ 'plugin/charts/nvd3_pie/config',
+ 'plugin/charts/nvd3_scatter/config',
'plugin/charts/nvd3_stackedarea/config',
+ 'plugin/charts/nvd3_stackedarea_full/config',
+ 'plugin/charts/nvd3_stackedarea_stream/config',
'plugin/charts/highcharts_boxplot/config',
'plugin/charts/heatmap/config',
- ], function(nvd3_bardiagram,
+ ], function(nvd3_bar,
+ nvd3_bar_stacked,
+ nvd3_bar_horizontal,
+ nvd3_bar_horizontal_stacked,
nvd3_histogram,
- nvd3_horizontal,
nvd3_line,
- nvd3_linewithfocus,
- nvd3_piechart,
- nvd3_scatterplot,
+ nvd3_line_focus,
+ nvd3_pie,
+ nvd3_scatter,
nvd3_stackedarea,
+ nvd3_stackedarea_full,
+ nvd3_stackedarea_stream,
highcharts_boxplot,
heatmap
) {
@@ -26,16 +34,20 @@
{
// types
defaults: {
- 'nvd3_bardiagram' : nvd3_bardiagram,
- 'nvd3_horizontal' : nvd3_horizontal,
- //'heatmap' : heatmap,
- 'nvd3_histogram' : nvd3_histogram,
- 'nvd3_line' : nvd3_line,
- 'nvd3_linewithfocus' : nvd3_linewithfocus,
- 'nvd3_piechart' : nvd3_piechart,
- 'nvd3_scatterplot' : nvd3_scatterplot,
- 'nvd3_stackedarea' : nvd3_stackedarea,
- 'highcharts_boxplot' : highcharts_boxplot
+ 'nvd3_bar' : nvd3_bar,
+ 'nvd3_bar_stacked' : nvd3_bar_stacked,
+ 'nvd3_bar_horizontal' : nvd3_bar_horizontal,
+ 'nvd3_bar_horizontal_stacked' : nvd3_bar_horizontal_stacked,
+ 'nvd3_stackedarea' : nvd3_stackedarea,
+ 'nvd3_stackedarea_full' : nvd3_stackedarea_full,
+ 'nvd3_stackedarea_stream' : nvd3_stackedarea_stream,
+ 'nvd3_line' : nvd3_line,
+ 'nvd3_line_focus' : nvd3_line_focus,
+ 'nvd3_scatter' : nvd3_scatter,
+ 'nvd3_pie' : nvd3_pie,
+ 'nvd3_histogram' : nvd3_histogram,
+ 'highcharts_boxplot' : highcharts_boxplot,
+ 'heatmap' : heatmap
}
});
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/library/deferred.js
--- a/config/plugins/visualizations/charts/static/library/deferred.js
+++ b/config/plugins/visualizations/charts/static/library/deferred.js
@@ -76,11 +76,7 @@
// ready
ready: function() {
- if (this.counter == 0) {
- return true;
- } else {
- return false;
- }
+ return (this.counter == 0);
}
});
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/library/ui-table.js
--- a/config/plugins/visualizations/charts/static/library/ui-table.js
+++ b/config/plugins/visualizations/charts/static/library/ui-table.js
@@ -162,13 +162,14 @@
// get values
var old_value = this.value();
var new_value = $(e.target).closest('tr').attr('id');
-
- // check equality
- if (new_value && old_value != new_value) {
- if (this.options.onconfirm) {
- this.options.onconfirm(new_value);
- } else {
- this.value(new_value);
+ if (new_value != ''){
+ // check equality
+ if (new_value && old_value != new_value) {
+ if (this.options.onconfirm) {
+ this.options.onconfirm(new_value);
+ } else {
+ this.value(new_value);
+ }
}
}
},
diff -r 31e5817ba7d36a039c432205b32958e190cbabbc -r 2b4c26870efbc19441f02da19659c830cc8b591a config/plugins/visualizations/charts/static/library/ui.js
--- a/config/plugins/visualizations/charts/static/library/ui.js
+++ b/config/plugins/visualizations/charts/static/library/ui.js
@@ -2,11 +2,35 @@
define(['utils/utils', 'plugin/library/ui-select'], function(Utils, Select) {
// plugin
+var Image = Backbone.View.extend(
+{
+ // options
+ optionsDefault: {
+ url : ''
+ },
+
+ // initialize
+ initialize : function(options) {
+ // get options
+ this.options = Utils.merge(options, this.optionsDefault);
+
+ // create new element
+ this.setElement(this._template(this.options));
+ },
+
+ // template
+ _template: function(options) {
+ return '<img src="' + options.url + '"/>';
+ }
+});
+
+// plugin
var Label = Backbone.View.extend(
{
// options
optionsDefault: {
- title : ''
+ title : '',
+ cls : ''
},
// initialize
@@ -25,7 +49,7 @@
// template
_template: function(options) {
- return '<label><b>' + options.title + '</b></label>';
+ return '<label class="' + options.cls + '"><b>' + options.title + '</b></label>';
},
// value
@@ -108,39 +132,6 @@
});
// plugin
-var Icon = Backbone.View.extend(
-{
- // options
- optionsDefault: {
- float : 'right',
- icon : '',
- tooltip : '',
- placement : 'bottom',
- title : ''
- },
-
- // initialize
- initialize : function(options) {
- // get options
- this.options = Utils.merge(options, this.optionsDefault);
-
- // create new element
- this.setElement(this._template(this.options));
-
- // add tooltip
- $(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
- },
-
- // element
- _template: function(options) {
- return '<div>' +
- '<span class="fa ' + options.icon + '" style="font-size: 1.2em;"/> ' +
- options.title +
- '</div>';
- }
-});
-
-// plugin
var ButtonIcon = Backbone.View.extend(
{
// options
@@ -194,6 +185,39 @@
});
// plugin
+var Icon = Backbone.View.extend(
+{
+ // options
+ optionsDefault: {
+ float : 'right',
+ icon : '',
+ tooltip : '',
+ placement : 'bottom',
+ title : ''
+ },
+
+ // initialize
+ initialize : function(options) {
+ // get options
+ this.options = Utils.merge(options, this.optionsDefault);
+
+ // create new element
+ this.setElement(this._template(this.options));
+
+ // add tooltip
+ $(this.el).tooltip({title: options.tooltip, placement: 'bottom'});
+ },
+
+ // element
+ _template: function(options) {
+ return '<div>' +
+ '<span class="fa ' + options.icon + '" style="font-size: 1.2em;"/> ' +
+ options.title +
+ '</div>';
+ }
+});
+
+// plugin
var Anchor = Backbone.View.extend(
{
// options
@@ -552,6 +576,7 @@
// return
return {
Label : Label,
+ Image : Image,
Button : Button,
Icon : Icon,
ButtonIcon : ButtonIcon,
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/954789571b9d/
Changeset: 954789571b9d
User: jmchilton
Date: 2014-05-15 01:25:50
Summary: Bugfix: Small fix for running workflows with subcollection mapping steps.
Affected #: 1 file
diff -r 9a1415f8108f6283181c7a5b564118920359decc -r 954789571b9d7c2c2ea2d1651d50f13aefaced7e lib/galaxy/dataset_collections/structure.py
--- a/lib/galaxy/dataset_collections/structure.py
+++ b/lib/galaxy/dataset_collections/structure.py
@@ -42,7 +42,7 @@
if substructure.is_leaf:
yield dict_map( element, collection_dict )
else:
- sub_collections = dict_map( lambda collection: element( collection ).child_collection )
+ sub_collections = dict_map( lambda collection: element( collection ).child_collection, collection_dict )
for element in substructure._walk_collections( sub_collections ):
yield element
https://bitbucket.org/galaxy/galaxy-central/commits/31e5817ba7d3/
Changeset: 31e5817ba7d3
User: jmchilton
Date: 2014-05-15 01:25:50
Summary: Bugfix: Yet another bug fix for workflow extraction with collection operations.
Fail, fail, fail.
Affected #: 2 files
diff -r 954789571b9d7c2c2ea2d1651d50f13aefaced7e -r 31e5817ba7d36a039c432205b32958e190cbabbc lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -2864,6 +2864,13 @@
def dataset( self ):
return self.dataset_instance.dataset
+ def first_dataset_instance( self ):
+ element_object = self.element_object
+ if isinstance( element_object, DatasetCollection ):
+ return element_object.dataset_instances[ 0 ]
+ else:
+ return element_object
+
def copy_to_collection( self, collection ):
new_element = DatasetCollectionElement(
element=self.element_object,
diff -r 954789571b9d7c2c2ea2d1651d50f13aefaced7e -r 31e5817ba7d36a039c432205b32958e190cbabbc lib/galaxy/workflow/extract.py
--- a/lib/galaxy/workflow/extract.py
+++ b/lib/galaxy/workflow/extract.py
@@ -293,6 +293,8 @@
# HACK: Nested associations are not yet working, but we
# still need to clean them up so we can serialize
# if not( prefix ):
+ if isinstance( tmp, model.DatasetCollectionElement ):
+ tmp = tmp.first_dataset_instance()
if tmp: # this is false for a non-set optional dataset
if not isinstance(tmp, list):
associations.append( ( tmp.hid, prefix + key ) )
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
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9a1415f8108f/
Changeset: 9a1415f8108f
User: greg
Date: 2014-05-15 00:13:33
Summary: Enhance the galaxy API for the Tool Shed to retrieve the latest installable revision from the Tool Shed from an installed repository, specifying a name and owner. Enhance the ~/scripts/api/install_tool_shed_repositories.py script to allow the changeset_revision to be optional, and if not specified, the latest installable revision will be installed for the repository specified by the name and owner.
Affected #: 3 files
diff -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f -r 9a1415f8108f6283181c7a5b564118920359decc lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
--- a/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
+++ b/lib/galaxy/webapps/galaxy/api/tool_shed_repositories.py
@@ -66,6 +66,50 @@
exported_workflows.append( display_dict )
return exported_workflows
+ @web.expose_api
+ def get_latest_installable_revision( self, trans, payload, **kwd ):
+ """
+ POST /api/tool_shed_repositories/get_latest_installable_revision
+ Get the latest installable revision of a specified repository from a specified Tool Shed.
+
+ :param key: the current Galaxy admin user's API key
+
+ The following parameters are included in the payload.
+ :param tool_shed_url (required): the base URL of the Tool Shed from which to retrieve the Repository revision.
+ :param name (required): the name of the Repository
+ :param owner (required): the owner of the Repository
+ """
+ # Get the information about the repository to be installed from the payload.
+ tool_shed_url = payload.get( 'tool_shed_url', '' )
+ if not tool_shed_url:
+ raise HTTPBadRequest( detail="Missing required parameter 'tool_shed_url'." )
+ name = payload.get( 'name', '' )
+ if not name:
+ raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ owner = payload.get( 'owner', '' )
+ if not owner:
+ raise HTTPBadRequest( detail="Missing required parameter 'owner'." )
+ # Make sure the current user's API key proves he is an admin user in this Galaxy instance.
+ if not trans.user_is_admin():
+ raise HTTPForbidden( detail='You are not authorized to request the latest installable revision for a repository in this Galaxy instance.' )
+ params = '?name=%s&owner=%s' % ( name, owner )
+ url = common_util.url_join( tool_shed_url,
+ 'api/repositories/get_ordered_installable_revisions%s' % params )
+ try:
+ raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
+ except Exception, e:
+ message = "Error attempting to retrieve the latest installable revision from tool shed %s for repository %s owned by %s: %s" % \
+ ( str( tool_shed_url ), str( name ), str( owner ), str( e ) )
+ log.debug( message )
+ return dict( status='error', error=message )
+ if raw_text:
+ # If successful, the response from get_ordered_installable_revisions will be a list of
+ # changeset_revision hash strings.
+ changeset_revisions = json.from_json_string( raw_text )
+ if len( changeset_revisions ) >= 1:
+ return changeset_revisions[ -1 ]
+ return suc.INITIAL_CHANGELOG_HASH
+
def __get_value_mapper( self, trans, tool_shed_repository ):
value_mapper={ 'id' : trans.security.encode_id( tool_shed_repository.id ),
'error_message' : tool_shed_repository.error_message or '' }
diff -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f -r 9a1415f8108f6283181c7a5b564118920359decc lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -321,7 +321,8 @@
'exported_workflows' : 'GET',
'import_workflow' : 'POST',
'import_workflows' : 'POST' },
- collection={ 'reset_metadata_on_installed_repositories' : 'POST' },
+ collection={ 'get_latest_installable_revision' : 'POST',
+ 'reset_metadata_on_installed_repositories' : 'POST' },
controller='tool_shed_repositories',
name_prefix='tool_shed_repository_',
path_prefix='/api',
diff -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f -r 9a1415f8108f6283181c7a5b564118920359decc scripts/api/install_tool_shed_repositories.py
--- a/scripts/api/install_tool_shed_repositories.py
+++ b/scripts/api/install_tool_shed_repositories.py
@@ -1,8 +1,12 @@
#!/usr/bin/env python
"""
-Install a specified repository revision from a specified tool shed into Galaxy. This example demonstrates installation of a repository that contains
-valid tools, loading them into a section of the Galaxy tool panel or creating a new tool panel section.
-You can choose if tool dependencies or repository dependencies should be installed, use --repository-deps or --tool-deps.
+If a repository name, owner and revision are specified,install the revision from a specified tool shed into Galaxy.
+Specifying a revision is optional, if it is no specified, the latest installable revision will automatically be installed.
+However, the name and owner are required.
+
+This example demonstrates installation of a repository that contains valid tools, loading them into a section of the
+Galaxy tool panel or creating a new tool panel section. You can choose if tool dependencies or repository dependencies
+should be installed, use --repository-deps or --tool-deps.
This example requires a tool panel config file (e.g., tool_conf.xml, shed_tool_conf.xml, etc) to contain a tool panel section like the following:
@@ -10,7 +14,7 @@
</section>
Here is a working example of how to use this script to install a repository from the test tool shed.
-./install_tool_shed_repositories.py --api <api key> --local <galaxy base url> --url http://testtoolshed.g2.bx.psu.edu --name gregs_filter --owner greg --revision f28d5018f9cb --tool-deps
+./install_tool_shed_repositories.py --api <api key> --local <galaxy base url> --url http://testtoolshed.g2.bx.psu.edu --name gregs_filter --owner greg --tool-deps
"""
import os
@@ -25,7 +29,20 @@
data[ 'tool_shed_url' ] = options.tool_shed_url
data[ 'name' ] = options.name
data[ 'owner' ] = options.owner
- data[ 'changeset_revision' ] = options.changeset_revision
+ if options.changeset_revision:
+ data[ 'changeset_revision' ] = options.changeset_revision
+ else:
+ # If the changeset_revision is not specified, default to the latest installable revision.
+ revision_data = {}
+ revision_data[ 'tool_shed_url' ] = options.tool_shed_url.rstrip( '/' )
+ revision_data[ 'name' ] = options.name
+ revision_data[ 'owner' ] = options.owner
+ revision_url = '%s%s' % ( options.local_url.rstrip( '/' ), '/api/tool_shed_repositories/get_latest_installable_revision' )
+ latest_installable_revision = submit( options.api,
+ revision_url,
+ revision_data,
+ return_formatted=False )
+ data[ 'changeset_revision' ] = latest_installable_revision
if options.tool_panel_section_id:
data[ 'tool_panel_section_id' ] = options.tool_panel_section_id
elif options.new_tool_panel_section_label:
@@ -34,7 +51,7 @@
data[ 'install_repository_dependencies' ] = options.install_repository_dependencies
if options.install_tool_dependencies:
data[ 'install_tool_dependencies' ] = options.install_tool_dependencies
- submit( options.api, '%s%s' % ( options.local_url.strip( '/' ), '/api/tool_shed_repositories/new/install_repository_revision' ), data )
+ submit( options.api, '%s%s' % ( options.local_url.rstrip( '/' ), '/api/tool_shed_repositories/new/install_repository_revision' ), data )
if __name__ == '__main__':
parser = argparse.ArgumentParser( description='Installation of tool shed repositories via the Galaxy API.' )
@@ -43,7 +60,7 @@
parser.add_argument( "-l", "--local", dest="local_url", required=True, help="URL of the galaxy instance." )
parser.add_argument( "-n", "--name", required=True, help="Repository name." )
parser.add_argument( "-o", "--owner", required=True, help="Repository owner." )
- parser.add_argument( "-r", "--revision", dest="changeset_revision", required=True, help="Repository owner." )
+ parser.add_argument( "-r", "--revision", dest="changeset_revision", help="Repository revision." )
parser.add_argument( "--panel-section-id", dest="tool_panel_section_id", help="Tool panel section id if you want to add your repository to an existing tool section." )
parser.add_argument( "--panel-section-name", dest="new_tool_panel_section_label", help="New tool panel section label. If specified a new tool section will be created." )
parser.add_argument( "--repository-deps", dest="install_repository_dependencies", action="store_true", default=False, help="Install repository dependencies. [False]")
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Add a config option for controlling the AMQP consumer timeout, catch socket.error and attempt to recover from it.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/22ec0ac1ebcd/
Changeset: 22ec0ac1ebcd
User: natefoo
Date: 2014-05-14 23:34:15
Summary: Add a config option for controlling the AMQP consumer timeout, catch socket.error and attempt to recover from it.
Affected #: 4 files
diff -r a24a928c3b8c4e49bad89fb95496c6b1f78c23bc -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f job_conf.xml.sample_advanced
--- a/job_conf.xml.sample_advanced
+++ b/job_conf.xml.sample_advanced
@@ -51,6 +51,12 @@
<!-- <param id="amqp_connect_ssl_keyfile">/path/to/key.pem</param> --><!-- <param id="amqp_connect_ssl_certfile">/path/to/cert.pem</param> --><!-- <param id="amqp_connect_ssl_cert_reqs">cert_required</param> -->
+ <!-- By default, the AMQP consumer uses a nonblocking connection with
+ a 0.2 second timeout. In testing, this works fine for
+ unencrypted AMQP connections, but with SSL it will cause the
+ client to reconnect to the server after each timeout. Set to a
+ higher value (in seconds) (or `None` to use blocking connections). -->
+ <!-- <param id="amqp_consumer_timeout">None</param> --></plugin><plugin id="cli" type="runner" load="galaxy.jobs.runners.cli:ShellJobRunner" /><plugin id="condor" type="runner" load="galaxy.jobs.runners.condor:CondorJobRunner" />
diff -r a24a928c3b8c4e49bad89fb95496c6b1f78c23bc -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -47,10 +47,16 @@
self._init_monitor_thread()
self._init_worker_threads()
amqp_connect_ssl_args = {}
+ amqp_consumer_timeout = False
for kwd in kwds.keys():
if kwd.startswith('amqp_connect_ssl_'):
amqp_connect_ssl_args[kwd] = kwds[kwd]
client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url, 'amqp_connect_ssl_args': amqp_connect_ssl_args or None}
+ if 'amqp_consumer_timeout' in kwds:
+ if kwds['amqp_consumer_timeout'] == 'None':
+ client_manager_kwargs['amqp_consumer_timeout'] = None
+ else:
+ client_manager_kwargs['amqp_consumer_timeout'] = float(kwds['amqp_consumer_timeout'])
self.galaxy_url = galaxy_url
self.client_manager = build_client_manager(**client_manager_kwargs)
diff -r a24a928c3b8c4e49bad89fb95496c6b1f78c23bc -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
--- a/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
+++ b/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
@@ -6,6 +6,7 @@
import socket
import logging
+from time import sleep
log = logging.getLogger(__name__)
@@ -47,13 +48,18 @@
def consume(self, queue_name, callback, check=True, connection_kwargs={}):
queue = self.__queue(queue_name)
- with self.connection(self.__url, ssl=self.__connect_ssl, **connection_kwargs) as connection:
- with kombu.Consumer(connection, queues=[queue], callbacks=[callback], accept=['json']):
- while check:
- try:
- connection.drain_events(timeout=self.__timeout)
- except socket.timeout:
- pass
+ while check:
+ try:
+ with self.connection(self.__url, ssl=self.__connect_ssl, **connection_kwargs) as connection:
+ with kombu.Consumer(connection, queues=[queue], callbacks=[callback], accept=['json']):
+ while check and connection.connected:
+ try:
+ connection.drain_events(timeout=self.__timeout)
+ except socket.timeout:
+ pass
+ except socket.error, exc:
+ log.warning('Got socket.error, will retry: %s', exc)
+ sleep(1)
def publish(self, name, payload):
with self.connection(self.__url, ssl=self.__connect_ssl) as connection:
diff -r a24a928c3b8c4e49bad89fb95496c6b1f78c23bc -r 22ec0ac1ebcd1cc5ae5fda4ec70723043e8d5c5f lib/galaxy/jobs/runners/lwr_client/manager.py
--- a/lib/galaxy/jobs/runners/lwr_client/manager.py
+++ b/lib/galaxy/jobs/runners/lwr_client/manager.py
@@ -78,7 +78,11 @@
self.url = kwds.get('url')
self.manager_name = kwds.get("manager", "_default_")
self.connect_ssl = parse_amqp_connect_ssl_params(kwds.get('amqp_connect_ssl_args', None))
- self.exchange = LwrExchange(self.url, self.manager_name, self.connect_ssl)
+ timeout = kwds.get('amqp_consumer_timeout', False)
+ if timeout is False:
+ self.exchange = LwrExchange(self.url, self.manager_name, self.connect_ssl)
+ else:
+ self.exchange = LwrExchange(self.url, self.manager_name, self.connect_ssl, timeout=timeout)
self.status_cache = {}
self.callback_lock = threading.Lock()
self.callback_thread = None
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: dan: Fix for setting metadata when uploading directly to a library.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a24a928c3b8c/
Changeset: a24a928c3b8c
User: dan
Date: 2014-05-14 23:26:41
Summary: Fix for setting metadata when uploading directly to a library.
Affected #: 1 file
diff -r c9ad7f354f48f546e11879ba864b60c48d6d52f8 -r a24a928c3b8c4e49bad89fb95496c6b1f78c23bc lib/galaxy/jobs/__init__.py
--- a/lib/galaxy/jobs/__init__.py
+++ b/lib/galaxy/jobs/__init__.py
@@ -1309,7 +1309,7 @@
config_file = self.app.config.config_file
if datatypes_config is None:
datatypes_config = self.app.datatypes_registry.integrated_datatypes_configs
- return self.external_output_metadata.setup_external_metadata( [ output_dataset_assoc.dataset for output_dataset_assoc in job.output_datasets ],
+ return self.external_output_metadata.setup_external_metadata( [ output_dataset_assoc.dataset for output_dataset_assoc in job.output_datasets + job.output_library_datasets ],
self.sa_session,
exec_dir=exec_dir,
tmp_dir=tmp_dir,
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: jmchilton: Remove stray log statements in previous commit.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c9ad7f354f48/
Changeset: c9ad7f354f48
User: jmchilton
Date: 2014-05-14 23:13:32
Summary: Remove stray log statements in previous commit.
Affected #: 1 file
diff -r 170e2294712a2db7a703df8df62ace9a27fa1c9c -r c9ad7f354f48f546e11879ba864b60c48d6d52f8 lib/galaxy/workflow/extract.py
--- a/lib/galaxy/workflow/extract.py
+++ b/lib/galaxy/workflow/extract.py
@@ -99,8 +99,6 @@
raise AssertionError( "Attempt to create workflow with job not connected to current history" )
job = jobs_by_id[ job_id ]
tool_inputs, associations = step_inputs( trans, job )
- log.info("job %s has tool_inputs %s" % (job.id, tool_inputs) )
- log.info("associations are %s" % associations)
step = model.WorkflowStep()
step.type = 'tool'
step.tool_id = job.tool_id
@@ -114,7 +112,6 @@
input_collection = an_implicit_output_collection.find_implicit_input_collection( input_name )
if input_collection:
other_hid = input_collection.hid
- log.info("For input_name %s, have hid %s" % ( input_name, other_hid ) )
if other_hid in hid_to_output_pair:
other_step, other_name = hid_to_output_pair[ other_hid ]
conn = model.WorkflowStepConnection()
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: jmchilton: Bugfixes: More bug fixes for extracting collection-y workflows from a history.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/170e2294712a/
Changeset: 170e2294712a
User: jmchilton
Date: 2014-05-14 23:06:33
Summary: Bugfixes: More bug fixes for extracting collection-y workflows from a history.
The embarrassment continues...
Affected #: 1 file
diff -r c0eb8b472f3ccabdfd1b0396dbf92c34f3140200 -r 170e2294712a2db7a703df8df62ace9a27fa1c9c lib/galaxy/workflow/extract.py
--- a/lib/galaxy/workflow/extract.py
+++ b/lib/galaxy/workflow/extract.py
@@ -5,6 +5,7 @@
from galaxy import model
from galaxy.tools.parameters.basic import (
DataToolParameter,
+ DataCollectionToolParameter,
DrillDownSelectToolParameter,
SelectToolParameter,
UnvalidatedValue
@@ -98,6 +99,8 @@
raise AssertionError( "Attempt to create workflow with job not connected to current history" )
job = jobs_by_id[ job_id ]
tool_inputs, associations = step_inputs( trans, job )
+ log.info("job %s has tool_inputs %s" % (job.id, tool_inputs) )
+ log.info("associations are %s" % associations)
step = model.WorkflowStep()
step.type = 'tool'
step.tool_id = job.tool_id
@@ -111,6 +114,7 @@
input_collection = an_implicit_output_collection.find_implicit_input_collection( input_name )
if input_collection:
other_hid = input_collection.hid
+ log.info("For input_name %s, have hid %s" % ( input_name, other_hid ) )
if other_hid in hid_to_output_pair:
other_step, other_name = hid_to_output_pair[ other_hid ]
conn = model.WorkflowStepConnection()
@@ -190,7 +194,6 @@
# just grab the implicitly mapped jobs and handle in second pass. Second pass is
# needed because cannot allow selection of individual datasets from an implicit
# mapping during extraction - you get the collection or nothing.
- implicit_outputs = []
for content in self.history.active_contents:
if content.history_content_type == "dataset_collection":
hid = content.hid
@@ -200,34 +203,32 @@
job = DatasetCollectionCreationJob( content )
self.jobs[ job ] = [ ( None, content ) ]
else:
- implicit_outputs.append( content )
+ dataset_collection = content
+ # TODO: Optimize db call
+ # TODO: Ensure this is deterministic, must get same job
+ # for each dataset collection.
+ dataset_instance = dataset_collection.collection.dataset_instances[ 0 ]
+ if not self.__check_state( dataset_instance ):
+ # Just checking the state of one instance, don't need more but
+ # makes me wonder if even need this check at all?
+ continue
+
+ job_hda = self.__original_hda( dataset_instance )
+ if not job_hda.creating_job_associations:
+ log.warn( "An implicitly create output dataset collection doesn't have a creating_job_association, should not happen!" )
+ job = DatasetCollectionCreationJob( dataset_collection )
+ self.jobs[ job ] = [ ( None, dataset_collection ) ]
+
+ for assoc in job_hda.creating_job_associations:
+ job = assoc.job
+ if job not in self.jobs or self.jobs[ job ][ 0 ][ 1 ].history_content_type == "dataset":
+ self.jobs[ job ] = [ ( assoc.name, dataset_collection ) ]
+ self.implicit_map_jobs.append( job )
+ else:
+ self.jobs[ job ].append( ( assoc.name, dataset_collection ) )
else:
self.__append_dataset( content )
- for dataset_collection in implicit_outputs:
- # TODO: Optimize db call
- # TODO: Ensure this is deterministic, must get same job
- # for each dataset collection.
- dataset_instance = dataset_collection.collection.dataset_instances[ 0 ]
- if not self.__check_state( dataset_instance ):
- # Just checking the state of one instance, don't need more but
- # makes me wonder if even need this check at all?
- continue
-
- job_hda = self.__original_hda( dataset_instance )
- if not job_hda.creating_job_associations:
- log.warn( "An implicitly create output dataset collection doesn't have a creating_job_association, should not happen!" )
- job = DatasetCollectionCreationJob( dataset_collection )
- self.jobs[ job ] = [ ( None, dataset_collection ) ]
-
- for assoc in job_hda.creating_job_associations:
- job = assoc.job
- if job not in self.jobs or self.jobs[ job ][ 0 ][ 1 ].history_content_type == "dataset":
- self.jobs[ job ] = [ ( assoc.name, dataset_collection ) ]
- self.implicit_map_jobs.append( job )
- else:
- self.jobs[ job ].append( ( assoc.name, dataset_collection ) )
-
def __append_dataset( self, dataset ):
if not self.__check_state( dataset ):
return
@@ -289,7 +290,7 @@
if isinstance( input, ( SelectToolParameter, DrillDownSelectToolParameter ) ):
if input.is_dynamic and not isinstance( values[key], UnvalidatedValue ):
values[key] = UnvalidatedValue( values[key] )
- if isinstance( input, DataToolParameter ):
+ if isinstance( input, DataToolParameter ) or isinstance( input, DataCollectionToolParameter ):
tmp = values[key]
values[key] = None
# HACK: Nested associations are not yet working, but we
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Correctly handle the case where the AMQP SSL connection param parser gets params=None.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c0eb8b472f3c/
Changeset: c0eb8b472f3c
User: natefoo
Date: 2014-05-14 22:27:28
Summary: Correctly handle the case where the AMQP SSL connection param parser gets params=None.
Affected #: 1 file
diff -r b483d9df129c00480fc72253a277de18ab67b27d -r c0eb8b472f3ccabdfd1b0396dbf92c34f3140200 lib/galaxy/jobs/runners/lwr_client/util.py
--- a/lib/galaxy/jobs/runners/lwr_client/util.py
+++ b/lib/galaxy/jobs/runners/lwr_client/util.py
@@ -65,7 +65,9 @@
def parse_amqp_connect_ssl_params(params):
ssl = None
rval = None
- ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
+ ssl_options = []
+ if params:
+ ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
if ssl_options:
ssl = __import__('ssl')
rval = {}
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: Fix missing imports, add self.app in a few more places.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b483d9df129c/
Changeset: b483d9df129c
User: davebgx
Date: 2014-05-14 21:19:48
Summary: Fix missing imports, add self.app in a few more places.
Affected #: 1 file
diff -r c0832d30e315c24dcc2cf23918e4b0bd7b30ba56 -r b483d9df129c00480fc72253a277de18ab67b27d lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -19,6 +19,8 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import xml_util
+from tool_shed.galaxy_install.install_manager import InstallManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
from galaxy.util.odict import odict
log = logging.getLogger( __name__ )
@@ -497,12 +499,12 @@
tool_dependency,
error_message,
remove_installation_path=False )
- if tool_dependency and tool_dependency.status in [ app.install_model.ToolDependency.installation_status.INSTALLED,
- app.install_model.ToolDependency.installation_status.ERROR ]:
+ if tool_dependency and tool_dependency.status in [ self.app.install_model.ToolDependency.installation_status.INSTALLED,
+ self.app.install_model.ToolDependency.installation_status.ERROR ]:
installed_tool_dependencies.append( tool_dependency )
- if app.config.manage_dependency_relationships:
+ if self.app.config.manage_dependency_relationships:
# Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
- app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
+ self.app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status == self.app.install_model.ToolDependency.installation_status.ERROR:
print '\nThe ToolMigrationManager returned the following error while installing tool dependency ', installed_tool_dependency.name, ':'
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f95cf49907cc/
Changeset: f95cf49907cc
User: jmchilton
Date: 2014-05-14 21:08:03
Summary: Bugfix: Annotation, tags on collections update looking in old location.
Moved to collection instances instead of collections a little before PR opened.
Affected #: 1 file
diff -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 -r f95cf49907cca1c57a2fad9738e66c9aa5078fb9 lib/galaxy/dataset_collections/__init__.py
--- a/lib/galaxy/dataset_collections/__init__.py
+++ b/lib/galaxy/dataset_collections/__init__.py
@@ -138,10 +138,10 @@
changed = dataset_collection_instance.set_from_dict( new_data )
# the rest (often involving the trans) - do here
if 'annotation' in new_data.keys() and trans.get_user():
- dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance.collection, new_data[ 'annotation' ] )
+ dataset_collection_instance.add_item_annotation( trans.sa_session, trans.get_user(), dataset_collection_instance, new_data[ 'annotation' ] )
changed[ 'annotation' ] = new_data[ 'annotation' ]
if 'tags' in new_data.keys() and trans.get_user():
- self.set_tags_from_list( trans, dataset_collection_instance.collection, new_data[ 'tags' ], user=trans.user )
+ self.set_tags_from_list( trans, dataset_collection_instance, new_data[ 'tags' ], user=trans.user )
if changed.keys():
trans.sa_session.flush()
https://bitbucket.org/galaxy/galaxy-central/commits/c0832d30e315/
Changeset: c0832d30e315
User: jmchilton
Date: 2014-05-14 21:08:56
Summary: Merge.
Affected #: 1 file
diff -r f95cf49907cca1c57a2fad9738e66c9aa5078fb9 -r c0832d30e315c24dcc2cf23918e4b0bd7b30ba56 lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -470,7 +470,7 @@
if index is not None:
tool_dependency = tool_dependencies[ index ]
tool_dependency, proceed_with_install, action_elem_tuples = \
- tag_manager.process_tag_set( trans.app,
+ tag_manager.process_tag_set( self.app,
tool_shed_repository,
tool_dependency,
elem,
@@ -480,7 +480,7 @@
tool_dependency_db_records=tool_dependencies )
if proceed_with_install:
try:
- tool_dependency = install_manager.install_package( trans.app,
+ tool_dependency = install_manager.install_package( self.app,
elem,
tool_shed_repository,
tool_dependencies=tool_dependencies,
@@ -493,7 +493,7 @@
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: greg: Fix for tool migration manager to use self.app instead of trans.app.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a4699a3d7c2d/
Changeset: a4699a3d7c2d
User: greg
Date: 2014-05-14 21:07:30
Summary: Fix for tool migration manager to use self.app instead of trans.app.
Affected #: 1 file
diff -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 -r a4699a3d7c2de78ad5aa5ea9e79409e85050fa9f lib/tool_shed/galaxy_install/tool_migration_manager.py
--- a/lib/tool_shed/galaxy_install/tool_migration_manager.py
+++ b/lib/tool_shed/galaxy_install/tool_migration_manager.py
@@ -470,7 +470,7 @@
if index is not None:
tool_dependency = tool_dependencies[ index ]
tool_dependency, proceed_with_install, action_elem_tuples = \
- tag_manager.process_tag_set( trans.app,
+ tag_manager.process_tag_set( self.app,
tool_shed_repository,
tool_dependency,
elem,
@@ -480,7 +480,7 @@
tool_dependency_db_records=tool_dependencies )
if proceed_with_install:
try:
- tool_dependency = install_manager.install_package( trans.app,
+ tool_dependency = install_manager.install_package( self.app,
elem,
tool_shed_repository,
tool_dependencies=tool_dependencies,
@@ -493,7 +493,7 @@
# Since there was an installation error, update the tool dependency status to Error. The
# remove_installation_path option must be left False here.
tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency_util.handle_tool_dependency_installation_error( self.app,
tool_dependency,
error_message,
remove_installation_path=False )
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6fecbad49afd/
Changeset: 6fecbad49afd
User: greg
Date: 2014-05-14 20:55:31
Summary: Phase 2 of the tool dependency package installation framework rewrite: 1) rename the RecipeManager class to be the StepManager class and add a new TagManager class, both of which are contained in the recipe_manager.py module. 2) Add appropriate new classes for handling recipe tag sets to a new tag_handler.py module. Add a new InstallManager class with functions for installing tool dependencies. Eliminate the use of fabric_util.py and install_util.py.
Affected #: 18 files
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
--- a/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
+++ b/lib/galaxy/webapps/galaxy/controllers/admin_toolshed.py
@@ -23,8 +23,11 @@
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
from tool_shed.util import workflow_util
+from tool_shed.util import xml_util
from tool_shed.galaxy_install import repository_util
import tool_shed.galaxy_install.grids.admin_toolshed_grids as admin_toolshed_grids
+from tool_shed.galaxy_install.install_manager import InstallManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
import pkg_resources
eggs.require( 'mercurial' )
@@ -444,20 +447,74 @@
@web.expose
@web.require_admin
def initiate_tool_dependency_installation( self, trans, tool_dependencies, **kwd ):
- """Install specified dependencies for repository tools."""
+ """
+ Install specified dependencies for repository tools. The received list of tool_dependencies
+ are the database records for those dependencies defined in the tool_dependencies.xml file
+ (contained in the repository) that should be installed. This allows for filtering out dependencies
+ that have not been checked for installation on the 'Manage tool dependencies' page for an installed
+ tool shed repository.
+ """
# Get the tool_shed_repository from one of the tool_dependencies.
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
err_msg = ''
+ attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in tool_dependencies ]
tool_shed_repository = tool_dependencies[ 0 ].tool_shed_repository
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = suc.get_config_from_disk( suc.TOOL_DEPENDENCY_DEFINITION_FILENAME,
tool_shed_repository.repo_path( trans.app ) )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_dependencies,
- from_tool_migration_manager=False )
+ # Parse the tool_dependencies.xml config.
+ tree, error_message = xml_util.parse_xml( tool_dependencies_config )
+ installed_tool_dependencies = []
+ install_manager = InstallManager()
+ tag_manager = TagManager()
+ root = tree.getroot()
+ for elem in root:
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if package_name and package_version:
+ # elem is a package tag set.
+ attr_tup = ( package_name, package_version, 'package' )
+ try:
+ index = attr_tups_of_dependencies_for_install.index( attr_tup )
+ except Exception, e:
+ index = None
+ if index is not None:
+ tool_dependency = tool_dependencies[ index ]
+ tool_dependency, proceed_with_install, action_elem_tuples = \
+ tag_manager.process_tag_set( trans.app,
+ tool_shed_repository,
+ tool_dependency,
+ elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=False,
+ tool_dependency_db_records=tool_dependencies )
+ if proceed_with_install:
+ try:
+ tool_dependency = install_manager.install_package( trans.app,
+ elem,
+ tool_shed_repository,
+ tool_dependencies=tool_dependencies,
+ from_tool_migration_manager=False )
+ except Exception, e:
+ error_message = "Error installing tool dependency package %s version %s: %s" % \
+ ( str( package_name ), str( package_version ), str( e ) )
+ log.exception( error_message )
+ if tool_dependency:
+ # Since there was an installation error, update the tool dependency status to Error. The
+ # remove_installation_path option must be left False here.
+ tool_dependency = \
+ tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ if tool_dependency and tool_dependency.status in [ trans.app.install_model.ToolDependency.installation_status.INSTALLED,
+ trans.app.install_model.ToolDependency.installation_status.ERROR ]:
+ installed_tool_dependencies.append( tool_dependency )
+ if trans.app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ trans.app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status == trans.app.install_model.ToolDependency.installation_status.ERROR:
text = util.unicodify( installed_tool_dependency.error_message )
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py
--- a/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py
+++ b/lib/tool_shed/galaxy_install/grids/admin_toolshed_grids.py
@@ -185,8 +185,8 @@
operation='install latest revision' ) ),
grids.GridOperation( label="Install",
condition=( lambda item: \
- not item.deleted and \
- item.status == tool_shed_install.ToolShedRepository.installation_status.NEW ),
+ not item.deleted and \
+ item.status == tool_shed_install.ToolShedRepository.installation_status.NEW ),
allow_multiple=False,
url_args=dict( controller='admin_toolshed',
action='manage_repository',
@@ -196,7 +196,7 @@
not item.deleted and \
item.status not in \
[ tool_shed_install.ToolShedRepository.installation_status.ERROR,
- tool_shed_install.ToolShedRepository.installation_status.NEW ] ),
+ tool_shed_install.ToolShedRepository.installation_status.NEW ] ),
allow_multiple=False,
url_args=dict( controller='admin_toolshed',
action='browse_repositories',
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/install_manager.py
--- a/lib/tool_shed/galaxy_install/install_manager.py
+++ b/lib/tool_shed/galaxy_install/install_manager.py
@@ -1,8 +1,318 @@
import logging
import os
+from galaxy import eggs
+
+eggs.require( 'paramiko' )
+eggs.require( 'ssh' )
+eggs.require( 'Fabric' )
+
+from fabric.api import lcd
+
+from tool_shed.util import tool_dependency_util
+
+from tool_shed.galaxy_install.tool_dependencies import td_common_util
+from tool_shed.galaxy_install.tool_dependencies.recipe.env_file_builder import EnvFileBuilder
+from tool_shed.galaxy_install.tool_dependencies.recipe.install_environment import InstallEnvironment
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import StepManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
+
log = logging.getLogger( __name__ )
+INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environmnet',
+ 'setup_r_environmnet', 'setup_ruby_environmnet', 'shell_command' ]
+
class InstallManager( object ):
- pass
\ No newline at end of file
+
+ def get_tool_shed_repository_install_dir( self, app, tool_shed_repository ):
+ return os.path.abspath( tool_shed_repository.repo_files_directory( app ) )
+
+ def install_and_build_package( self, app, tool_shed_repository, tool_dependency, actions_dict ):
+ """Install a Galaxy tool dependency package either via a url or a mercurial or git clone command."""
+ tool_shed_repository_install_dir = self.get_tool_shed_repository_install_dir( app, tool_shed_repository )
+ install_dir = actions_dict[ 'install_dir' ]
+ package_name = actions_dict[ 'package_name' ]
+ actions = actions_dict.get( 'actions', None )
+ filtered_actions = []
+ env_file_builder = EnvFileBuilder( install_dir )
+ install_environment = InstallEnvironment( tool_shed_repository_install_dir=tool_shed_repository_install_dir,
+ install_dir=install_dir )
+ step_manager = StepManager()
+ if actions:
+ with install_environment.make_tmp_dir() as work_dir:
+ with lcd( work_dir ):
+ # The first action in the list of actions will be the one that defines the initial download process.
+ # There are currently three supported actions; download_binary, download_by_url and clone via a
+ # shell_command action type. The recipe steps will be filtered at this stage in the process, with
+ # the filtered actions being used in the next stage below. The installation directory (i.e., dir)
+ # is also defined in this stage and is used in the next stage below when defining current_dir.
+ action_type, action_dict = actions[ 0 ]
+ if action_type in INSTALL_ACTIONS:
+ # Some of the parameters passed here are needed only by a subset of the step handler classes,
+ # but to allow for a standard method signature we'll pass them along. We don't check the
+ # tool_dependency status in this stage because it should not have been changed based on a
+ # download.
+ tool_dependency, filtered_actions, dir = \
+ step_manager.execute_step( app=app,
+ tool_dependency=tool_dependency,
+ package_name=package_name,
+ actions=actions,
+ action_type=action_type,
+ action_dict=action_dict,
+ filtered_actions=filtered_actions,
+ env_file_builder=env_file_builder,
+ install_environment=install_environment,
+ work_dir=work_dir,
+ current_dir=None,
+ initial_download=True )
+ else:
+ # We're handling a complex repository dependency where we only have a set_environment tag set.
+ # <action type="set_environment">
+ # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
+ # </action>
+ filtered_actions = [ a for a in actions ]
+ dir = install_dir
+ # We're in stage 2 of the installation process. The package has been down-loaded, so we can
+ # now perform all of the actions defined for building it.
+ for action_tup in filtered_actions:
+ current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
+ with lcd( current_dir ):
+ action_type, action_dict = action_tup
+ tool_dependency, tmp_filtered_actions, tmp_dir = \
+ step_manager.execute_step( app=app,
+ tool_dependency=tool_dependency,
+ package_name=package_name,
+ actions=actions,
+ action_type=action_type,
+ action_dict=action_dict,
+ filtered_actions=filtered_actions,
+ env_file_builder=env_file_builder,
+ install_environment=install_environment,
+ work_dir=work_dir,
+ current_dir=current_dir,
+ initial_download=False )
+ if tool_dependency.status in [ app.install_model.ToolDependency.installation_status.ERROR ]:
+ # If the tool_dependency status is in an error state, return it with no additional
+ # processing.
+ return tool_dependency
+ # Make sure to handle the special case where the value of dir is reset (this happens when
+ # the action_type is change_directiory). In all other action types, dir will be returned as
+ # None.
+ if tmp_dir is not None:
+ dir = tmp_dir
+ return tool_dependency
+
+ def install_and_build_package_via_fabric( self, app, tool_shed_repository, tool_dependency, actions_dict ):
+ sa_session = app.install_model.context
+ try:
+ # There is currently only one fabric method.
+ tool_dependency = self.install_and_build_package( app, tool_shed_repository, tool_dependency, actions_dict )
+ except Exception, e:
+ log.exception( 'Error installing tool dependency %s version %s.', str( tool_dependency.name ), str( tool_dependency.version ) )
+ # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
+ # be left False here.
+ error_message = '%s\n%s' % ( td_common_util.format_traceback(), str( e ) )
+ tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ tool_dependency = tool_dependency_util.mark_tool_dependency_installed( app, tool_dependency )
+ return tool_dependency
+
+ def install_via_fabric( self, app, tool_shed_repository, tool_dependency, install_dir, package_name=None, custom_fabfile_path=None,
+ actions_elem=None, action_elem=None, **kwd ):
+ """
+ Parse a tool_dependency.xml file's <actions> tag set to gather information for installation using
+ self.install_and_build_package(). The use of fabric is being eliminated, so some of these functions
+ may need to be renamed at some point.
+ """
+ sa_session = app.install_model.context
+ if not os.path.exists( install_dir ):
+ os.makedirs( install_dir )
+ actions_dict = dict( install_dir=install_dir )
+ if package_name:
+ actions_dict[ 'package_name' ] = package_name
+ actions = []
+ is_binary_download = False
+ if actions_elem is not None:
+ elems = actions_elem
+ if elems.get( 'os' ) is not None and elems.get( 'architecture' ) is not None:
+ is_binary_download = True
+ elif action_elem is not None:
+ # We were provided with a single <action> element to perform certain actions after a platform-specific tarball was downloaded.
+ elems = [ action_elem ]
+ else:
+ elems = []
+ step_manager = StepManager()
+ tool_shed_repository_install_dir = self.get_tool_shed_repository_install_dir( app, tool_shed_repository )
+ install_environment = InstallEnvironment( tool_shed_repository_install_dir, install_dir )
+ for action_elem in elems:
+ # Make sure to skip all comments, since they are now included in the XML tree.
+ if action_elem.tag != 'action':
+ continue
+ action_dict = {}
+ action_type = action_elem.get( 'type', None )
+ if action_type is not None:
+ action_dict = step_manager.prepare_step( app=app,
+ tool_dependency=tool_dependency,
+ action_type=action_type,
+ action_elem=action_elem,
+ action_dict=action_dict,
+ install_environment=install_environment,
+ is_binary_download=is_binary_download )
+ action_tuple = ( action_type, action_dict )
+ if action_type == 'set_environment':
+ if action_tuple not in actions:
+ actions.append( action_tuple )
+ else:
+ actions.append( action_tuple )
+ if actions:
+ actions_dict[ 'actions' ] = actions
+ if custom_fabfile_path is not None:
+ # TODO: this is not yet supported or functional, but when it is handle it using the fabric api.
+ raise Exception( 'Tool dependency installation using proprietary fabric scripts is not yet supported.' )
+ else:
+ tool_dependency = self.install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict )
+ return tool_dependency
+
+ def install_package( self, app, elem, tool_shed_repository, tool_dependencies=None, from_tool_migration_manager=False ):
+ """
+ Install a tool dependency package defined by the XML element elem. The value of tool_dependencies is
+ a partial or full list of ToolDependency records associated with the tool_shed_repository.
+ """
+ tag_manager = TagManager()
+ sa_session = app.install_model.context
+ # The value of package_name should match the value of the "package" type in the tool config's
+ # <requirements> tag set, but it's not required.
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if tool_dependencies and package_name and package_version:
+ tool_dependency = None
+ for tool_dependency in tool_dependencies:
+ if package_name == str( tool_dependency.name ) and package_version == str( tool_dependency.version ):
+ break
+ if tool_dependency is not None:
+ for package_elem in elem:
+ tool_dependency, proceed_with_install, actions_elem_tuples = \
+ tag_manager.process_tag_set( app,
+ tool_shed_repository,
+ tool_dependency,
+ package_elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=from_tool_migration_manager,
+ tool_dependency_db_records=None )
+ if proceed_with_install and actions_elem_tuples:
+ # Get the installation directory for tool dependencies that will be installed for the received
+ # tool_shed_repository.
+ install_dir = \
+ tool_dependency_util.get_tool_dependency_install_dir( app=app,
+ repository_name=tool_shed_repository.name,
+ repository_owner=tool_shed_repository.owner,
+ repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
+ tool_dependency_type='package',
+ tool_dependency_name=package_name,
+ tool_dependency_version=package_version )
+ # At this point we have a list of <actions> elems that are either defined within an <actions_group>
+ # tag set with <actions> sub-elements that contains os and architecture attributes filtered by the
+ # platform into which the appropriate compiled binary will be installed, or not defined within an
+ # <actions_group> tag set and not filtered. Here is an example actions_elem_tuple.
+ # [(True, [<Element 'actions' at 0x109293d10>)]
+ binary_installed = False
+ for actions_elem_tuple in actions_elem_tuples:
+ in_actions_group, actions_elems = actions_elem_tuple
+ if in_actions_group:
+ # Platform matching is only performed inside <actions_group> tag sets, os and architecture
+ # attributes are otherwise ignored.
+ can_install_from_source = False
+ for actions_elem in actions_elems:
+ system = actions_elem.get( 'os' )
+ architecture = actions_elem.get( 'architecture' )
+ # If this <actions> element has the os and architecture attributes defined, then we only
+ # want to process until a successful installation is achieved.
+ if system and architecture:
+ # If an <actions> tag has been defined that matches our current platform, and the
+ # recipe specified within that <actions> tag has been successfully processed, skip
+ # any remaining platform-specific <actions> tags. We cannot break out of the loop
+ # here because there may be <action> tags at the end of the <actions_group> tag set
+ # that must be processed.
+ if binary_installed:
+ continue
+ # No platform-specific <actions> recipe has yet resulted in a successful installation.
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=actions_elem,
+ action_elem=None )
+ if tool_dependency.status == app.install_model.ToolDependency.installation_status.INSTALLED:
+ # If an <actions> tag was found that matches the current platform, and
+ # self.install_via_fabric() did not result in an error state, set binary_installed
+ # to True in order to skip any remaining platform-specific <actions> tags.
+ binary_installed = True
+ else:
+ # Process the next matching <actions> tag, or any defined <actions> tags that do not
+ # contain platform dependent recipes.
+ log.debug( 'Error downloading binary for tool dependency %s version %s: %s' % \
+ ( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
+ else:
+ if actions_elem.tag == 'actions':
+ # We've reached an <actions> tag that defines the recipe for installing and compiling from
+ # source. If binary installation failed, we proceed with the recipe.
+ if not binary_installed:
+ installation_directory = tool_dependency.installation_directory( app )
+ if os.path.exists( installation_directory ):
+ # Delete contents of installation directory if attempt at binary installation failed.
+ installation_directory_contents = os.listdir( installation_directory )
+ if installation_directory_contents:
+ removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
+ if removed:
+ can_install_from_source = True
+ else:
+ log.debug( 'Error removing old files from installation directory %s: %s' % \
+ ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
+ else:
+ can_install_from_source = True
+ else:
+ can_install_from_source = True
+ if can_install_from_source:
+ # We now know that binary installation was not successful, so proceed with the <actions>
+ # tag set that defines the recipe to install and compile from source.
+ log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % \
+ str( tool_dependency.name ) )
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=actions_elem,
+ action_elem=None )
+ if actions_elem.tag == 'action' and \
+ tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
+ # If the tool dependency is not in an error state, perform any final actions that have been
+ # defined within the actions_group tag set, but outside of an <actions> tag, which defines
+ # the recipe for installing and compiling from source.
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=None,
+ action_elem=actions_elem )
+ else:
+ # Checks for "os" and "architecture" attributes are not made for any <actions> tag sets outside of
+ # an <actions_group> tag set. If the attributes are defined, they will be ignored. All <actions> tags
+ # outside of an <actions_group> tag set will always be processed.
+ tool_dependency = self.install_via_fabric( app,
+ tool_shed_repository,
+ tool_dependency,
+ install_dir,
+ package_name=package_name,
+ actions_elem=actions_elems,
+ action_elem=None )
+ if tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
+ log.debug( 'Tool dependency %s version %s has been installed in %s.' % \
+ ( str( package_name ), str( package_version ), str( install_dir ) ) )
+ return tool_dependency
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 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
@@ -20,7 +20,10 @@
from tool_shed.util import metadata_util
from tool_shed.util import tool_dependency_util
from tool_shed.util import tool_util
-from xml.etree import ElementTree as XmlET
+from tool_shed.util import xml_util
+
+from tool_shed.galaxy_install.install_manager import InstallManager
+from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import TagManager
from galaxy import eggs
eggs.require( 'mercurial' )
@@ -621,11 +624,58 @@
trans.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', install_dir )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=tool_shed_repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=tool_shed_repository.tool_dependencies,
- from_tool_migration_manager=False )
+ # Parse the tool_dependencies.xml config.
+ tree, error_message = xml_util.parse_xml( tool_dependencies_config )
+ install_manager = InstallManager()
+ tag_manager = TagManager()
+ root = tree.getroot()
+ for elem in root:
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if package_name and package_version:
+ repository_tool_dependencies = util.listify( tool_shed_repository.tool_dependencies )
+ # elem is a package tag set.
+ attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in repository_tool_dependencies ]
+ attr_tup = ( package_name, package_version, 'package' )
+ try:
+ index = attr_tups_of_dependencies_for_install.index( attr_tup )
+ except Exception, e:
+ index = None
+ if index is not None:
+ tool_dependency = repository_tool_dependencies[ index ]
+ tool_dependency, proceed_with_install, action_elem_tuples = \
+ tag_manager.process_tag_set( trans.app,
+ tool_shed_repository,
+ tool_dependency,
+ elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=False,
+ tool_dependency_db_records=repository_tool_dependencies )
+ if proceed_with_install:
+ try:
+ tool_dependency = install_manager.install_package( trans.app,
+ elem,
+ tool_shed_repository,
+ tool_dependencies=repository_tool_dependencies,
+ from_tool_migration_manager=False )
+ except Exception, e:
+ error_message = "Error installing tool dependency package %s version %s: %s" % \
+ ( str( package_name ), str( package_version ), str( e ) )
+ log.exception( error_message )
+ if tool_dependency:
+ # Since there was an installation error, update the tool dependency status to Error. The
+ # remove_installation_path option must be left False here.
+ tool_dependency = \
+ tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ if tool_dependency and tool_dependency.status in [ trans.app.install_model.ToolDependency.installation_status.INSTALLED,
+ trans.app.install_model.ToolDependency.installation_status.ERROR ]:
+ if trans.app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ trans.app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
suc.remove_dir( work_dir )
suc.update_tool_shed_repository_status( trans.app,
tool_shed_repository,
@@ -877,11 +927,61 @@
trans.install_model.ToolShedRepository.installation_status.INSTALLING_TOOL_DEPENDENCIES )
# Get the tool_dependencies.xml file from the repository.
tool_dependencies_config = suc.get_config_from_disk( 'tool_dependencies.xml', repository.repo_path( trans.app ) )
- installed_tool_dependencies = common_install_util.handle_tool_dependencies( app=trans.app,
- tool_shed_repository=repository,
- tool_dependencies_config=tool_dependencies_config,
- tool_dependencies=repository.tool_dependencies,
- from_tool_migration_manager=False )
+ installed_tool_dependencies = []
+ # Parse the tool_dependencies.xml config.
+ tree, error_message = xml_util.parse_xml( tool_dependencies_config )
+ if tree is None:
+ return installed_tool_dependencies
+ install_manager = InstallManager()
+ tag_manager = TagManager()
+ root = tree.getroot()
+ for elem in root:
+ package_name = elem.get( 'name', None )
+ package_version = elem.get( 'version', None )
+ if package_name and package_version:
+ # elem is a package tag set.
+ attr_tups_of_dependencies_for_install = [ ( td.name, td.version, td.type ) for td in tool_dependencies ]
+ attr_tup = ( package_name, package_version, 'package' )
+ try:
+ index = attr_tups_of_dependencies_for_install.index( attr_tup )
+ except Exception, e:
+ index = None
+ if index is not None:
+ tool_dependency = tool_dependency_db_records[ index ]
+ tool_dependency, proceed_with_install, action_elem_tuples = \
+ tag_manager.process_tag_set( trans.app,
+ tool_shed_repository,
+ tool_dependency,
+ elem,
+ package_name,
+ package_version,
+ from_tool_migration_manager=False,
+ tool_dependency_db_records=tool_dependencies )
+ if proceed_with_install:
+ try:
+ tool_dependency = install_manager.install_package( trans.app,
+ elem,
+ tool_shed_repository,
+ tool_dependencies=tool_dependencies,
+ from_tool_migration_manager=False )
+ except Exception, e:
+ error_message = "Error installing tool dependency package %s version %s: %s" % \
+ ( str( package_name ), str( package_version ), str( e ) )
+ log.exception( error_message )
+ if tool_dependency:
+ # Since there was an installation error, update the tool dependency status to Error. The
+ # remove_installation_path option must be left False here.
+ tool_dependency = \
+ tool_dependency_util.handle_tool_dependency_installation_error( trans.app,
+ tool_dependency,
+ error_message,
+ remove_installation_path=False )
+ if tool_dependency and tool_dependency.status in [ app.install_model.ToolDependency.installation_status.INSTALLED,
+ app.install_model.ToolDependency.installation_status.ERROR ]:
+ installed_tool_dependencies.append( tool_dependency )
+ if app.config.manage_dependency_relationships:
+ # Add the tool_dependency to the in-memory dictionaries in the installed_repository_manager.
+ app.installed_repository_manager.handle_tool_dependency_install( tool_shed_repository, tool_dependency )
for installed_tool_dependency in installed_tool_dependencies:
if installed_tool_dependency.status in [ trans.install_model.ToolDependency.installation_status.ERROR ]:
repair_dict = add_repair_dict_entry( repository.name, installed_tool_dependency.error_message )
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ /dev/null
@@ -1,103 +0,0 @@
-import logging
-import os
-
-from galaxy import eggs
-
-eggs.require( 'paramiko' )
-eggs.require( 'ssh' )
-eggs.require( 'Fabric' )
-
-from fabric.api import env
-from fabric.api import lcd
-
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import EnvFileBuilder
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import InstallEnvironment
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import RecipeManager
-
-log = logging.getLogger( __name__ )
-
-INSTALL_ACTIONS = [ 'download_binary', 'download_by_url', 'download_file', 'setup_perl_environmnet',
- 'setup_r_environmnet', 'setup_ruby_environmnet', 'shell_command' ]
-
-def check_fabric_version():
- version = env.version
- if int( version.split( "." )[ 0 ] ) < 1:
- raise NotImplementedError( "Install Fabric version 1.0 or later." )
-
-def get_tool_shed_repository_install_dir( app, tool_shed_repository ):
- return os.path.abspath( tool_shed_repository.repo_files_directory( app ) )
-
-def install_and_build_package( app, tool_shed_repository, tool_dependency, actions_dict ):
- """Install a Galaxy tool dependency package either via a url or a mercurial or git clone command."""
- tool_shed_repository_install_dir = get_tool_shed_repository_install_dir( app, tool_shed_repository )
- install_dir = actions_dict[ 'install_dir' ]
- package_name = actions_dict[ 'package_name' ]
- actions = actions_dict.get( 'actions', None )
- filtered_actions = []
- env_file_builder = EnvFileBuilder( install_dir )
- install_environment = InstallEnvironment( tool_shed_repository_install_dir=tool_shed_repository_install_dir,
- install_dir=install_dir )
- recipe_manager = RecipeManager()
- if actions:
- with install_environment.make_tmp_dir() as work_dir:
- with lcd( work_dir ):
- # The first action in the list of actions will be the one that defines the initial download process.
- # There are currently three supported actions; download_binary, download_by_url and clone via a
- # shell_command action type. The recipe steps will be filtered at this stage in the process, with
- # the filtered actions being used in the next stage below. The installation directory (i.e., dir)
- # is also defined in this stage and is used in the next stage below when defining current_dir.
- action_type, action_dict = actions[ 0 ]
- if action_type in INSTALL_ACTIONS:
- # Some of the parameters passed here are needed only by a subset of the step handler classes,
- # but to allow for a standard method signature we'll pass them along. We don't check the
- # tool_dependency status in this stage because it should not have been changed based on a
- # download.
- tool_dependency, filtered_actions, dir = \
- recipe_manager.execute_step( app=app,
- tool_dependency=tool_dependency,
- package_name=package_name,
- actions=actions,
- action_type=action_type,
- action_dict=action_dict,
- filtered_actions=filtered_actions,
- env_file_builder=env_file_builder,
- install_environment=install_environment,
- work_dir=work_dir,
- current_dir=None,
- initial_download=True )
- else:
- # We're handling a complex repository dependency where we only have a set_environment tag set.
- # <action type="set_environment">
- # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR/bin</environment_variable>
- # </action>
- filtered_actions = [ a for a in actions ]
- dir = install_dir
- # We're in stage 2 of the installation process. The package has been down-loaded, so we can
- # now perform all of the actions defined for building it.
- for action_tup in filtered_actions:
- current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
- with lcd( current_dir ):
- action_type, action_dict = action_tup
- tool_dependency, tmp_filtered_actions, tmp_dir = \
- recipe_manager.execute_step( app=app,
- tool_dependency=tool_dependency,
- package_name=package_name,
- actions=actions,
- action_type=action_type,
- action_dict=action_dict,
- filtered_actions=filtered_actions,
- env_file_builder=env_file_builder,
- install_environment=install_environment,
- work_dir=work_dir,
- current_dir=current_dir,
- initial_download=False )
- if tool_dependency.status in [ app.install_model.ToolDependency.installation_status.ERROR ]:
- # If the tool_dependency status is in an error state, return it with no additional
- # processing.
- return tool_dependency
- # Make sure to handle the special case where the value of dir is reset (this happens when
- # the action_type is change_directiory). In all other action types, dir will be returned as
- # None.
- if tmp_dir is not None:
- dir = tmp_dir
- return tool_dependency
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ /dev/null
@@ -1,734 +0,0 @@
-import logging
-import os
-import shutil
-import stat
-import subprocess
-import sys
-import tempfile
-import fabric_util
-import td_common_util
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import EnvFileBuilder
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import InstallEnvironment
-from tool_shed.galaxy_install.tool_dependencies.recipe.recipe_manager import RecipeManager
-import tool_shed.util.shed_util_common as suc
-from tool_shed.util import common_util
-from tool_shed.util import encoding_util
-from tool_shed.util import tool_dependency_util
-from tool_shed.util import xml_util
-from tool_shed.galaxy_install.tool_dependencies import td_common_util
-from galaxy.model.orm import and_
-from galaxy.util import asbool
-from galaxy.util import listify
-
-log = logging.getLogger( __name__ )
-
-def create_temporary_tool_dependencies_config( app, tool_shed_url, name, owner, changeset_revision ):
- """Make a call to the tool shed to get the required repository's tool_dependencies.xml file."""
- tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
- params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
- url = common_util.url_join( tool_shed_url,
- 'repository/get_tool_dependencies_config_contents%s' % params )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
- if text:
- # Write the contents to a temporary file on disk so it can be reloaded and parsed.
- fh = tempfile.NamedTemporaryFile( 'wb', prefix="tmp-toolshed-cttdc" )
- tmp_filename = fh.name
- fh.close()
- fh = open( tmp_filename, 'wb' )
- fh.write( text )
- fh.close()
- return tmp_filename
- else:
- message = "Unable to retrieve required tool_dependencies.xml file from the tool shed for revision "
- message += "%s of installed repository %s owned by %s." % ( str( changeset_revision ), str( name ), str( owner ) )
- raise Exception( message )
- return None
-
-def create_tool_dependency_with_initialized_env_sh_file( app, dependent_install_dir, tool_shed_repository, required_repository, package_name,
- package_version, tool_dependencies_config ):
- """
- Create or get a tool_dependency record that is defined by the received package_name and package_version. An env.sh file will be
- created for the tool_dependency in the received dependent_install_dir.
- """
- #The received required_repository refers to a tool_shed_repository record that is defined as a complex repository dependency for this
- # tool_dependency. The required_repository may or may not be currently installed (it doesn't matter). If it is installed, it is
- # associated with a tool_dependency that has an env.sh file that this new tool_dependency must be able to locate and "source". If it
- # is not installed, we can still determine where that env.sh file will be, so we'll initialize this new tool_dependency's env.sh file
- # in either case. If the require repository end up with an installation error, this new tool dependency will still be fine because its
- # containing repository will be defined as missing dependencies.
- tool_dependencies = []
- if not os.path.exists( dependent_install_dir ):
- os.makedirs( dependent_install_dir )
- required_tool_dependency_env_file_path = None
- if tool_dependencies_config:
- required_td_tree, error_message = xml_util.parse_xml( tool_dependencies_config )
- if required_td_tree:
- required_td_root = required_td_tree.getroot()
- for required_td_elem in required_td_root:
- # Find the appropriate package name and version.
- if required_td_elem.tag == 'package':
- # <package name="bwa" version="0.5.9">
- required_td_package_name = required_td_elem.get( 'name', None )
- required_td_package_version = required_td_elem.get( 'version', None )
- # Check the database to see if we have a record for the required tool dependency (we may not which is ok). If we
- # find a record, we need to see if it is in an error state and if so handle it appropriately.
- required_tool_dependency = \
- tool_dependency_util.get_tool_dependency_by_name_version_type_repository( app,
- required_repository,
- required_td_package_name,
- required_td_package_version,
- 'package' )
- if required_td_package_name == package_name and required_td_package_version == package_version:
- # Get or create a database tool_dependency record with which the installed package on disk will be associated.
- tool_dependency = \
- tool_dependency_util.create_or_update_tool_dependency( app=app,
- tool_shed_repository=tool_shed_repository,
- name=package_name,
- version=package_version,
- type='package',
- status=app.install_model.ToolDependency.installation_status.NEVER_INSTALLED,
- set_status=True )
- # Create an env.sh file for the tool_dependency whose first line will source the env.sh file located in
- # the path defined by required_tool_dependency_env_file_path. It doesn't matter if the required env.sh
- # file currently exists..
- required_tool_dependency_env_file_path = \
- tool_dependency_util.get_required_repository_package_env_sh_path( app,
- package_name,
- package_version,
- required_repository )
- env_file_builder = EnvFileBuilder( tool_dependency.installation_directory( app ) )
- env_file_builder.append_line( action="source", value=required_tool_dependency_env_file_path )
- return_code = env_file_builder.return_code
- if return_code:
- error_message = 'Error defining env.sh file for package %s, return_code: %s' % \
- ( str( package_name ), str( return_code ) )
- tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- elif required_tool_dependency is not None and required_tool_dependency.in_error_state:
- error_message = "This tool dependency's required tool dependency %s version %s has status %s." % \
- ( str( required_tool_dependency.name ), str( required_tool_dependency.version ), str( required_tool_dependency.status ) )
- tool_dependency = \
- tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- else:
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=app.install_model.ToolDependency.installation_status.INSTALLED )
- tool_dependencies.append( tool_dependency )
- return tool_dependencies
-
-def get_absolute_path_to_file_in_repository( repo_files_dir, file_name ):
- """Return the absolute path to a specified disk file contained in a repository."""
- stripped_file_name = strip_path( file_name )
- file_path = None
- for root, dirs, files in os.walk( repo_files_dir ):
- if root.find( '.hg' ) < 0:
- for name in files:
- if name == stripped_file_name:
- return os.path.abspath( os.path.join( root, name ) )
- return file_path
-
-def get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app, tool_shed_url, name, owner, changeset_revision ):
- sa_session = app.install_model.context
- # The protocol is not stored, but the port is if it exists.
- tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed_url )
- tool_shed_repository = sa_session.query( app.install_model.ToolShedRepository ) \
- .filter( and_( app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
- app.install_model.ToolShedRepository.table.c.name == name,
- app.install_model.ToolShedRepository.table.c.owner == owner,
- app.install_model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
- .first()
- if tool_shed_repository:
- return tool_shed_repository
- # The tool_shed_repository must have been updated to a newer changeset revision than the one defined in the repository_dependencies.xml file,
- # so call the tool shed to get all appropriate newer changeset revisions.
- text = get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url, name, owner, changeset_revision )
- if text:
- changeset_revisions = listify( text )
- for changeset_revision in changeset_revisions:
- tool_shed_repository = sa_session.query( app.install_model.ToolShedRepository ) \
- .filter( and_( app.install_model.ToolShedRepository.table.c.tool_shed == tool_shed,
- app.install_model.ToolShedRepository.table.c.name == name,
- app.install_model.ToolShedRepository.table.c.owner == owner,
- app.install_model.ToolShedRepository.table.c.changeset_revision == changeset_revision ) ) \
- .first()
- if tool_shed_repository:
- return tool_shed_repository
- return None
-
-def get_updated_changeset_revisions_from_tool_shed( app, tool_shed_url, name, owner, changeset_revision ):
- """
- Get all appropriate newer changeset revisions for the repository defined by
- the received tool_shed_url / name / owner combination.
- """
- tool_shed_url = common_util.get_tool_shed_url_from_tool_shed_registry( app, tool_shed_url )
- params = '?name=%s&owner=%s&changeset_revision=%s' % ( name, owner, changeset_revision )
- url = common_util.url_join( tool_shed_url,
- 'repository/updated_changeset_revisions%s' % params )
- text = common_util.tool_shed_get( app, tool_shed_url, url )
- return text
-
-
-def handle_complex_repository_dependency_for_package( app, elem, package_name, package_version, tool_shed_repository, from_tool_migration_manager=False ):
- """
- Inspect the repository defined by a complex repository dependency definition and take certain steps to enable installation
- of the received package name and version to proceed. The received elem is the <repository> tag set which defines the complex
- repository dependency. The received tool_shed_repository is the installed tool shed repository for which the tool dependency
- defined by the received package_name and package_version is being installed.
- """
- handled_tool_dependencies = []
- tool_shed = elem.attrib[ 'toolshed' ]
- # The protocol is not stored, but the port is if it exists.
- tool_shed = common_util.remove_protocol_from_tool_shed_url( tool_shed )
- required_repository_name = elem.attrib[ 'name' ]
- required_repository_owner = elem.attrib[ 'owner' ]
- default_required_repository_changeset_revision = elem.attrib[ 'changeset_revision' ]
- required_repository = get_tool_shed_repository_by_tool_shed_name_owner_changeset_revision( app,
- tool_shed,
- required_repository_name,
- required_repository_owner,
- default_required_repository_changeset_revision )
- tmp_filename = None
- if required_repository:
- required_repository_changeset_revision = required_repository.installed_changeset_revision
- # Define the installation directory for the required tool dependency package in the required repository.
- required_repository_package_install_dir = \
- tool_dependency_util.get_tool_dependency_install_dir( app=app,
- repository_name=required_repository_name,
- repository_owner=required_repository_owner,
- repository_changeset_revision=required_repository_changeset_revision,
- tool_dependency_type='package',
- tool_dependency_name=package_name,
- tool_dependency_version=package_version )
- # Define this dependent repository's tool dependency installation directory that will contain the env.sh file with a path to the
- # required repository's installed tool dependency package.
- dependent_install_dir = \
- tool_dependency_util.get_tool_dependency_install_dir( app=app,
- repository_name=tool_shed_repository.name,
- repository_owner=tool_shed_repository.owner,
- repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dependency_type='package',
- 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 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_tool_migration_manager:
- can_install_tool_dependency = True
- else:
- # Notice that we'll throw away the following tool_dependency if it can be installed.
- tool_dependency, can_install_tool_dependency = \
- tool_dependency_util.sync_database_with_file_system( app,
- tool_shed_repository,
- package_name,
- package_version,
- dependent_install_dir,
- tool_dependency_type='package' )
- if not can_install_tool_dependency:
- log.debug( "Tool dependency %s version %s cannot be installed (it was probably previously installed), " % \
- ( str( tool_dependency.name, str( tool_dependency.version ) ) ) )
- log.debug( "so appending it to the list of handled tool dependencies." )
- handled_tool_dependencies.append( tool_dependency )
- else:
- can_install_tool_dependency = True
- if can_install_tool_dependency:
- # Set this dependent repository's tool dependency env.sh file with a path to the required repository's installed tool dependency package.
- # We can get everything we need from the discovered installed required_repository.
- if required_repository.is_deactivated_or_installed:
- if not os.path.exists( required_repository_package_install_dir ):
- print 'Missing required tool dependency directory %s' % str( required_repository_package_install_dir )
- repo_files_dir = required_repository.repo_files_directory( app )
- tool_dependencies_config = get_absolute_path_to_file_in_repository( repo_files_dir, 'tool_dependencies.xml' )
- if tool_dependencies_config:
- config_to_use = tool_dependencies_config
- else:
- message = "Unable to locate required tool_dependencies.xml file for revision %s of installed repository %s owned by %s." % \
- ( str( required_repository.changeset_revision ), str( required_repository.name ), str( required_repository.owner ) )
- raise Exception( message )
- else:
- # Make a call to the tool shed to get the changeset revision to which the current value of required_repository_changeset_revision
- # should be updated if it's not current.
- text = get_updated_changeset_revisions_from_tool_shed( app=app,
- tool_shed_url=tool_shed,
- name=required_repository_name,
- owner=required_repository_owner,
- changeset_revision=required_repository_changeset_revision )
- if text:
- updated_changeset_revisions = listify( text )
- # The list of changeset revisions is in reverse order, so the newest will be first.
- required_repository_changeset_revision = updated_changeset_revisions[ 0 ]
- # Make a call to the tool shed to get the required repository's tool_dependencies.xml file.
- tmp_filename = create_temporary_tool_dependencies_config( app,
- tool_shed,
- required_repository_name,
- required_repository_owner,
- required_repository_changeset_revision )
- config_to_use = tmp_filename
- handled_tool_dependencies = create_tool_dependency_with_initialized_env_sh_file( app=app,
- dependent_install_dir=dependent_install_dir,
- tool_shed_repository=tool_shed_repository,
- required_repository=required_repository,
- package_name=package_name,
- package_version=package_version,
- tool_dependencies_config=config_to_use )
- suc.remove_file( tmp_filename )
- else:
- message = "Unable to locate required tool shed repository named %s owned by %s with revision %s." % \
- ( str( required_repository_name ), str( required_repository_owner ), str( default_required_repository_changeset_revision ) )
- raise Exception( message )
- return handled_tool_dependencies
-
-def install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict ):
- sa_session = app.install_model.context
- try:
- # There is currently only one fabric method.
- tool_dependency = fabric_util.install_and_build_package( app, tool_shed_repository, tool_dependency, actions_dict )
- except Exception, e:
- log.exception( 'Error installing tool dependency %s version %s.', str( tool_dependency.name ), str( tool_dependency.version ) )
- # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
- # be left False here.
- error_message = '%s\n%s' % ( td_common_util.format_traceback(), str( e ) )
- tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- tool_dependency = tool_dependency_util.mark_tool_dependency_installed( app, tool_dependency )
- return tool_dependency
-
-def install_package( app, elem, tool_shed_repository, tool_dependencies=None, from_tool_migration_manager=False ):
- """
- Install a tool dependency package defined by the XML element elem. The value of tool_dependencies is
- a partial or full list of ToolDependency records associated with the tool_shed_repository.
- """
- sa_session = app.install_model.context
- tool_dependency = None
- # The value of package_name should match the value of the "package" type in the tool config's <requirements> tag set, but it's not required.
- package_name = elem.get( 'name', None )
- package_version = elem.get( 'version', None )
- if tool_dependencies and package_name and package_version:
- for package_elem in elem:
- if package_elem.tag == 'repository':
- # We have a complex repository dependency definition.
- rd_tool_dependencies = handle_complex_repository_dependency_for_package( app,
- package_elem,
- package_name,
- package_version,
- tool_shed_repository,
- from_tool_migration_manager=from_tool_migration_manager )
- for rd_tool_dependency in rd_tool_dependencies:
- if rd_tool_dependency.status == app.install_model.ToolDependency.installation_status.ERROR:
- # We'll log the error here, but continue installing packages since some may not require this dependency.
- print "Error installing tool dependency for required repository: %s" % str( rd_tool_dependency.error_message )
- elif package_elem.tag == 'install':
- # <install version="1.0">
- # Get the installation directory for tool dependencies that will be installed for the received tool_shed_repository.
- install_dir = tool_dependency_util.get_tool_dependency_install_dir( app=app,
- repository_name=tool_shed_repository.name,
- repository_owner=tool_shed_repository.owner,
- repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dependency_type='package',
- 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 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_tool_migration_manager:
- can_install_tool_dependency = True
- else:
- # Notice that we'll throw away the following tool_dependency if it can be installed.
- tool_dependency, can_install_tool_dependency = \
- tool_dependency_util.sync_database_with_file_system( app,
- tool_shed_repository,
- package_name,
- package_version,
- install_dir,
- tool_dependency_type='package' )
- if not can_install_tool_dependency:
- log.debug( "Tool dependency %s version %s cannot be installed (it was probably previously installed), so returning it." % \
- ( str( tool_dependency.name ), str( tool_dependency.version ) ) )
- return tool_dependency
- else:
- can_install_tool_dependency = True
- if can_install_tool_dependency:
- package_install_version = package_elem.get( 'version', '1.0' )
- status = app.install_model.ToolDependency.installation_status.INSTALLING
- tool_dependency = \
- tool_dependency_util.create_or_update_tool_dependency( app=app,
- tool_shed_repository=tool_shed_repository,
- name=package_name,
- version=package_version,
- type='package',
- status=status,
- set_status=True )
- # Get the information about the current platform in case the tool dependency definition includes tag sets
- # for installing compiled binaries.
- platform_info_dict = tool_dependency_util.get_platform_info_dict()
- if package_install_version == '1.0':
- # Handle tool dependency installation using a fabric method included in the Galaxy framework.
- actions_elem_tuples = td_common_util.parse_package_elem( package_elem,
- platform_info_dict=platform_info_dict,
- include_after_install_actions=True )
- if actions_elem_tuples:
- # At this point we have a list of <actions> elems that are either defined within an <actions_group>
- # tag set with <actions> sub-elements that contains os and architecture attributes filtered by the
- # platform into which the appropriate compiled binary will be installed, or not defined within an
- # <actions_group> tag set and not filtered. Here is an example actions_elem_tuple.
- # [(True, [<Element 'actions' at 0x109293d10>)]
- binary_installed = False
- for actions_elem_tuple in actions_elem_tuples:
- in_actions_group, actions_elems = actions_elem_tuple
- if in_actions_group:
- # Platform matching is only performed inside <actions_group> tag sets, os and architecture
- # attributes are otherwise ignored.
- can_install_from_source = False
- for actions_elem in actions_elems:
- system = actions_elem.get( 'os' )
- architecture = actions_elem.get( 'architecture' )
- # If this <actions> element has the os and architecture attributes defined, then we only
- # want to process until a successful installation is achieved.
- if system and architecture:
- # If an <actions> tag has been defined that matches our current platform, and the
- # recipe specified within that <actions> tag has been successfully processed, skip
- # any remaining platform-specific <actions> tags. We cannot break out of the loop
- # here because there may be <action> tags at the end of the <actions_group> tag set
- # that must be processed.
- if binary_installed:
- continue
- # No platform-specific <actions> recipe has yet resulted in a successful installation.
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=actions_elem,
- action_elem=None )
- if tool_dependency.status == app.install_model.ToolDependency.installation_status.INSTALLED:
- # If an <actions> tag was found that matches the current platform, and the
- # install_via_fabric method did not result in an error state, set binary_installed
- # to True in order to skip any remaining platform-specific <actions> tags.
- binary_installed = True
- else:
- # Process the next matching <actions> tag, or any defined <actions> tags that do not
- # contain platform dependent recipes.
- log.debug( 'Error downloading binary for tool dependency %s version %s: %s' % \
- ( str( package_name ), str( package_version ), str( tool_dependency.error_message ) ) )
- else:
- if actions_elem.tag == 'actions':
- # We've reached an <actions> tag that defines the recipe for installing and compiling from
- # source. If binary installation failed, we proceed with the recipe.
- if not binary_installed:
- installation_directory = tool_dependency.installation_directory( app )
- if os.path.exists( installation_directory ):
- # Delete contents of installation directory if attempt at binary installation failed.
- installation_directory_contents = os.listdir( installation_directory )
- if installation_directory_contents:
- removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
- if removed:
- can_install_from_source = True
- else:
- log.debug( 'Error removing old files from installation directory %s: %s' % \
- ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
- else:
- can_install_from_source = True
- else:
- can_install_from_source = True
- if can_install_from_source:
- # We now know that binary installation was not successful, so proceed with the <actions>
- # tag set that defines the recipe to install and compile from source.
- log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % \
- str( tool_dependency.name ) )
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=actions_elem,
- action_elem=None )
- if actions_elem.tag == 'action' and tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
- # If the tool dependency is not in an error state, perform any final actions that have been
- # defined within the actions_group tag set, but outside of an <actions> tag, which defines
- # the recipe for installing and compiling from source.
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=None,
- action_elem=actions_elem )
- else:
- # Checks for "os" and "architecture" attributes are not made for any <actions> tag sets outside of
- # an <actions_group> tag set. If the attributes are defined, they will be ignored. All <actions> tags
- # outside of an <actions_group> tag set will always be processed.
- tool_dependency = install_via_fabric( app,
- tool_shed_repository,
- tool_dependency,
- install_dir,
- package_name=package_name,
- actions_elem=actions_elems,
- action_elem=None )
- if tool_dependency.status != app.install_model.ToolDependency.installation_status.ERROR:
- log.debug( 'Tool dependency %s version %s has been installed in %s.' % \
- ( str( package_name ), str( package_version ), str( install_dir ) ) )
- else:
- error_message = 'Version %s of the %s package cannot be installed because ' % ( str( package_version ), str( package_name ) )
- error_message += 'the recipe for installing the package is missing either an <actions> tag set or an <actions_group> '
- error_message += 'tag set.'
- # Since there was an installation error, update the tool dependency status to Error. The remove_installation_path option must
- # be left False here.
- tool_dependency = tool_dependency_util.handle_tool_dependency_installation_error( app,
- tool_dependency,
- error_message,
- remove_installation_path=False )
- return tool_dependency
- else:
- raise NotImplementedError( 'Only install version 1.0 is currently supported (i.e., change your tag to be <install version="1.0">).' )
- elif package_elem.tag == 'readme':
- # Nothing to be done.
- continue
- #elif package_elem.tag == 'custom_fabfile':
- # # TODO: This is not yet supported or functionally correct...
- # # Handle tool dependency installation where the repository includes one or more custom fabric scripts.
- # if not fabric_version_checked:
- # check_fabric_version()
- # fabric_version_checked = True
- # fabfile_name = package_elem.get( 'name', None )
- # custom_fabfile_path = os.path.abspath( os.path.join( os.path.split( tool_dependencies_config )[ 0 ], fabfile_name ) )
- # print 'Installing tool dependencies via fabric script ', custom_fabfile_path
- return tool_dependency
-
-def install_via_fabric( app, tool_shed_repository, tool_dependency, install_dir, package_name=None, custom_fabfile_path=None,
- actions_elem=None, action_elem=None, **kwd ):
- """
- Parse a tool_dependency.xml file's <actions> tag set to gather information for installation using the
- fabric_util.install_and_build_package() method. The use of fabric is being eliminated, so some of these
- functions may need to be renamed at some point.
- """
- sa_session = app.install_model.context
- if not os.path.exists( install_dir ):
- os.makedirs( install_dir )
- actions_dict = dict( install_dir=install_dir )
- if package_name:
- actions_dict[ 'package_name' ] = package_name
- actions = []
- is_binary_download = False
- if actions_elem is not None:
- elems = actions_elem
- if elems.get( 'os' ) is not None and elems.get( 'architecture' ) is not None:
- is_binary_download = True
- elif action_elem is not None:
- # We were provided with a single <action> element to perform certain actions after a platform-specific tarball was downloaded.
- elems = [ action_elem ]
- else:
- elems = []
- recipe_manager = RecipeManager()
- tool_shed_repository_install_dir = fabric_util.get_tool_shed_repository_install_dir( app, tool_shed_repository )
- install_environment = InstallEnvironment( tool_shed_repository_install_dir, install_dir )
- for action_elem in elems:
- # Make sure to skip all comments, since they are now included in the XML tree.
- if action_elem.tag != 'action':
- continue
- action_dict = {}
- action_type = action_elem.get( 'type', None )
- if action_type is not None:
- action_dict = recipe_manager.prepare_step( app=app,
- tool_dependency=tool_dependency,
- action_type=action_type,
- action_elem=action_elem,
- action_dict=action_dict,
- install_environment=install_environment,
- is_binary_download=is_binary_download )
- action_tuple = ( action_type, action_dict )
- if action_type == 'set_environment':
- if action_tuple not in actions:
- actions.append( action_tuple )
- else:
- actions.append( action_tuple )
- if actions:
- actions_dict[ 'actions' ] = actions
- if custom_fabfile_path is not None:
- # TODO: this is not yet supported or functional, but when it is handle it using the fabric api.
- # execute_custom_fabric_script( app, elem, custom_fabfile_path, install_dir, package_name=package_name )
- raise Exception( 'Tool dependency installation using proprietary fabric scripts is not yet supported.' )
- else:
- tool_dependency = install_and_build_package_via_fabric( app, tool_shed_repository, tool_dependency, actions_dict )
- return tool_dependency
-
-def execute_custom_fabric_script( app, elem, custom_fabfile_path, install_dir, package_name=None, **kwd ):
- """
- TODO: Handle this using the fabric api.
- Parse a tool_dependency.xml file's fabfile <method> tag set to build the method parameters and execute the method.
- """
- if not os.path.exists( install_dir ):
- os.makedirs( install_dir )
- # Default value for env_dependency_path.
- env_dependency_path = install_dir
- method_name = elem.get( 'name', None )
- params_str = ''
- actions = []
- for param_elem in elem:
- param_name = param_elem.get( 'name' )
- if param_name:
- if param_name == 'actions':
- for action_elem in param_elem:
- actions.append( action_elem.text.replace( '$INSTALL_DIR', install_dir ) )
- if actions:
- params_str += 'actions=%s,' % encoding_util.tool_shed_encode( encoding_util.encoding_sep.join( actions ) )
- else:
- if param_elem.text:
- param_value = encoding_util.tool_shed_encode( param_elem.text )
- params_str += '%s=%s,' % ( param_name, param_value )
- if package_name:
- params_str += 'package_name=%s' % package_name
- else:
- params_str = params_str.rstrip( ',' )
- try:
- cmd = 'fab -f %s %s:%s' % ( custom_fabfile_path, method_name, params_str )
- returncode, message = run_subprocess( app, cmd )
- except Exception, e:
- return "Exception executing fabric script %s: %s. " % ( str( custom_fabfile_path ), str( e ) )
- if returncode:
- return message
- handle_environment_settings( app, tool_dependency, install_dir, cmd )
-
-def run_subprocess( app, cmd ):
- env = os.environ
- PYTHONPATH = env.get( 'PYTHONPATH', '' )
- if PYTHONPATH:
- env[ 'PYTHONPATH' ] = '%s:%s' % ( os.path.abspath( os.path.join( app.config.root, 'lib' ) ), PYTHONPATH )
- else:
- env[ 'PYTHONPATH' ] = os.path.abspath( os.path.join( app.config.root, 'lib' ) )
- message = ''
- tmp_name = tempfile.NamedTemporaryFile( prefix="tmp-toolshed-rs" ).name
- tmp_stderr = open( tmp_name, 'wb' )
- proc = subprocess.Popen( cmd, shell=True, env=env, stderr=tmp_stderr.fileno() )
- returncode = proc.wait()
- tmp_stderr.close()
- if returncode:
- tmp_stderr = open( tmp_name, 'rb' )
- message = '%s\n' % str( tmp_stderr.read() )
- tmp_stderr.close()
- suc.remove_file( tmp_name )
- return returncode, message
-
-def set_environment( app, elem, tool_shed_repository, attr_tups_of_dependencies_for_install ):
- """
- Create a ToolDependency to set an environment variable. This is different from the process used to
- set an environment variable that is associated with a package. An example entry in a tool_dependencies.xml
- file is::
-
- <set_environment version="1.0">
- <environment_variable name="R_SCRIPT_PATH" action="set_to">$REPOSITORY_INSTALL_DIR</environment_variable>
- </set_environment>
- """
- # TODO: Add support for a repository dependency definition within this tool dependency type's tag set. This should look something like
- # the following. See the implementation of support for this in the tool dependency package type's method above.
- # This function is only called for set environment actions as defined below, not within an <install version="1.0"> tool
- # dependency type. Here is an example of the tag set this function does handle:
- # <action type="set_environment">
- # <environment_variable name="PATH" action="prepend_to">$INSTALL_DIR</environment_variable>
- # </action>
- # Here is an example of the tag set this function does not handle:
- # <set_environment version="1.0">
- # <repository toolshed="<tool shed>" name="<repository name>" owner="<repository owner>" changeset_revision="<changeset revision>" />
- # </set_environment>
- sa_session = app.install_model.context
- tool_dependencies = []
- env_var_version = elem.get( 'version', '1.0' )
- tool_shed_repository_install_dir = fabric_util.get_tool_shed_repository_install_dir( app, tool_shed_repository )
- for env_var_elem in elem:
- # Althoug we're in a loop here, this method will always return only a single ToolDependency or None.
- env_var_name = env_var_elem.get( 'name', None )
- # The value of env_var_name must match the text value of at least 1 <requirement> tag in the tool config's <requirements> tag set whose
- # "type" attribute is "set_environment" (e.g., <requirement type="set_environment">R_SCRIPT_PATH</requirement>).
- env_var_action = env_var_elem.get( 'action', None )
- if env_var_name and env_var_action:
- # Tool dependencies of type "set_environmnet" always have the version attribute set to None.
- attr_tup = ( env_var_name, None, 'set_environment' )
- if attr_tup in attr_tups_of_dependencies_for_install:
- install_dir = \
- tool_dependency_util.get_tool_dependency_install_dir( app=app,
- repository_name=tool_shed_repository.name,
- repository_owner=tool_shed_repository.owner,
- repository_changeset_revision=tool_shed_repository.installed_changeset_revision,
- tool_dependency_type='set_environment',
- tool_dependency_name=env_var_name,
- tool_dependency_version=None )
- install_environment = InstallEnvironment( tool_shed_repository_install_dir=tool_shed_repository_install_dir,
- install_dir=install_dir )
- env_var_dict = td_common_util.create_env_var_dict( elem=env_var_elem,
- install_environment=install_environment )
- if env_var_dict:
- if not os.path.exists( install_dir ):
- os.makedirs( install_dir )
- status = app.install_model.ToolDependency.installation_status.INSTALLING
- tool_dependency = \
- tool_dependency_util.create_or_update_tool_dependency( app=app,
- tool_shed_repository=tool_shed_repository,
- name=env_var_name,
- version=None,
- type='set_environment',
- status=status,
- set_status=True )
- if env_var_version == '1.0':
- # Create this tool dependency's env.sh file.
- env_file_builder = EnvFileBuilder( install_dir )
- return_code = env_file_builder.append_line( make_executable=True, **env_var_dict )
- if return_code:
- error_message = 'Error creating env.sh file for tool dependency %s, return_code: %s' % \
- ( str( tool_dependency.name ), str( return_code ) )
- log.debug( error_message )
- status = app.install_model.ToolDependency.installation_status.ERROR
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=status,
- error_message=error_message,
- remove_from_disk=False )
- else:
- if tool_dependency.status not in [ app.install_model.ToolDependency.installation_status.ERROR,
- app.install_model.ToolDependency.installation_status.INSTALLED ]:
- status = app.install_model.ToolDependency.installation_status.INSTALLED
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=status,
- error_message=None,
- remove_from_disk=False )
- log.debug( 'Environment variable %s set in %s for tool dependency %s.' % \
- ( str( env_var_name ), str( install_dir ), str( tool_dependency.name ) ) )
- else:
- error_message = 'Only set_environment version 1.0 is currently supported (i.e., change your tag to be <set_environment version="1.0">).'
- status = app.install_model.ToolDependency.installation_status.ERROR
- tool_dependency = \
- tool_dependency_util.set_tool_dependency_attributes( app,
- tool_dependency=tool_dependency,
- status=status,
- error_message=error_message,
- remove_from_disk=False )
- tool_dependencies.append( tool_dependency )
- return tool_dependencies
-
-def strip_path( fpath ):
- if not fpath:
- return fpath
- try:
- file_path, file_name = os.path.split( fpath )
- except:
- file_name = fpath
- return file_name
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/recipe/asynchronous_reader.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/asynchronous_reader.py
@@ -0,0 +1,32 @@
+import logging
+import os
+import threading
+
+log = logging.getLogger( __name__ )
+
+
+class AsynchronousReader( threading.Thread ):
+ """
+ A helper class to implement asynchronous reading of a stream in a separate thread. Read lines are pushed
+ onto a queue to be consumed in another thread.
+ """
+
+ def __init__( self, fd, queue ):
+ threading.Thread.__init__( self )
+ self._fd = fd
+ self._queue = queue
+ self.lines = []
+
+ def run( self ):
+ """Read lines and put them on the queue."""
+ thread_lock = threading.Lock()
+ thread_lock.acquire()
+ for line in iter( self._fd.readline, '' ):
+ stripped_line = line.rstrip()
+ self.lines.append( stripped_line )
+ self._queue.put( stripped_line )
+ thread_lock.release()
+
+ def installation_complete( self ):
+ """Make sure there is more installation and compilation logging content expected."""
+ return not self.is_alive() and self._queue.empty()
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/env_file_builder.py
@@ -0,0 +1,95 @@
+import logging
+import os
+import stat
+
+log = logging.getLogger( __name__ )
+
+
+class EnvFileBuilder( object ):
+
+ def __init__( self, install_dir ):
+ self.install_dir = install_dir
+ self.return_code = 0
+
+ def append_line( self, make_executable=True, **kwd ):
+ env_var_dict = dict( **kwd )
+ env_entry, env_file = self.create_or_update_env_shell_file( self.install_dir, env_var_dict )
+ return_code = self.file_append( env_entry, env_file, make_executable=make_executable )
+ self.return_code = self.return_code or return_code
+ return self.return_code
+
+ @staticmethod
+ def create_or_update_env_shell_file( install_dir, env_var_dict ):
+ env_var_action = env_var_dict[ 'action' ]
+ env_var_value = env_var_dict[ 'value' ]
+ if env_var_action in [ 'prepend_to', 'set_to', 'append_to' ]:
+ env_var_name = env_var_dict[ 'name' ]
+ if env_var_action == 'prepend_to':
+ changed_value = '%s:$%s' % ( env_var_value, env_var_name )
+ elif env_var_action == 'set_to':
+ changed_value = '%s' % env_var_value
+ elif env_var_action == 'append_to':
+ changed_value = '$%s:%s' % ( env_var_name, env_var_value )
+ line = "%s=%s; export %s" % ( env_var_name, changed_value, env_var_name )
+ elif env_var_action == "source":
+ line = "if [ -f %s ] ; then . %s ; fi" % ( env_var_value, env_var_value )
+ else:
+ raise Exception( "Unknown shell file action %s" % env_var_action )
+ env_shell_file_path = os.path.join( install_dir, 'env.sh' )
+ return line, env_shell_file_path
+
+ def file_append( self, text, file_path, make_executable=True ):
+ """
+ Append a line to a file unless the line already exists in the file. This method creates the file if
+ it doesn't exist. If make_executable is True, the permissions on the file are set to executable by
+ the owner.
+ """
+ file_dir = os.path.dirname( file_path )
+ if not os.path.exists( file_dir ):
+ try:
+ os.makedirs( file_dir )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ if os.path.exists( file_path ):
+ try:
+ new_env_file_contents = []
+ env_file_contents = file( file_path, 'r' ).readlines()
+ # Clean out blank lines from the env.sh file.
+ for line in env_file_contents:
+ line = line.rstrip()
+ if line:
+ new_env_file_contents.append( line )
+ env_file_contents = new_env_file_contents
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ else:
+ env_file_handle = open( file_path, 'w' )
+ env_file_handle.close()
+ env_file_contents = []
+ if make_executable:
+ # Explicitly set the file's executable bits.
+ try:
+ os.chmod( file_path, int( '111', base=8 ) | os.stat( file_path )[ stat.ST_MODE ] )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ # Convert the received text to a list, in order to support adding one or more lines to the file.
+ if isinstance( text, basestring ):
+ text = [ text ]
+ for line in text:
+ line = line.rstrip()
+ if line and line not in env_file_contents:
+ env_file_contents.append( line )
+ try:
+ file( file_path, 'w' ).write( '\n'.join( env_file_contents ) )
+ except Exception, e:
+ log.exception( str( e ) )
+ return 1
+ return 0
+
+ def handle_action_shell_file_paths( self, action_dict ):
+ shell_file_paths = action_dict.get( 'action_shell_file_paths', [] )
+ for shell_file_path in shell_file_paths:
+ self.append_line( action="source", value=shell_file_path )
diff -r 23bb24573f1370b4f6322651d471d11ff5352447 -r 6fecbad49afd69beebb55fb8a9b83ecae29af723 lib/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py
--- /dev/null
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/recipe/install_environment.py
@@ -0,0 +1,273 @@
+import logging
+import os
+import Queue
+import shutil
+import subprocess
+import tempfile
+import threading
+import time
+from contextlib import contextmanager
+
+# TODO: eliminate the use of fabric here.
+from galaxy import eggs
+
+eggs.require( 'paramiko' )
+eggs.require( 'ssh' )
+eggs.require( 'Fabric' )
+
+from fabric.operations import _AttributeString
+from fabric import state
+from fabric.api import prefix
+
+from galaxy.util import DATABASE_MAX_STRING_SIZE
+from galaxy.util import DATABASE_MAX_STRING_SIZE_PRETTY
+from galaxy.util import shrink_string_by_size
+from galaxy.util import unicodify
+
+from tool_shed.galaxy_install.tool_dependencies import td_common_util
+from tool_shed.galaxy_install.tool_dependencies.recipe import asynchronous_reader
+
+log = logging.getLogger( __name__ )
+
+class InstallEnvironment( object ):
+ """Object describing the environment built up as part of the process of building and installing a package."""
+
+
+ def __init__( self, tool_shed_repository_install_dir, install_dir ):
+ """
+ The value of the received tool_shed_repository_install_dir is the root installation directory
+ of the repository containing the tool dependency, and the value of the received install_dir is
+ the root installation directory of the tool dependency.
+ """
+ self.env_shell_file_paths = []
+ self.install_dir = install_dir
+ self.tool_shed_repository_install_dir = tool_shed_repository_install_dir
+
+ def __call__( self ):
+ with settings( warn_only=True, **td_common_util.get_env_var_values( self ) ):
+ with prefix( self.__setup_environment() ):
+ yield
+
+ def add_env_shell_file_paths( self, paths ):
+ for path in paths:
+ self.env_shell_file_paths.append( str( path ) )
+
+ def build_command( self, command, action_type='shell_command' ):
+ """
+ Build command line for execution from simple command, but
+ configuring environment described by this object.
+ """
+ env_cmds = self.environment_commands( action_type )
+ return '\n'.join( env_cmds + [ command ] )
+
+ def close_file_descriptor( self, fd ):
+ """Attempt to close a file descriptor."""
+ start_timer = time.time()
+ error = ''
+ while True:
+ try:
+ fd.close()
+ break
+ except IOError, e:
+ # Undoubtedly close() was called during a concurrent operation on the same file object.
+ log.debug( 'Error closing file descriptor: %s' % str( e ) )
+ time.sleep( .5 )
+ current_wait_time = time.time() - start_timer
+ if current_wait_time >= 600:
+ error = 'Error closing file descriptor: %s' % str( e )
+ break
+ return error
+
+ def enqueue_output( self, stdout, stdout_queue, stderr, stderr_queue ):
+ """
+ This method places streamed stdout and stderr into a threaded IPC queue target. Received data
+ is printed and saved to that thread's queue. The calling thread can then retrieve the data using
+ thread.stdout and thread.stderr.
+ """
+ stdout_logger = logging.getLogger( 'install_environment.STDOUT' )
+ stderr_logger = logging.getLogger( 'install_environment.STDERR' )
+ for line in iter( stdout.readline, '' ):
+ output = line.rstrip()
+ stdout_logger.debug( output )
+ stdout_queue.put( output )
+ stdout_queue.put( None )
+ for line in iter( stderr.readline, '' ):
+ output = line.rstrip()
+ stderr_logger.debug( output )
+ stderr_queue.put( output )
+ stderr_queue.put( None )
+
+ def environment_commands( self, action_type ):
+ """Build a list of commands used to construct the environment described by this object."""
+ cmds = []
+ for env_shell_file_path in self.env_shell_file_paths:
+ if os.path.exists( env_shell_file_path ):
+ for env_setting in open( env_shell_file_path ):
+ cmds.append( env_setting.strip( '\n' ) )
+ else:
+ log.debug( 'Invalid file %s specified, ignoring %s action.' % ( str( env_shell_file_path ), str( action_type ) ) )
+ return cmds
+
+ def environment_dict( self, action_type='template_command' ):
+ env_vars = dict()
+ for env_shell_file_path in self.env_shell_file_paths:
+ if os.path.exists( env_shell_file_path ):
+ for env_setting in open( env_shell_file_path ):
+ env_string = env_setting.split( ';' )[ 0 ]
+ env_name, env_path = env_string.split( '=' )
+ env_vars[ env_name ] = env_path
+ else:
+ log.debug( 'Invalid file %s specified, ignoring template_command action.' % str( env_shell_file_path ) )
+ return env_vars
+
+ def handle_command( self, app, tool_dependency, cmd, return_output=False ):
+ """Handle a command and log the results."""
+ context = app.install_model.context
+ command = str( cmd )
+ output = self.handle_complex_command( command )
+ self.log_results( cmd, output, os.path.join( self.install_dir, td_common_util.INSTALLATION_LOG ) )
+ stdout = output.stdout
+ stderr = output.stderr
+ if len( stdout ) > DATABASE_MAX_STRING_SIZE:
+ print "Length of stdout > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY )
+ stdout = shrink_string_by_size( stdout, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True )
+ if len( stderr ) > DATABASE_MAX_STRING_SIZE:
+ print "Length of stderr > %s, so only a portion will be saved in the database." % str( DATABASE_MAX_STRING_SIZE_PRETTY )
+ stderr = shrink_string_by_size( stderr, DATABASE_MAX_STRING_SIZE, join_by="\n..\n", left_larger=True, beginning_on_size_error=True )
+ if output.return_code not in [ 0 ]:
+ tool_dependency.status = app.install_model.ToolDependency.installation_status.ERROR
+ if stderr:
+ tool_dependency.error_message = unicodify( stderr )
+ elif stdout:
+ tool_dependency.error_message = unicodify( stdout )
+ else:
+ # We have a problem if there was no stdout and no stderr.
+ tool_dependency.error_message = "Unknown error occurred executing shell command %s, return_code: %s" % \
+ ( str( cmd ), str( output.return_code ) )
+ context.add( tool_dependency )
+ context.flush()
+ if return_output:
+ return output
+ return output.return_code
+
+ def handle_complex_command( self, command ):
+ """
+ Wrap subprocess.Popen in such a way that the stderr and stdout from running a shell command will
+ be captured and logged in nearly real time. This is similar to fabric.local, but allows us to
+ retain control over the process. This method is named "complex" because it uses queues and
+ threads to execute a command while capturing and displaying the output.
+ """
+ # Launch the command as subprocess. A bufsize of 1 means line buffered.
+ process_handle = subprocess.Popen( str( command ),
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ bufsize=1,
+ close_fds=False,
+ shell=True,
+ cwd=state.env[ 'lcwd' ] )
+ pid = process_handle.pid
+ # Launch the asynchronous readers of the process' stdout and stderr.
+ stdout_queue = Queue.Queue()
+ stdout_reader = asynchronous_reader.AsynchronousReader( process_handle.stdout, stdout_queue )
+ stdout_reader.start()
+ stderr_queue = Queue.Queue()
+ stderr_reader = asynchronous_reader.AsynchronousReader( process_handle.stderr, stderr_queue )
+ stderr_reader.start()
+ # Place streamed stdout and stderr into a threaded IPC queue target so it can
+ # be printed and stored for later retrieval when generating the INSTALLATION.log.
+ stdio_thread = threading.Thread( target=self.enqueue_output,
+ args=( process_handle.stdout,
+ stdout_queue,
+ process_handle.stderr,
+ stderr_queue ) )
+ thread_lock = threading.Lock()
+ thread_lock.acquire()
+ stdio_thread.start()
+ # Check the queues for output until there is nothing more to get.
+ start_timer = time.time()
+ while not stdout_reader.installation_complete() or not stderr_reader.installation_complete():
+ # Show what we received from standard output.
+ while not stdout_queue.empty():
+ try:
+ line = stdout_queue.get()
+ except Queue.Empty:
+ line = None
+ break
+ if line:
+ print line
+ start_timer = time.time()
+ else:
+ break
+ # Show what we received from standard error.
+ while not stderr_queue.empty():
+ try:
+ line = stderr_queue.get()
+ except Queue.Empty:
+ line = None
+ break
+ if line:
+ print line
+ start_timer = time.time()
+ else:
+ stderr_queue.task_done()
+ break
+ # Sleep a bit before asking the readers again.
+ time.sleep( .1 )
+ current_wait_time = time.time() - start_timer
+ if stdout_queue.empty() and stderr_queue.empty() and current_wait_time > td_common_util.NO_OUTPUT_TIMEOUT:
+ err_msg = "\nShutting down process id %s because it generated no output for the defined timeout period of %.1f seconds.\n" % \
+ ( pid, td_common_util.NO_OUTPUT_TIMEOUT )
+ stderr_reader.lines.append( err_msg )
+ process_handle.kill()
+ break
+ thread_lock.release()
+ # Wait until each of the threads we've started terminate. The following calls will block each thread
+ # until it terminates either normally, through an unhandled exception, or until the timeout occurs.
+ stdio_thread.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ stdout_reader.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ stderr_reader.join( td_common_util.NO_OUTPUT_TIMEOUT )
+ # Close subprocess' file descriptors.
+ error = self.close_file_descriptor( process_handle.stdout )
+ error = self.close_file_descriptor( process_handle.stderr )
+ stdout = '\n'.join( stdout_reader.lines )
+ stderr = '\n'.join( stderr_reader.lines )
+ # Handle error condition (deal with stdout being None, too)
+ output = _AttributeString( stdout.strip() if stdout else "" )
+ errors = _AttributeString( stderr.strip() if stderr else "" )
+ # Make sure the process has finished.
+ process_handle.poll()
+ output.return_code = process_handle.returncode
+ output.stderr = errors
+ return output
+
+ def log_results( self, command, fabric_AttributeString, file_path ):
+ """Write attributes of fabric.operations._AttributeString to a specified log file."""
+ if os.path.exists( file_path ):
+ logfile = open( file_path, 'ab' )
+ else:
+ logfile = open( file_path, 'wb' )
+ logfile.write( "\n#############################################\n" )
+ logfile.write( '%s\nSTDOUT\n' % command )
+ logfile.write( str( fabric_AttributeString.stdout ) )
+ logfile.write( "\n#############################################\n" )
+ logfile.write( "\n#############################################\n" )
+ logfile.write( '%s\nSTDERR\n' % command )
+ logfile.write( str( fabric_AttributeString.stderr ) )
+ logfile.write( "\n#############################################\n" )
+ logfile.close()
+
+ @contextmanager
+ def make_tmp_dir( self ):
+ work_dir = tempfile.mkdtemp( prefix="tmp-toolshed-mtd" )
+ yield work_dir
+ if os.path.exists( work_dir ):
+ try:
+ shutil.rmtree( work_dir )
+ except Exception, e:
+ log.exception( str( e ) )
+
+ def __setup_environment( self ):
+ return "&&".join( [ ". %s" % file for file in self.__valid_env_shell_file_paths() ] )
+
+ def __valid_env_shell_file_paths( self ):
+ return [ file for file in self.env_shell_file_paths if os.path.exists( file ) ]
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: martenson: data libraries: first take on api for requesting roles(assigned and assignable) for permissions; do not use - needs to be tested on test
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/23bb24573f13/
Changeset: 23bb24573f13
User: martenson
Date: 2014-05-14 19:53:01
Summary: data libraries: first take on api for requesting roles(assigned and assignable) for permissions; do not use - needs to be tested on test
changes to UI, removed modal for dataset details, dissasembled into separate backbone view
Affected #: 20 files
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/security/__init__.py
--- a/lib/galaxy/security/__init__.py
+++ b/lib/galaxy/security/__init__.py
@@ -986,8 +986,8 @@
def dataset_is_private_to_user( self, trans, dataset ):
"""
- If the dataset object has exactly one access role and that is the
- current user's private role then we consider the dataset private.
+ If the LibraryDataset object has exactly one access role and that is
+ the current user's private role then we consider the dataset private.
"""
private_role = self.get_private_user_role( trans.user )
access_roles = dataset.library_dataset_dataset_association.get_access_roles( trans )
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -68,53 +68,39 @@
raise exceptions.InternalServerError( 'Error loading from the database.' )
current_user_roles = trans.get_current_user_roles()
- can_add_library_item = trans.user_is_admin() or trans.app.security_agent.can_add_library_item( current_user_roles, folder )
- if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ):
- if folder.parent_id is None:
- try:
- library = trans.sa_session.query( trans.app.model.Library ).filter( trans.app.model.Library.table.c.root_folder_id == decoded_folder_id ).one()
- except Exception:
- raise exceptions.InternalServerError( 'Error loading from the database.' )
- if trans.app.security_agent.library_is_unrestricted( library ):
- pass
- else:
- if trans.user:
- log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
- else:
- log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
- raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ # Special level of security on top of libraries.
+ if trans.app.security_agent.can_access_library( current_user_roles, folder.parent_library ):
+ pass
+ else:
+ if trans.user:
+ log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
else:
- if trans.user:
- log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
- else:
- log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
- raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ log.warning( "SECURITY: Anonymous user is trying to load restricted folder with ID of %s" % ( decoded_folder_id ) )
+ raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
- def build_path( folder ):
- """
- Search the path upwards recursively and load the whole route of
- names and ids for breadcrumb building purposes.
-
- :param folder: current folder for navigating up
- :param type: Galaxy LibraryFolder
-
- :returns: list consisting of full path to the library
- :type: list
- """
- path_to_root = []
- # We are almost in root
- if folder.parent_id is None:
- path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
- else:
- # We add the current folder and traverse up one folder.
- path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
- upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
- path_to_root.extend( build_path( upper_folder ) )
- return path_to_root
-
- # Return the reversed path so it starts with the library node.
- full_path = build_path( folder )[::-1]
+ # if not ( trans.user_is_admin() or trans.app.security_agent.can_access_library_item( current_user_roles, folder, trans.user ) ):
+ # log.debug('folder parent id: ' + str(folder.parent_id))
+ # if folder.parent_id is None:
+ # try:
+ # library = trans.sa_session.query( trans.app.model.Library ).filter( trans.app.model.Library.table.c.root_folder_id == decoded_folder_id ).one()
+ # except Exception:
+ # raise exceptions.InternalServerError( 'Error loading from the database.' )
+ # if trans.app.security_agent.library_is_unrestricted( library ):
+ # pass
+ # else:
+ # if trans.user:
+ # log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
+ # else:
+ # log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
+ # raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
+ # else:
+ # if trans.user:
+ # log.warning( "SECURITY: User (id: %s) without proper access rights is trying to load folder with ID of %s" % ( trans.user.id, decoded_folder_id ) )
+ # else:
+ # log.debug('PARENT ID IS NOT NONE')
+ # log.warning( "SECURITY: Anonymous user without proper access rights is trying to load folder with ID of %s" % ( decoded_folder_id ) )
+ # raise exceptions.ObjectNotFound( 'Folder with the id provided ( %s ) was not found' % str( folder_id ) )
folder_contents = []
update_time = ''
@@ -128,17 +114,42 @@
if content_item.api_type == 'folder':
encoded_id = 'F' + encoded_id
+ # Check whether user can modify current folder
+ can_modify = False
+ if trans.user_is_admin():
+ can_modify = True
+ elif trans.user:
+ can_modify = trans.app.security_agent.can_modify_library_item( current_user_roles, folder )
+ return_item.update( dict( can_modify=can_modify ) )
if content_item.api_type == 'file':
+ # Is the dataset public or private?
+ # When both are False the dataset is 'restricted'
+ is_private = False
+ is_unrestricted = False
+ if trans.app.security_agent.dataset_is_public( content_item.library_dataset_dataset_association.dataset ):
+ is_unrestricted = True
+ else:
+ is_unrestricted = False
+ if trans.user:
+ is_private = trans.app.security_agent.dataset_is_private_to_user( trans, content_item )
+
+ # Can user manage the permissions on the dataset?
+ can_manage = False
+ if trans.user_is_admin():
+ can_manage = True
+ elif trans.user:
+ can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, content_item.library_dataset_dataset_association.dataset )
+
+ nice_size = util.nice_size( int( content_item.library_dataset_dataset_association.get_size() ) )
+
library_dataset_dict = content_item.to_dict()
- library_dataset_dict[ 'is_unrestricted' ] = trans.app.security_agent.dataset_is_public( content_item.library_dataset_dataset_association.dataset )
- library_dataset_dict[ 'is_private' ] = trans.app.security_agent.dataset_is_private_to_user( trans, content_item )
-
return_item.update( dict( data_type=library_dataset_dict[ 'data_type' ],
- file_size=library_dataset_dict[ 'file_size' ],
date_uploaded=library_dataset_dict[ 'date_uploaded' ],
- is_unrestricted=library_dataset_dict[ 'is_unrestricted' ],
- is_private=library_dataset_dict[ 'is_private' ] ) )
+ is_unrestricted=is_unrestricted,
+ is_private=is_private,
+ can_manage=can_manage,
+ file_size=nice_size ) )
# For every item include the default meta-data
return_item.update( dict( id=encoded_id,
@@ -150,7 +161,42 @@
) )
folder_contents.append( return_item )
- return { 'metadata': { 'full_path': full_path, 'can_add_library_item': can_add_library_item, 'folder_name': folder.name }, 'folder_contents': folder_contents }
+ # Return the reversed path so it starts with the library node.
+ full_path = self.build_path( trans, folder )[ ::-1 ]
+
+ # Check whether user can add items to the current folder
+ can_add_library_item = trans.user_is_admin() or trans.app.security_agent.can_add_library_item( current_user_roles, folder )
+
+ # Check whether user can modify current folder
+ can_modify_folder = trans.app.security_agent.can_modify_library_item( current_user_roles, folder )
+
+ metadata = dict( full_path=full_path,
+ can_add_library_item=can_add_library_item,
+ can_modify_folder=can_modify_folder )
+ folder_container = dict( metadata=metadata, folder_contents=folder_contents )
+ return folder_container
+
+ def build_path( self, trans, folder ):
+ """
+ Search the path upwards recursively and load the whole route of
+ names and ids for breadcrumb building purposes.
+
+ :param folder: current folder for navigating up
+ :param type: Galaxy LibraryFolder
+
+ :returns: list consisting of full path to the library
+ :type: list
+ """
+ path_to_root = []
+ # We are almost in root
+ if folder.parent_id is None:
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ else:
+ # We add the current folder and traverse up one folder.
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
+ path_to_root.extend( self.build_path( trans, upper_folder ) )
+ return path_to_root
def _load_folder_contents( self, trans, folder, include_deleted ):
"""
@@ -291,14 +337,13 @@
:param encoded_folder_id: encoded id of Galaxy LibraryFolder
:type encoded_folder_id: encoded string
- :returns: last 16 chars of the encoded id in case it was Folder
- (had 'F' prepended)
+ :returns: encoded id of Folder (had 'F' prepended)
:type: string
:raises: MalformedId
"""
- if ( len( encoded_folder_id ) == 17 and encoded_folder_id.startswith( 'F' )):
- return encoded_folder_id[1:]
+ if ( ( len( encoded_folder_id ) % 16 == 1 ) and encoded_folder_id.startswith( 'F' ) ):
+ return encoded_folder_id[ 1: ]
else:
raise exceptions.MalformedId( 'Malformed folder id ( %s ) specified, unable to decode.' % str( encoded_folder_id ) )
@@ -307,11 +352,11 @@
"""
GET /api/folders/{encoded_folder_id}/
"""
- raise exceptions.NotImplemented( 'Showing the library folder content is not implemented.' )
+ raise exceptions.NotImplemented( 'Showing the library folder content is not implemented here.' )
@web.expose_api
def update( self, trans, id, library_id, payload, **kwd ):
"""
PUT /api/folders/{encoded_folder_id}/contents
"""
- raise exceptions.NotImplemented( 'Updating the library folder content is not implemented.' )
+ raise exceptions.NotImplemented( 'Updating the library folder content is not implemented here.' )
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/webapps/galaxy/api/lda_datasets.py
--- a/lib/galaxy/webapps/galaxy/api/lda_datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/lda_datasets.py
@@ -47,12 +47,68 @@
dataset = self.get_library_dataset( trans, id=id, check_ownership=False, check_accessible=True )
except Exception:
raise exceptions.ObjectNotFound( 'Requested dataset was not found.' )
+
+ # Build the full path for breadcrumb purposes.
+ full_path = self._build_path( trans, dataset.folder )
+ dataset_item = ( trans.security.encode_id( dataset.id ), dataset.name )
+ full_path.insert(0, dataset_item)
+ full_path = full_path[ ::-1 ]
+
+ nice_size = util.nice_size( int( dataset.library_dataset_dataset_association.get_size() ) )
+
+ date_uploaded = dataset.library_dataset_dataset_association.create_time.strftime( "%Y-%m-%d %I:%M %p" )
+
rval = trans.security.encode_all_ids( dataset.to_dict() )
rval[ 'deleted' ] = dataset.deleted
rval[ 'folder_id' ] = 'F' + rval[ 'folder_id' ]
+ rval[ 'full_path' ] = full_path
+ rval[ 'file_size' ] = nice_size
+ rval[ 'date_uploaded' ] = date_uploaded
return rval
@expose_api
+ def show_roles( self, trans, encoded_dataset_id, **kwd ):
+ """
+ show_roles( self, trans, id, **kwd ):
+ GET /api/libraries/datasets/{encoded_dataset_id}/permissions:
+ Displays information about current and available roles
+ for a given dataset permission.
+ """
+ current_user_roles = trans.get_current_user_roles()
+ page = int( kwd.get( 'page', None ) )
+ page_limit = int( kwd.get( 'page_limit', None ) )
+ query = kwd.get ( 'q', None )
+
+ if page is None:
+ page = 1
+
+ if page_limit is None:
+ page_limit = 10
+
+ try:
+ library_dataset = self.get_library_dataset( trans, id=encoded_dataset_id, check_ownership=False, check_accessible=False )
+ except Exception, e:
+ raise exceptions.ObjectNotFound( 'Requested dataset was not found.' + str(e) )
+ library = library_dataset.folder.parent_library
+ dataset = library_dataset.library_dataset_dataset_association.dataset
+
+ can_manage = trans.app.security_agent.can_manage_dataset( current_user_roles, dataset ) or trans.user_is_admin()
+ if not can_manage:
+ raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to access permissions.' )
+
+ cntrller = 'standard_user'
+ if trans.user_is_admin():
+ cntrller = 'library_admin'
+
+ roles = trans.app.security_agent.get_legitimate_roles( trans, library, cntrller )
+ total_roles = len( roles )
+ return_roles = []
+ for role in roles:
+ return_roles.append( dict( id=role.name, name=role.name, type=role.type ) )
+
+ return dict( roles=return_roles, page=page, page_limit=page_limit, total=total_roles )
+
+ @expose_api
def delete( self, trans, encoded_dataset_id, **kwd ):
"""
delete( self, trans, encoded_dataset_id, **kwd ):
@@ -107,7 +163,9 @@
:raises: MessageException, ItemDeletionException, ItemAccessibilityException, HTTPBadRequest, OSError, IOError, ObjectNotFound
"""
lddas = []
- datasets_to_download = kwd[ 'ldda_ids%5B%5D' ]
+ datasets_to_download = kwd.get( 'ldda_ids%5B%5D', None )
+ if datasets_to_download is None:
+ datasets_to_download = kwd.get( 'ldda_ids', None )
if ( datasets_to_download is not None ):
datasets_to_download = util.listify( datasets_to_download )
@@ -121,6 +179,8 @@
raise exceptions.InternalServerError( 'Internal error. ' + str( e.err_msg ) )
except Exception, e:
raise exceptions.InternalServerError( 'Unknown error. ' + str( e ) )
+ else:
+ raise exceptions.RequestParameterMissingException( 'Request has to contain a list of dataset ids to download.' )
if format in [ 'zip', 'tgz', 'tbz' ]:
# error = False
@@ -262,3 +322,25 @@
raise exceptions.InternalServerError( "This dataset contains no content." )
else:
raise exceptions.RequestParameterInvalidException( "Wrong format parameter specified" )
+
+ def _build_path( self, trans, folder ):
+ """
+ Search the path upwards recursively and load the whole route of
+ names and ids for breadcrumb building purposes.
+
+ :param folder: current folder for navigating up
+ :param type: Galaxy LibraryFolder
+
+ :returns: list consisting of full path to the library
+ :type: list
+ """
+ path_to_root = []
+ # We are almost in root
+ if folder.parent_id is None:
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ else:
+ # We add the current folder and traverse up one folder.
+ path_to_root.append( ( 'F' + trans.security.encode_id( folder.id ), folder.name ) )
+ upper_folder = trans.sa_session.query( trans.app.model.LibraryFolder ).get( folder.parent_id )
+ path_to_root.extend( self._build_path( trans, upper_folder ) )
+ return path_to_root
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -218,6 +218,12 @@
action='show',
conditions=dict( method=[ "GET" ] ) )
+ webapp.mapper.connect( 'show_legitimate_lda_roles',
+ '/api/libraries/datasets/:encoded_dataset_id/permissions',
+ controller='lda_datasets',
+ action='show_roles',
+ conditions=dict( method=[ "GET" ] ) )
+
webapp.mapper.connect( 'delete_lda_item',
'/api/libraries/datasets/:encoded_dataset_id',
controller='lda_datasets',
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -11,7 +11,8 @@
"mvc/library/library-folderlist-view",
"mvc/library/library-librarylist-view",
"mvc/library/library-librarytoolbar-view",
- "mvc/library/library-foldertoolbar-view"
+ "mvc/library/library-foldertoolbar-view",
+ "mvc/library/library-dataset-view"
],
function(mod_masthead,
mod_utils,
@@ -21,7 +22,8 @@
mod_folderlist_view,
mod_librarylist_view,
mod_librarytoolbar_view,
- mod_foldertoolbar_view
+ mod_foldertoolbar_view,
+ mod_library_dataset_view
) {
// ============================================================================
@@ -34,10 +36,11 @@
},
routes: {
- "" : "libraries",
- "folders/:id" : "folder_content",
- "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
- "folders/:folder_id/download/:format" : "download"
+ "" : "libraries",
+ "folders/:id" : "folder_content",
+ "folders/:folder_id/datasets/:dataset_id" : "dataset_detail",
+ "folders/:folder_id/datasets/:dataset_id/permissions" : "dataset_permissions",
+ "folders/:folder_id/download/:format" : "download"
},
back: function() {
@@ -80,14 +83,11 @@
this.library_router = new LibraryRouter();
this.library_router.on('route:libraries', function() {
- // initialize and render the toolbar first
Galaxy.libraries.libraryToolbarView = new mod_librarytoolbar_view.LibraryToolbarView();
- // initialize and render libraries second
Galaxy.libraries.libraryListView = new mod_librarylist_view.LibraryListView();
});
this.library_router.on('route:folder_content', function(id) {
- // TODO maybe caching somewhere here, sessionstorage/localstorage?
if (Galaxy.libraries.folderToolbarView){
Galaxy.libraries.folderToolbarView.$el.unbind('click');
}
@@ -106,12 +106,10 @@
});
this.library_router.on('route:dataset_detail', function(folder_id, dataset_id){
- // if (Galaxy.libraries.folderToolbarView){
- // Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id, dataset_id: dataset_id});
- // } else {
- Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: folder_id});
- Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: folder_id, dataset_id: dataset_id});
- // }
+ new mod_library_dataset_view.LibraryDatasetView({id: dataset_id})
+ });
+ this.library_router.on('route:dataset_permissions', function(folder_id, dataset_id){
+ new mod_library_dataset_view.LibraryDatasetView({id: dataset_id, show_permissions: true})
});
Backbone.history.start({pushState: false});
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/mvc/library/library-dataset-view.js
--- /dev/null
+++ b/static/scripts/mvc/library/library-dataset-view.js
@@ -0,0 +1,556 @@
+define([
+ "libs/toastr",
+ "mvc/library/library-model",
+ 'mvc/ui/ui-select'
+ ],
+function(mod_toastr,
+ mod_library_model,
+ mod_select
+ ) {
+
+var LibraryDatasetView = Backbone.View.extend({
+ el: '#center',
+
+ model: null,
+
+ options: {
+
+ },
+
+ events: {
+ "click .toolbtn_modify_dataset" : "enableModification",
+ "click .toolbtn_cancel_modifications" : "render",
+ "click .toolbtn_change_permissions" : "showPermissions",
+ "click .toolbtn-download-dataset" : "downloadDataset",
+ "click .toolbtn-import-dataset" : "importIntoHistory",
+ "click .toolbtn-share-dataset" : "shareDataset"
+
+ },
+
+ initialize: function(options){
+ this.options = _.extend(this.options, options);
+ if (this.options.id){
+ this.fetchDataset();
+ }
+ },
+
+ fetchDataset: function(options){
+ this.options = _.extend(this.options, options);
+ this.model = new mod_library_model.Item({id:this.options.id});
+ var that = this;
+ this.model.fetch({
+ success: function() {
+ if (that.options.show_permissions){
+ that.showPermissions();
+ } else {
+ that.render();
+ }
+ },
+ error: function(model, response){
+ if (typeof response.responseJSON !== "undefined"){
+ mod_toastr.error(response.responseJSON.err_msg + ' Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
+ } else {
+ mod_toastr.error('An error ocurred :(. Click this to go back.', '', {onclick: function() {Galaxy.libraries.library_router.back();}});
+ }
+ }
+ });
+ },
+
+ render: function(options){
+ $(".tooltip").remove();
+ this.options = _.extend(this.options, options);
+ var template = this.templateDataset();
+ this.$el.html(template({item: this.model}));
+ $(".peek").html(this.model.get("peek"));
+ $("#center [data-toggle]").tooltip();
+ },
+
+ enableModification: function(){
+ $(".tooltip").remove();
+ var template = this.templateModifyDataset();
+ this.$el.html(template({item: this.model}));
+ $(".peek").html(this.model.get("peek"));
+ $("#center [data-toggle]").tooltip();
+ },
+
+ downloadDataset: function(){
+ var url = '/api/libraries/datasets/download/uncompressed';
+ var data = {'ldda_ids' : this.id};
+ this.processDownload(url, data);
+ },
+
+ processDownload: function(url, data, method){
+ //url and data options required
+ if( url && data ){
+ //data can be string of parameters or array/object
+ data = typeof data == 'string' ? data : $.param(data);
+ //split params into form inputs
+ var inputs = '';
+ $.each(data.split('&'), function(){
+ var pair = this.split('=');
+ inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
+ });
+ //send request
+ $('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
+ .appendTo('body').submit().remove();
+
+ mod_toastr.info('Your download will begin soon');
+ }
+ },
+
+ importIntoHistory: function(){
+ this.refreshUserHistoriesList(function(self){
+ var template = self.templateBulkImportInModal();
+ self.modal = Galaxy.modal;
+ self.modal.show({
+ closing_events : true,
+ title : 'Import into History',
+ body : template({histories : self.histories.models}),
+ buttons : {
+ 'Import' : function() {self.importCurrentIntoHistory();},
+ 'Close' : function() {Galaxy.modal.hide();}
+ }
+ });
+ });
+ },
+
+ refreshUserHistoriesList: function(callback){
+ var self = this;
+ this.histories = new mod_library_model.GalaxyHistories();
+ this.histories.fetch({
+ success: function (){
+ callback(self);
+ },
+ error: function(model, response){
+ if (typeof response.responseJSON !== "undefined"){
+ mod_toastr.error(response.responseJSON.err_msg);
+ } else {
+ mod_toastr.error('An error ocurred :(');
+ }
+ }
+ });
+ },
+
+ importCurrentIntoHistory: function(){
+ var self = this;
+ var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val();
+ var historyItem = new mod_library_model.HistoryItem();
+ historyItem.url = historyItem.urlRoot + history_id + '/contents';
+
+ // set the used history as current so user will see the last one
+ // that he imported into in the history panel on the 'analysis' page
+ var set_current_url = '/api/histories/' + history_id + '/set_as_current';
+ $.ajax({
+ url: set_current_url,
+ type: 'PUT'
+ });
+
+ // save the dataset into selected history
+ historyItem.save({ content : this.id, source : 'library' }, {
+ success : function(){
+ Galaxy.modal.hide();
+ mod_toastr.success('Dataset imported. Click this to start analysing it.', '', {onclick: function() {window.location='/';}});
+ },
+ error : function(model, response){
+ if (typeof response.responseJSON !== "undefined"){
+ mod_toastr.error('Dataset not imported. ' + response.responseJSON.err_msg);
+ } else {
+ mod_toastr.error('An error occured! Dataset not imported. Please try again.');
+ }
+ }
+ });
+ },
+
+ shareDataset: function(){
+ mod_toastr.info('Feature coming soon.');
+ },
+
+ showPermissions: function(){
+ $(".tooltip").remove();
+ var template = this.templateDatasetPermissions();
+ this.$el.html(template({item: this.model}));
+
+ var self = this;
+
+ this.access_perm = new mod_select.View({
+ css: 'access_perm',
+ multiple:true,
+ placeholder: 'Click to select a role',
+ container: self.$el.find('#access_perm'),
+ ajax: {
+ url: "/api/libraries/datasets/5969b1f7201f12ae/permissions",
+ dataType: 'json',
+ quietMillis: 100,
+ data: function (term, page) { // page is the one-based page number tracked by Select2
+ return {
+ q: term, //search term
+ page_limit: 10, // page size
+ page: page // page number
+ };
+ },
+ results: function (data, page) {
+ var more = (page * 10) < data.total; // whether or not there are more results available
+ // notice we return the value of more so Select2 knows if more results can be loaded
+ return {results: data.roles, more: more};
+ }
+ },
+ formatResult : function roleFormatResult(role) {
+ return role.name;
+ },
+
+ formatSelection: function roleFormatSelection(role) {
+ return role.name;
+ },
+ initSelection: function(element, callback) {
+ // the input tag has a value attribute preloaded that points to a preselected role's id
+ // this function resolves that id attribute to an object that select2 can render
+ // using its formatResult renderer - that way the role name is shown preselected
+ var data = [];
+ $(element.val().split(",")).each(function(i) {
+ var item = this.split(':');
+ data.push({
+ id: item[1],
+ name: item[1]
+ });
+ });
+ callback(data);
+ },
+ initialData: 'marten@bx.psu.edu:marten@bx.psu.edu',
+ dropdownCssClass: "bigdrop" // apply css that makes the dropdown taller
+ });
+ // this.access_perm.$el.append($('<option>', {value:"NEWVAL", text: "New Option Text"}));
+
+ // this.modify_perm = new mod_select.View({
+ // css: 'modify_perm',
+ // placeholder: 'Select a role',
+ // // onchange : function() {
+ // // self.model.set('access_perm', self.select_genome.value());
+ // // },
+ // data: [{id:'test',text:'testik'}, {id:'dududu', text:'dadada'}],
+ // container: self.$el.find('#modify_perm'),
+ // multiple: true
+ // // value: self.model.get('access_perm')
+ // });
+ // this.modify_perm.$el.append($('<option>', {value:"NEWVAL", text: "New Option Text"}));
+
+ // this.manage_perm = new mod_select.View({
+ // css: 'manage_perm',
+ // placeholder: 'Select a role',
+ // // onchange : function() {
+ // // self.model.set('access_perm', self.select_genome.value());
+ // // },
+ // data: [{id:'test',text:'testik'}, {id:'dududu', text:'dadada'}],
+ // container: self.$el.find('#manage_perm'),
+ // multiple: true
+ // // value: self.model.get('access_perm')
+ // });
+ // this.manage_perm.$el.append($('<option>', {value:"NEWVAL", text: "New Option Text"}));
+
+ $("#center [data-toggle]").tooltip();
+ },
+
+
+ templateDataset : function(){
+ var tmpl_array = [];
+ // CONTAINER START
+ tmpl_array.push('<div class="library_style_container">');
+
+ tmpl_array.push(' <div id="library_toolbar">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Download dataset" class="btn btn-default toolbtn-download-dataset primary-button" type="button"><span class="fa fa-download"></span> Download</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import dataset into history" class="btn btn-default toolbtn-import-dataset primary-button" type="button"><span class="fa fa-book"></span> to History</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Modify dataset" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Change permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Share dataset" class="btn btn-default toolbtn-share-dataset primary-button" type="button"><span class="fa fa-share"></span> Share</span></button>');
+
+ tmpl_array.push(' </div>');
+
+ // BREADCRUMBS
+ tmpl_array.push('<ol class="breadcrumb">');
+ tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
+ tmpl_array.push(' <% _.each(item.get("full_path"), function(path_item) { %>');
+ tmpl_array.push(' <% if (path_item[0] != item.id) { %>');
+ tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');
+ tmpl_array.push( '<% } else { %>');
+ tmpl_array.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</ol>');
+
+ tmpl_array.push('<div class="dataset_table">');
+
+ tmpl_array.push(' <table class="grid table table-striped table-condensed">');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("name")) %></td>');
+ tmpl_array.push(' </tr>');
+
+ tmpl_array.push(' <% if (item.get("data_type")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Data type</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("data_type")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("genome_build")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Genome build</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("genome_build")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("file_size")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Size</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("file_size")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("date_uploaded")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Date uploaded (UTC)</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("uploaded_by")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Uploaded by</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_data_lines")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Data Lines</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_comment_lines")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Comment Lines</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_columns")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Number of Columns</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("metadata_column_types")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Column Types</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("message")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Message</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("misc_blurb")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous blurb</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' <% if (item.get("misc_info")) { %>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous information</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <% } %>');
+
+ tmpl_array.push(' </table>');
+ tmpl_array.push(' <div>');
+ tmpl_array.push(' <pre class="peek">');
+ tmpl_array.push(' </pre>');
+ tmpl_array.push(' </div>');
+ tmpl_array.push('</div>');
+
+ // CONTAINER END
+ tmpl_array.push('</div>');
+
+ return _.template(tmpl_array.join(''));
+ },
+
+ templateModifyDataset : function(){
+ var tmpl_array = [];
+ // CONTAINER START
+ tmpl_array.push('<div class="library_style_container">');
+
+ tmpl_array.push(' <div id="library_toolbar">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');
+
+ tmpl_array.push(' </div>');
+
+ // BREADCRUMBS
+ tmpl_array.push('<ol class="breadcrumb">');
+ tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
+ tmpl_array.push(' <% _.each(item.get("full_path"), function(path_item) { %>');
+ tmpl_array.push(' <% if (path_item[0] != item.id) { %>');
+ tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');
+ tmpl_array.push( '<% } else { %>');
+ tmpl_array.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</ol>');
+
+ tmpl_array.push('<div class="dataset_table">');
+ tmpl_array.push('<p>For more editing options please import the dataset to history and use "Edit attributes" on it.</p>');
+ tmpl_array.push(' <table class="grid table table-striped table-condensed">');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');
+ tmpl_array.push(' <td><input class="input_dataset_name form-control" type="text" placeholder="name" value="<%= _.escape(item.get("name")) %>"></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Data type</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("data_type")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Genome build</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("genome_build")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Size</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("file_size")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Date uploaded (UTC)</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Uploaded by</th>');
+ tmpl_array.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr scope="row">');
+ tmpl_array.push(' <th scope="row">Data Lines</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <th scope="row">Comment Lines</th>');
+ tmpl_array.push(' <% if (item.get("metadata_comment_lines") === "") { %>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');
+ tmpl_array.push(' <% } else { %>');
+ tmpl_array.push(' <td scope="row">unknown</td>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Number of Columns</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Column Types</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Message</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous information</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr>');
+ tmpl_array.push(' <th scope="row">Miscellaneous blurb</th>');
+ tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');
+ tmpl_array.push(' </tr>');
+ tmpl_array.push(' </table>');
+ tmpl_array.push('<div>');
+ tmpl_array.push(' <pre class="peek">');
+ tmpl_array.push(' </pre>');
+ tmpl_array.push('</div>');
+ tmpl_array.push('</div>');
+
+ // CONTAINER END
+ tmpl_array.push('</div>');
+
+ return _.template(tmpl_array.join(''));
+ },
+
+ templateDatasetPermissions : function(){
+ var tmpl_array = [];
+ // CONTAINER START
+ tmpl_array.push('<div class="library_style_container">');
+
+ tmpl_array.push(' <div id="library_toolbar">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');
+
+ tmpl_array.push(' </div>');
+
+ // BREADCRUMBS
+ tmpl_array.push('<ol class="breadcrumb">');
+ tmpl_array.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');
+ tmpl_array.push(' <% _.each(item.get("full_path"), function(path_item) { %>');
+ tmpl_array.push(' <% if (path_item[0] != item.id) { %>');
+ tmpl_array.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');
+ tmpl_array.push( '<% } else { %>');
+ tmpl_array.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');
+ tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</ol>');
+
+ tmpl_array.push('<h1><%= _.escape(item.get("name")) %></h1>');
+ tmpl_array.push('<div class="alert alert-success">You have rights to change permissions on this dataset. That means you can control who can access it, who can modify it and also appoint others that can manage permissions on it.</div>');
+ tmpl_array.push('<div class="dataset_table">');
+
+ tmpl_array.push('<h2>Basic permissions</h2>');
+ tmpl_array.push('<p>You can remove all access restrictions on this dataset. ');
+ tmpl_array.push('<button data-toggle="tooltip" data-placement="top" title="Everybody will be able to see the dataset." class="btn btn-default btn-remove-restrictions primary-button" type="button"><span class="fa fa-globe"></span> Remove restrictions</span></button>');
+ tmpl_array.push('</p>');
+
+ tmpl_array.push('<p>You can make this dataset private to you. ');
+ tmpl_array.push('<button data-toggle="tooltip" data-placement="top" title="Only you will be able to see the dataset." class="btn btn-default btn-make-private primary-button" type="button"><span class="fa fa-key"></span> Make private</span></button>');
+ tmpl_array.push('</p>');
+
+ tmpl_array.push('<h2>Advanced permissions</h2>');
+ tmpl_array.push('<p>You can assign any number of roles to any of the following three dataset permissions:</p>');
+ tmpl_array.push('<h3>Access Roles</h3>');
+ tmpl_array.push('<div class="alert alert-info">User has to have <strong>all these roles</strong> in order to see this dataset.</div>');
+ tmpl_array.push('<div id="access_perm" class="access_perm roles-selection"></div>');
+ tmpl_array.push('<h3>Modify Roles</h3>');
+ tmpl_array.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can modify the information about this dataset.</div>');
+ tmpl_array.push('<div id="modify_perm" class="modify_perm"></div>');
+ tmpl_array.push('<h3>Manage Roles</h3>');
+ tmpl_array.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can change permissions of this dataset.</div>');
+ tmpl_array.push('<div id="manage_perm" class="manage_perm"></div>');
+
+
+ tmpl_array.push('</div>');
+
+ // CONTAINER END
+ tmpl_array.push('</div>');
+
+ return _.template(tmpl_array.join(''));
+ },
+
+templateBulkImportInModal : function(){
+ var tmpl_array = [];
+
+ tmpl_array.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');
+ tmpl_array.push('Select history: ');
+ tmpl_array.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');
+ tmpl_array.push(' <% _.each(histories, function(history) { %>'); //history select box
+ tmpl_array.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');
+ tmpl_array.push(' <% }); %>');
+ tmpl_array.push('</select>');
+ tmpl_array.push('</span>');
+
+ return _.template(tmpl_array.join(''));
+ }
+
+});
+
+return {
+ LibraryDatasetView: LibraryDatasetView
+};
+
+});
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/mvc/library/library-folderlist-view.js
--- a/static/scripts/mvc/library/library-folderlist-view.js
+++ b/static/scripts/mvc/library/library-folderlist-view.js
@@ -4,12 +4,16 @@
"utils/utils",
"libs/toastr",
"mvc/library/library-model",
- "mvc/library/library-folderrow-view"],
+ "mvc/library/library-folderrow-view",
+ "mvc/library/library-dataset-view"
+ ],
function(mod_masthead,
mod_utils,
mod_toastr,
mod_library_model,
- mod_library_folderrow_view) {
+ mod_library_folderrow_view,
+ mod_library_dataset_view
+ ) {
var FolderListView = Backbone.View.extend({
el : '#folder_items_element',
@@ -42,16 +46,14 @@
},
fetchFolder: function(options){
- // this.options = _.defaults(this.options, options);
var options = options || {};
this.options.include_deleted = options.include_deleted;
var that = this;
this.collection = new mod_library_model.Folder();
- // start to listen if someone adds a model to the collection
+ // start to listen if someone modifies collection
this.listenTo(this.collection, 'add', this.renderOne);
-
this.listenTo(this.collection, 'remove', this.removeOne);
this.folderContainer = new mod_library_model.FolderContainer({id: this.options.id});
@@ -65,7 +67,12 @@
that.render();
that.addAll(folder_container.get('folder').models);
if (that.options.dataset_id){
- _.findWhere(that.rowViews, {id: that.options.dataset_id}).showDatasetDetails();
+ row = _.findWhere(that.rowViews, {id: that.options.dataset_id});
+ if (row) {
+ row.showDatasetDetails();
+ } else {
+ mod_toastr.error('Dataset not found. Showing folder instead.');
+ }
}
},
error: function(model, response){
@@ -109,7 +116,7 @@
var fetched_metadata = this.folderContainer.attributes.metadata;
fetched_metadata.contains_file = typeof this.collection.findWhere({type: 'file'}) !== 'undefined';
Galaxy.libraries.folderToolbarView.configureElements(fetched_metadata);
- $('.deleted_dataset').hover(function() {
+ $('.dataset').hover(function() {
$(this).find('.show_on_hover').show();
}, function () {
$(this).find('.show_on_hover').hide();
@@ -151,7 +158,7 @@
renderOne: function(model){
if (model.get('data_type') !== 'folder'){
this.options.contains_file = true;
- model.set('readable_size', this.size_to_string(model.get('file_size')));
+ // model.set('readable_size', this.size_to_string(model.get('file_size')));
}
model.set('folder_id', this.id);
var rowView = new mod_library_folderrow_view.FolderRowView(model);
@@ -161,7 +168,7 @@
this.$el.find('#first_folder_item').after(rowView.el);
- $('.deleted_dataset').hover(function() {
+ $('.dataset').hover(function() {
$(this).find('.show_on_hover').show();
}, function () {
$(this).find('.show_on_hover').hide();
@@ -213,21 +220,6 @@
}
},
- /**
- * convert size to nice string
- * @param {int} size
- * @return {string} readable representation of size with units
- */
- size_to_string : function (size){
- var unit = "";
- if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else
- if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else
- if (size >= 100000) { size = size / 100000; unit = "MB"; } else
- if (size >= 100) { size = size / 100; unit = "KB"; } else
- { size = size * 10; unit = "b"; }
- return (Math.round(size) / 10) + unit;
- },
-
/**
* User clicked the checkbox in the table heading
* @param {context} event
@@ -320,7 +312,7 @@
tmpl_array.push(' <th style="text-align: center; width: 20px; " title="Check to select all datasets"><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');
tmpl_array.push(' <th><a class="sort-folder-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:5%;">data type</th>');
- tmpl_array.push(' <th style="width:5%;">size</th>');
+ tmpl_array.push(' <th style="width:10%;">size</th>');
tmpl_array.push(' <th style="width:160px;">time updated (UTC)</th>');
tmpl_array.push(' <th style="width:10%;"></th> ');
tmpl_array.push(' </thead>');
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/mvc/library/library-folderrow-view.js
--- a/static/scripts/mvc/library/library-folderrow-view.js
+++ b/static/scripts/mvc/library/library-folderrow-view.js
@@ -1,13 +1,14 @@
-// dependencies
define([
"galaxy.masthead",
"utils/utils",
"libs/toastr",
- "mvc/library/library-model"],
+ "mvc/library/library-model",
+ "mvc/library/library-dataset-view"],
function(mod_masthead,
mod_utils,
mod_toastr,
- mod_library_model) {
+ mod_library_model,
+ mod_library_dataset_view) {
// galaxy library row view
var FolderRowView = Backbone.View.extend({
@@ -15,7 +16,7 @@
lastSelectedHistory: '',
events: {
- 'click .undelete_dataset_btn' : 'undelete_dataset'
+ 'click .undelete_dataset_btn' : 'undelete_dataset'
},
options: {
@@ -27,9 +28,6 @@
},
render: function(folder_item){
- // if (typeof folder_item === 'undefined'){
- // folder_item = Galaxy.libraries.libraryFolderView.collection.get(this.$el.data('id'));
- // }
var template = null;
if (folder_item.get('type') === 'folder'){
this.options.type = 'folder';
@@ -47,172 +45,8 @@
return this;
},
- //show modal with current dataset info
showDatasetDetails : function(){
- var id = this.id;
-
- //create new item
- var item = new mod_library_model.Item();
- var histories = new mod_library_model.GalaxyHistories();
- item.id = id;
- var self = this;
-
- //fetch the dataset info
- item.fetch({
- success: function (item) {
- // TODO can start rendering here already
- //fetch user histories for import purposes
- histories.fetch({
- success: function (histories){
- self.renderModalAfterFetch(item, histories);
- },
- error: function(model, response){
- if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error(response.responseJSON.err_msg);
- } else {
- mod_toastr.error('An error occured during fetching histories:(');
- }
- self.renderModalAfterFetch(item);
- }
- });
- },
- error: function(model, response){
- if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error(response.responseJSON.err_msg);
- } else {
- mod_toastr.error('An error occured during loading dataset details :(');
- }
- }
- });
-},
-
- // show the current dataset in a modal
- renderModalAfterFetch : function(item, histories){
- var size = this.size_to_string(item.get('file_size'));
- var template = _.template(this.templateDatasetModal(), { item : item, size : size });
- // make modal
- var self = this;
- this.modal = Galaxy.modal;
- this.modal.show({
- closing_events : true,
- title : item.get('name'),
- body : template,
- buttons : {
- 'Import' : function() { self.importCurrentIntoHistory(); },
- 'Download' : function() { self.downloadCurrent(); },
- 'Close' : function() { self.modal.hide(); }
- },
- closing_callback : function(){
- var path_to_folder = Backbone.history.fragment.split('/datasets')[0];
- Galaxy.libraries.library_router.navigate('#' + path_to_folder, {trigger:true, replace:true});
- }
- });
-
- $(".peek").html(item.get("peek"));
-
- // show the import-into-history footer only if the request for histories succeeded
- if (typeof history.models !== undefined){
- var history_footer_tmpl = _.template(this.templateHistorySelectInModal(), {histories : histories.models});
- $(this.modal.elMain).find('.buttons').prepend(history_footer_tmpl);
- // preset last selected history if we know it
- if (self.lastSelectedHistory.length > 0) {
- $(this.modal.elMain).find('#dataset_import_single').val(self.lastSelectedHistory);
- }
- }
- },
-
- // TODO this is dup func, unify
- // convert size to nice string
- size_to_string : function (size){
- // identify unit
- var unit = "";
- if (size >= 100000000000) { size = size / 100000000000; unit = "TB"; } else
- if (size >= 100000000) { size = size / 100000000; unit = "GB"; } else
- if (size >= 100000) { size = size / 100000; unit = "MB"; } else
- if (size >= 100) { size = size / 100; unit = "KB"; } else
- { size = size * 10; unit = "b"; }
- // return formatted string
- return (Math.round(size) / 10) + unit;
- },
-
- // download dataset shown currently in modal
- downloadCurrent : function(){
- //disable the buttons
- this.modal.disableButton('Import');
- this.modal.disableButton('Download');
-
- var library_dataset_id = [];
- library_dataset_id.push($('#id_row').attr('data-id'));
- var url = '/api/libraries/datasets/download/uncompressed';
- var data = {'ldda_ids' : library_dataset_id};
-
- this.processDownload(url, data);
- this.modal.enableButton('Import');
- this.modal.enableButton('Download');
- },
-
- // TODO this is dup func, unify
- // create hidden form and submit through POST to initialize download
- processDownload: function(url, data, method){
- //url and data options required
- if( url && data ){
- //data can be string of parameters or array/object
- data = typeof data == 'string' ? data : $.param(data);
- //split params into form inputs
- var inputs = '';
- $.each(data.split('&'), function(){
- var pair = this.split('=');
- inputs+='<input type="hidden" name="'+ pair[0] +'" value="'+ pair[1] +'" />';
- });
- //send request
- $('<form action="'+ url +'" method="'+ (method||'post') +'">'+inputs+'</form>')
- .appendTo('body').submit().remove();
-
- mod_toastr.info('Your download will begin soon');
- }
- },
-
- // import dataset shown currently in modal into selected history
- importCurrentIntoHistory : function(){
- //disable the buttons
- this.modal.disableButton('Import');
- this.modal.disableButton('Download');
-
- var history_id = $(this.modal.elMain).find('select[name=dataset_import_single] option:selected').val();
- this.lastSelectedHistory = history_id; //save selected history for further use
-
- var library_dataset_id = $('#id_row').attr('data-id');
- var historyItem = new mod_library_model.HistoryItem();
- var self = this;
- historyItem.url = historyItem.urlRoot + history_id + '/contents';
-
- // set the used history as current so user will see the last one
- // that he imported into in the history panel on the 'analysis' page
- var set_current_url = '/api/histories/' + history_id + '/set_as_current';
- $.ajax({
- url: set_current_url,
- type: 'PUT'
- });
-
- // save the dataset into selected history
- historyItem.save({ content : library_dataset_id, source : 'library' }, {
- success : function(){
- mod_toastr.success('Dataset imported. Click this to start analysing it.', '', {onclick: function() {window.location='/'}});
- //enable the buttons
- self.modal.enableButton('Import');
- self.modal.enableButton('Download');
- },
- error : function(model, response){
- if (typeof response.responseJSON !== "undefined"){
- mod_toastr.error('Dataset not imported. ' + response.responseJSON.err_msg);
- } else {
- mod_toastr.error('An error occured! Dataset not imported. Please try again.');
- }
- //enable the buttons
- self.modal.enableButton('Import');
- self.modal.enableButton('Download');
- }
- });
+ this.dataset_view = new mod_library_dataset_view.LibraryDatasetView({id: this.id});
},
/**
@@ -232,8 +66,8 @@
success : function(model, response){
Galaxy.libraries.folderListView.collection.remove(dataset_id);
var updated_dataset = new mod_library_model.Item(response);
- Galaxy.libraries.folderListView.collection.add(updated_dataset)
- mod_toastr.success('Dataset undeleted. Click this to see it.', '', {onclick: function() {that.showDatasetDetails()}});
+ Galaxy.libraries.folderListView.collection.add(updated_dataset);
+ mod_toastr.success('Dataset undeleted. Click this to see it.', '', {onclick: function() {that.showDatasetDetails();}});
},
error : function(model, response){
if (typeof response.responseJSON !== "undefined"){
@@ -255,14 +89,9 @@
tmpl_array.push(' <td></td>');
tmpl_array.push(' <td>');
tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');
- // tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>'); // empty folder
- // tmpl_array.push(' <span>(empty folder)</span>');
- // tmpl_array.push(' <% } %>');
tmpl_array.push(' </td>');
tmpl_array.push(' <td>folder</td>');
tmpl_array.push(' <td></td>');
- // print item count only if it is given
- // tmpl_array.push(' <td><% if (typeof content_item.get("item_count") !== "undefined") { _.escape(content_item.get("item_count")); print("item(s)") } %></td>');
tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push(' <td></td>');
tmpl_array.push('</tr>');
@@ -273,20 +102,20 @@
templateRowFile: function(){
tmpl_array = [];
- tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');
+ tmpl_array.push('<tr class="dataset_row light dataset" id="<%- content_item.id %>">');
tmpl_array.push(' <td>');
tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');
tmpl_array.push(' </td>');
tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');
tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>'); // dataset
tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>'); // data type
- tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>'); // size
+ tmpl_array.push(' <td><%= _.escape(content_item.get("file_size")) %></td>'); // size
tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push(' <td>');
tmpl_array.push(' <% if (content_item.get("is_unrestricted")) { %><span data-toggle="tooltip" data-placement="top" title="Unrestricted dataset" style="color:grey;" class="fa fa-globe fa-lg"></span><% } %>');
tmpl_array.push(' <% if (content_item.get("is_private")) { %><span data-toggle="tooltip" data-placement="top" title="Private dataset" style="color:grey;" class="fa fa-key fa-lg"></span><% } %>');
- tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-group fa-lg"></span>');
- tmpl_array.push(' <% } %>');
+ tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-shield fa-lg"></span><% } %>');
+ tmpl_array.push(' <% if (content_item.get("can_manage")) { %><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" class="primary-button btn-xs permissions-dataset-btn show_on_hover" title="Manage permissions" style="display:none;"><span class="fa fa-group"></span></button></a><% } %>');
tmpl_array.push(' </td>');
tmpl_array.push('</tr>');
@@ -296,94 +125,20 @@
templateRowDeletedFile: function(){
tmpl_array = [];
- tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');
+ tmpl_array.push('<tr class="active deleted_dataset dataset" id="<%- content_item.id %>">');
tmpl_array.push(' <td>');
tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');
tmpl_array.push(' </td>');
tmpl_array.push(' <td></td>');
tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>'); // dataset
tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>'); // data type
- tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>'); // size
+ tmpl_array.push(' <td><%= _.escape(content_item.get("file_size")) %></td>'); // size
tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none; margin-left:1em;"><span class="fa fa-unlock"> Undelete</span></button></td>');
tmpl_array.push('</tr>');
return _.template(tmpl_array.join(''));
- },
-
-templateDatasetModal : function(){
- var tmpl_array = [];
-
- tmpl_array.push('<div class="modal_table">');
- tmpl_array.push(' <table class="grid table table-striped table-condensed">');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("name")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Data type</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("data_type")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Genome build</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("genome_build")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <th scope="row">Size</th>');
- tmpl_array.push(' <td><%= _.escape(size) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Date uploaded (UTC)</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Uploaded by</th>');
- tmpl_array.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr scope="row">');
- tmpl_array.push(' <th scope="row">Data Lines</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <th scope="row">Comment Lines</th>');
- tmpl_array.push(' <% if (item.get("metadata_comment_lines") === "") { %>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');
- tmpl_array.push(' <% } else { %>');
- tmpl_array.push(' <td scope="row">unknown</td>');
- tmpl_array.push(' <% } %>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Number of Columns</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Column Types</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' <tr>');
- tmpl_array.push(' <th scope="row">Miscellaneous information</th>');
- tmpl_array.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');
- tmpl_array.push(' </tr>');
- tmpl_array.push(' </table>');
- tmpl_array.push(' <pre class="peek">');
- tmpl_array.push(' </pre>');
- tmpl_array.push('</div>');
-
- return tmpl_array.join('');
-},
-
-templateHistorySelectInModal : function(){
- var tmpl_array = [];
-
- tmpl_array.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');
- tmpl_array.push('Select history: ');
- tmpl_array.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');
- tmpl_array.push(' <% _.each(histories, function(history) { %>'); //history select box
- tmpl_array.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');
- tmpl_array.push(' <% }); %>');
- tmpl_array.push('</select>');
- tmpl_array.push('</span>');
-
- return tmpl_array.join('');
-}
+ }
});
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/mvc/library/library-foldertoolbar-view.js
@@ -519,16 +519,16 @@
// CONTAINER
tmpl_array.push('<div class="library_style_container">');
// TOOLBAR
- tmpl_array.push('<div id="library_folder_toolbar">');
+ tmpl_array.push('<div id="library_toolbar">');
tmpl_array.push('<span data-toggle="tooltip" data-placement="top" class="logged-dataset-manipulation" title="Include deleted datasets" style="display:none;"><input id="include_deleted_datasets_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');
tmpl_array.push('<div class="btn-group add-library-items" style="display:none;">');
tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');
tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');
tmpl_array.push('</div>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button dataset-manipulation" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to history</button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button dataset-manipulation" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to History</button>');
tmpl_array.push(' <div id="toolbtn_dl" class="btn-group dataset-manipulation" style="margin-left: 0.5em; display:none; ">');
tmpl_array.push(' <button title="Download selected datasets as archive" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');
- tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');
+ tmpl_array.push(' <span class="fa fa-download"></span> Download <span class="caret"></span>');
tmpl_array.push(' </button>');
tmpl_array.push(' <ul class="dropdown-menu" role="menu">');
tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');
@@ -536,7 +536,7 @@
tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');
tmpl_array.push(' </ul>');
tmpl_array.push(' </div>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Mark selected datasets deleted" id="toolbtn_bulk_delete" class="primary-button logged-dataset-manipulation" style="margin-left: 0.5em; display:none; " type="button"><span class="fa fa-times"></span> delete</button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Mark selected datasets deleted" id="toolbtn_bulk_delete" class="primary-button logged-dataset-manipulation" style="margin-left: 0.5em; display:none; " type="button"><span class="fa fa-times"></span> Delete</button>');
tmpl_array.push(' </div>');
tmpl_array.push(' <div id="folder_items_element">');
// library items will append here
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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
@@ -115,7 +115,7 @@
tmpl_array.push('<div class="library_style_container">');
// TOOLBAR
- tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');
+ tmpl_array.push(' <div id="toolbar_form">');
tmpl_array.push(' <% if(admin_user === true) { %>');
tmpl_array.push(' <div id="library_toolbar">');
tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Include deleted libraries"><input id="include_deleted_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/galaxy.library.js
--- a/static/scripts/packed/galaxy.library.js
+++ b/static/scripts/packed/galaxy.library.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({initialize:function(){this.routesHit=0;Backbone.history.on("route",function(){this.routesHit++},this)},routes:{"":"libraries","folders/:id":"folder_content","folders/:folder_id/datasets/:dataset_id":"dataset_detail","folders/:folder_id/download/:format":"download"},back:function(){if(this.routesHit>1){window.history.back()}else{this.navigate("#",{trigger:true,replace:true})}}});var j=k.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new j({id:"global-lib-prefs"});this.library_router=new l();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new d.LibraryToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:m});Galaxy.libraries.folderListView=new a.FolderListView({id:m})});this.library_router.on("route:download",function(m,n){if($("#folder_list_body").find(":checked").length===0){g.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(m,n);Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:false,replace:true})}});this.library_router.on("route:dataset_detail",function(n,m){Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:n});Galaxy.libraries.folderListView=new a.FolderListView({id:n,dataset_id:m})});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view","mvc/library/library-dataset-view"],function(f,c,h,l,i,a,g,e,j,d){var m=Backbone.Router.extend({initialize:function(){this.routesHit=0;Backbone.history.on("route",function(){this.routesHit++},this)},routes:{"":"libraries","folders/:id":"folder_content","folders/:folder_id/datasets/:dataset_id":"dataset_detail","folders/:folder_id/datasets/:dataset_id/permissions":"dataset_permissions","folders/:folder_id/download/:format":"download"},back:function(){if(this.routesHit>1){window.history.back()}else{this.navigate("#",{trigger:true,replace:true})}}});var k=l.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new k({id:"global-lib-prefs"});this.library_router=new m();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new e.LibraryToolbarView();Galaxy.libraries.libraryListView=new g.LibraryListView()});this.library_router.on("route:folder_content",function(n){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new j.FolderToolbarView({id:n});Galaxy.libraries.folderListView=new a.FolderListView({id:n})});this.library_router.on("route:download",function(n,o){if($("#folder_list_body").find(":checked").length===0){h.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+n,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(n,o);Galaxy.libraries.library_router.navigate("folders/"+n,{trigger:false,replace:true})}});this.library_router.on("route:dataset_detail",function(o,n){new d.LibraryDatasetView({id:n})});this.library_router.on("route:dataset_permissions",function(o,n){new d.LibraryDatasetView({id:n,show_permissions:true})});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/mvc/library/library-dataset-view.js
--- /dev/null
+++ b/static/scripts/packed/mvc/library/library-dataset-view.js
@@ -0,0 +1,1 @@
+define(["libs/toastr","mvc/library/library-model","mvc/ui/ui-select"],function(d,c,b){var a=Backbone.View.extend({el:"#center",model:null,options:{},events:{"click .toolbtn_modify_dataset":"enableModification","click .toolbtn_cancel_modifications":"render","click .toolbtn_change_permissions":"showPermissions","click .toolbtn-download-dataset":"downloadDataset","click .toolbtn-import-dataset":"importIntoHistory","click .toolbtn-share-dataset":"shareDataset"},initialize:function(e){this.options=_.extend(this.options,e);if(this.options.id){this.fetchDataset()}},fetchDataset:function(e){this.options=_.extend(this.options,e);this.model=new c.Item({id:this.options.id});var f=this;this.model.fetch({success:function(){if(f.options.show_permissions){f.showPermissions()}else{f.render()}},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{d.error("An error ocurred :(. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(e){$(".tooltip").remove();this.options=_.extend(this.options,e);var f=this.templateDataset();this.$el.html(f({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},enableModification:function(){$(".tooltip").remove();var e=this.templateModifyDataset();this.$el.html(e({item:this.model}));$(".peek").html(this.model.get("peek"));$("#center [data-toggle]").tooltip()},downloadDataset:function(){var e="/api/libraries/datasets/download/uncompressed";var f={ldda_ids:this.id};this.processDownload(e,f)},processDownload:function(f,g,h){if(f&&g){g=typeof g=="string"?g:$.param(g);var e="";$.each(g.split("&"),function(){var i=this.split("=");e+='<input type="hidden" name="'+i[0]+'" value="'+i[1]+'" />'});$('<form action="'+f+'" method="'+(h||"post")+'">'+e+"</form>").appendTo("body").submit().remove();d.info("Your download will begin soon")}},importIntoHistory:function(){this.refreshUserHistoriesList(function(e){var f=e.templateBulkImportInModal();e.modal=Galaxy.modal;e.modal.show({closing_events:true,title:"Import into History",body:f({histories:e.histories.models}),buttons:{Import:function(){e.importCurrentIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})},refreshUserHistoriesList:function(f){var e=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){f(e)},error:function(h,g){if(typeof g.responseJSON!=="undefined"){d.error(g.responseJSON.err_msg)}else{d.error("An error ocurred :(")}}})},importCurrentIntoHistory:function(){var f=this;var g=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();var h=new c.HistoryItem();h.url=h.urlRoot+g+"/contents";var e="/api/histories/"+g+"/set_as_current";$.ajax({url:e,type:"PUT"});h.save({content:this.id,source:"library"},{success:function(){Galaxy.modal.hide();d.success("Dataset imported. Click this to start analysing it.","",{onclick:function(){window.location="/"}})},error:function(j,i){if(typeof i.responseJSON!=="undefined"){d.error("Dataset not imported. "+i.responseJSON.err_msg)}else{d.error("An error occured! Dataset not imported. Please try again.")}}})},shareDataset:function(){d.info("Feature coming soon.")},showPermissions:function(){$(".tooltip").remove();var g=this.templateDatasetPermissions();this.$el.html(g({item:this.model}));var e=this;this.access_perm=new b.View({css:"access_perm",multiple:true,placeholder:"Click to select a role",container:e.$el.find("#access_perm"),ajax:{url:"/api/libraries/datasets/5969b1f7201f12ae/permissions",dataType:"json",quietMillis:100,data:function(i,j){return{q:i,page_limit:10,page:j}},results:function(k,j){var i=(j*10)<k.total;return{results:k.roles,more:i}}},formatResult:function f(i){return i.name},formatSelection:function h(i){return i.name},initSelection:function(i,k){var j=[];$(i.val().split(",")).each(function(l){var m=this.split(":");j.push({id:m[1],name:m[1]})});k(j)},initialData:"marten@bx.psu.edu:marten@bx.psu.edu",dropdownCssClass:"bigdrop"});$("#center [data-toggle]").tooltip()},templateDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push(' <div id="library_toolbar">');e.push(' <button data-toggle="tooltip" data-placement="top" title="Download dataset" class="btn btn-default toolbtn-download-dataset primary-button" type="button"><span class="fa fa-download"></span> Download</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Import dataset into history" class="btn btn-default toolbtn-import-dataset primary-button" type="button"><span class="fa fa-book"></span> to History</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Modify dataset" class="btn btn-default toolbtn_modify_dataset primary-button" type="button"><span class="fa fa-pencil"></span> Modify</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Change permissions" class="btn btn-default toolbtn_change_permissions primary-button" type="button"><span class="fa fa-group"></span> Permissions</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Share dataset" class="btn btn-default toolbtn-share-dataset primary-button" type="button"><span class="fa fa-share"></span> Share</span></button>');e.push(" </div>");e.push('<ol class="breadcrumb">');e.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push(' <% _.each(item.get("full_path"), function(path_item) { %>');e.push(" <% if (path_item[0] != item.id) { %>");e.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push(" <% } %>");e.push(" <% }); %>");e.push("</ol>");e.push('<div class="dataset_table">');e.push(' <table class="grid table table-striped table-condensed">');e.push(" <tr>");e.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push(' <td><%= _.escape(item.get("name")) %></td>');e.push(" </tr>");e.push(' <% if (item.get("data_type")) { %>');e.push(" <tr>");e.push(' <th scope="row">Data type</th>');e.push(' <td><%= _.escape(item.get("data_type")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("genome_build")) { %>');e.push(" <tr>");e.push(' <th scope="row">Genome build</th>');e.push(' <td><%= _.escape(item.get("genome_build")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("file_size")) { %>');e.push(" <tr>");e.push(' <th scope="row">Size</th>');e.push(' <td><%= _.escape(item.get("file_size")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("date_uploaded")) { %>');e.push(" <tr>");e.push(' <th scope="row">Date uploaded (UTC)</th>');e.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("uploaded_by")) { %>');e.push(" <tr>");e.push(' <th scope="row">Uploaded by</th>');e.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_data_lines")) { %>');e.push(" <tr>");e.push(' <th scope="row">Data Lines</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_comment_lines")) { %>');e.push(" <tr>");e.push(' <th scope="row">Comment Lines</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_columns")) { %>');e.push(" <tr>");e.push(' <th scope="row">Number of Columns</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("metadata_column_types")) { %>');e.push(" <tr>");e.push(' <th scope="row">Column Types</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("message")) { %>');e.push(" <tr>");e.push(' <th scope="row">Message</th>');e.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("misc_blurb")) { %>');e.push(" <tr>");e.push(' <th scope="row">Miscellaneous blurb</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(' <% if (item.get("misc_info")) { %>');e.push(" <tr>");e.push(' <th scope="row">Miscellaneous information</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push(" </tr>");e.push(" <% } %>");e.push(" </table>");e.push(" <div>");e.push(' <pre class="peek">');e.push(" </pre>");e.push(" </div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateModifyDataset:function(){var e=[];e.push('<div class="library_style_container">');e.push(' <div id="library_toolbar">');e.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push(" </div>");e.push('<ol class="breadcrumb">');e.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push(' <% _.each(item.get("full_path"), function(path_item) { %>');e.push(" <% if (path_item[0] != item.id) { %>");e.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push(" <% } %>");e.push(" <% }); %>");e.push("</ol>");e.push('<div class="dataset_table">');e.push('<p>For more editing options please import the dataset to history and use "Edit attributes" on it.</p>');e.push(' <table class="grid table table-striped table-condensed">');e.push(" <tr>");e.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');e.push(' <td><input class="input_dataset_name form-control" type="text" placeholder="name" value="<%= _.escape(item.get("name")) %>"></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Data type</th>');e.push(' <td><%= _.escape(item.get("data_type")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Genome build</th>');e.push(' <td><%= _.escape(item.get("genome_build")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Size</th>');e.push(' <td><%= _.escape(item.get("file_size")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Date uploaded (UTC)</th>');e.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Uploaded by</th>');e.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');e.push(" </tr>");e.push(' <tr scope="row">');e.push(' <th scope="row">Data Lines</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');e.push(" </tr>");e.push(' <th scope="row">Comment Lines</th>');e.push(' <% if (item.get("metadata_comment_lines") === "") { %>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');e.push(" <% } else { %>");e.push(' <td scope="row">unknown</td>');e.push(" <% } %>");e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Number of Columns</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Column Types</th>');e.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Message</th>');e.push(' <td scope="row"><%= _.escape(item.get("message")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Miscellaneous information</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_info")) %></td>');e.push(" </tr>");e.push(" <tr>");e.push(' <th scope="row">Miscellaneous blurb</th>');e.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');e.push(" </tr>");e.push(" </table>");e.push("<div>");e.push(' <pre class="peek">');e.push(" </pre>");e.push("</div>");e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateDatasetPermissions:function(){var e=[];e.push('<div class="library_style_container">');e.push(' <div id="library_toolbar">');e.push(' <button data-toggle="tooltip" data-placement="top" title="Cancel modifications" class="btn btn-default toolbtn_cancel_modifications primary-button" type="button"><span class="fa fa-times"></span> Cancel</span></button>');e.push(' <button data-toggle="tooltip" data-placement="top" title="Save modifications" class="btn btn-default toolbtn_save_modifications primary-button" type="button"><span class="fa fa-floppy-o"></span> Save</span></button>');e.push(" </div>");e.push('<ol class="breadcrumb">');e.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');e.push(' <% _.each(item.get("full_path"), function(path_item) { %>');e.push(" <% if (path_item[0] != item.id) { %>");e.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');e.push("<% } else { %>");e.push(' <li class="active"><span title="You are here"><%- path_item[1] %></span></li>');e.push(" <% } %>");e.push(" <% }); %>");e.push("</ol>");e.push('<h1><%= _.escape(item.get("name")) %></h1>');e.push('<div class="alert alert-success">You have rights to change permissions on this dataset. That means you can control who can access it, who can modify it and also appoint others that can manage permissions on it.</div>');e.push('<div class="dataset_table">');e.push("<h2>Basic permissions</h2>");e.push("<p>You can remove all access restrictions on this dataset. ");e.push('<button data-toggle="tooltip" data-placement="top" title="Everybody will be able to see the dataset." class="btn btn-default btn-remove-restrictions primary-button" type="button"><span class="fa fa-globe"></span> Remove restrictions</span></button>');e.push("</p>");e.push("<p>You can make this dataset private to you. ");e.push('<button data-toggle="tooltip" data-placement="top" title="Only you will be able to see the dataset." class="btn btn-default btn-make-private primary-button" type="button"><span class="fa fa-key"></span> Make private</span></button>');e.push("</p>");e.push("<h2>Advanced permissions</h2>");e.push("<p>You can assign any number of roles to any of the following three dataset permissions:</p>");e.push("<h3>Access Roles</h3>");e.push('<div class="alert alert-info">User has to have <strong>all these roles</strong> in order to see this dataset.</div>');e.push('<div id="access_perm" class="access_perm roles-selection"></div>');e.push("<h3>Modify Roles</h3>");e.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can modify the information about this dataset.</div>');e.push('<div id="modify_perm" class="modify_perm"></div>');e.push("<h3>Manage Roles</h3>");e.push('<div class="alert alert-info">Users with <strong>any</strong> of these roles can change permissions of this dataset.</div>');e.push('<div id="manage_perm" class="manage_perm"></div>');e.push("</div>");e.push("</div>");return _.template(e.join(""))},templateBulkImportInModal:function(){var e=[];e.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');e.push("Select history: ");e.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');e.push(" <% _.each(histories, function(history) { %>");e.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');e.push(" <% }); %>");e.push("</select>");e.push("</span>");return _.template(e.join(""))}});return{LibraryDatasetView:a}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/mvc/library/library-folderlist-view.js
--- a/static/scripts/packed/mvc/library/library-folderlist-view.js
+++ b/static/scripts/packed/mvc/library/library-folderlist-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view"],function(c,e,f,d,a){var b=Backbone.View.extend({el:"#folder_items_element",defaults:{include_deleted:false},progress:0,progressStep:1,modal:null,folderContainer:null,sort:"asc",events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow","click .sort-folder-link":"sort_clicked"},rowViews:{},initialize:function(g){this.options=_.defaults(this.options||{},g);this.fetchFolder()},fetchFolder:function(g){var g=g||{};this.options.include_deleted=g.include_deleted;var h=this;this.collection=new d.Folder();this.listenTo(this.collection,"add",this.renderOne);this.listenTo(this.collection,"remove",this.removeOne);this.folderContainer=new d.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";if(this.options.include_deleted){this.folderContainer.url=this.folderContainer.url+"?include_deleted=true"}this.folderContainer.fetch({success:function(i){h.folder_container=i;h.render();h.addAll(i.get("folder").models);if(h.options.dataset_id){_.findWhere(h.rowViews,{id:h.options.dataset_id}).showDatasetDetails()}},error:function(j,i){if(typeof i.responseJSON!=="undefined"){f.error(i.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{f.error("An error ocurred :(. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(g){this.options=_.defaults(this.options,g);var h=this.templateFolder();var i=this.folderContainer.attributes.metadata.full_path;var j;if(i.length===1){j=0}else{j=i[i.length-2][0]}this.$el.html(h({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:j,order:this.sort}));$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},postRender:function(){var g=this.folderContainer.attributes.metadata;g.contains_file=typeof this.collection.findWhere({type:"file"})!=="undefined";Galaxy.libraries.folderToolbarView.configureElements(g);$(".deleted_dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},addAll:function(g){_.each(g.reverse(),function(h){Galaxy.libraries.folderListView.collection.add(h)});$("#center [data-toggle]").tooltip();this.checkEmptiness();this.postRender()},renderAll:function(){var g=this;_.each(this.collection.models.reverse(),function(h){g.renderOne(h)});this.postRender()},renderOne:function(h){if(h.get("data_type")!=="folder"){this.options.contains_file=true;h.set("readable_size",this.size_to_string(h.get("file_size")))}h.set("folder_id",this.id);var g=new a.FolderRowView(h);this.rowViews[h.get("id")]=g;this.$el.find("#first_folder_item").after(g.el);$(".deleted_dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},removeOne:function(g){this.$el.find("#"+g.id).remove()},checkEmptiness:function(){if((this.$el.find(".dataset_row").length===0)&&(this.$el.find(".folder_row").length===0)){this.$el.find(".empty-folder-message").show()}else{this.$el.find(".empty-folder-message").hide()}},sort_clicked:function(g){g.preventDefault();if(this.sort==="asc"){this.sortFolder("name","desc");this.sort="desc"}else{this.sortFolder("name","asc");this.sort="asc"}this.render();this.renderAll()},sortFolder:function(h,g){if(h==="name"){if(g==="asc"){return this.collection.sortByNameAsc()}else{if(g==="desc"){return this.collection.sortByNameDesc()}}}},size_to_string:function(g){var h="";if(g>=100000000000){g=g/100000000000;h="TB"}else{if(g>=100000000){g=g/100000000;h="GB"}else{if(g>=100000){g=g/100000;h="MB"}else{if(g>=100){g=g/100;h="KB"}else{g=g*10;h="b"}}}}return(Math.round(g)/10)+h},selectAll:function(h){var g=h.target.checked;that=this;$(":checkbox","#folder_list_body").each(function(){this.checked=g;$row=$(this.parentElement.parentElement);if(g){that.makeDarkRow($row)}else{that.makeWhiteRow($row)}})},selectClickedRow:function(h){var j="";var g;var i;if(h.target.localName==="input"){j=h.target;g=$(h.target.parentElement.parentElement);i="input"}else{if(h.target.localName==="td"){j=$("#"+h.target.parentElement.id).find(":checkbox")[0];g=$(h.target.parentElement);i="td"}}if(j.checked){if(i==="td"){j.checked="";this.makeWhiteRow(g)}else{if(i==="input"){this.makeDarkRow(g)}}}else{if(i==="td"){j.checked="selected";this.makeDarkRow(g)}else{if(i==="input"){this.makeWhiteRow(g)}}}},makeDarkRow:function(g){g.removeClass("light").addClass("dark");g.find("a").removeClass("light").addClass("dark");g.find(".fa-file-o").removeClass("fa-file-o").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark").addClass("light");g.find("a").removeClass("dark").addClass("light");g.find(".fa-file").removeClass("fa-file").addClass("fa-file-o")},templateFolder:function(){var g=[];g.push('<ol class="breadcrumb">');g.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');g.push(" <% _.each(path, function(path_item) { %>");g.push(" <% if (path_item[0] != id) { %>");g.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');g.push("<% } else { %>");g.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');g.push(" <% } %>");g.push(" <% }); %>");g.push("</ol>");g.push('<table id="folder_table" class="grid table table-condensed">');g.push(" <thead>");g.push(' <th class="button_heading"></th>');g.push(' <th style="text-align: center; width: 20px; " title="Check to select all datasets"><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');g.push(' <th><a class="sort-folder-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');g.push(' <th style="width:5%;">data type</th>');g.push(' <th style="width:5%;">size</th>');g.push(' <th style="width:160px;">time updated (UTC)</th>');g.push(' <th style="width:10%;"></th> ');g.push(" </thead>");g.push(' <tbody id="folder_list_body">');g.push(' <tr id="first_folder_item">');g.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" </tr>");g.push(" </tbody>");g.push("</table>");g.push('<div class="empty-folder-message" style="display:none;">This folder is either empty or you do not have proper access permissions to see the contents. If you expected something to show up please consult the <a href="https://wiki.galaxyproject.org/Admin/DataLibraries/LibrarySecurity">library security wikipage</a> or visit the <a href="https://biostar.usegalaxy.org/">Galaxy support site</a>.</div>');return _.template(g.join(""))}});return{FolderListView:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view","mvc/library/library-dataset-view"],function(d,f,g,e,a,c){var b=Backbone.View.extend({el:"#folder_items_element",defaults:{include_deleted:false},progress:0,progressStep:1,modal:null,folderContainer:null,sort:"asc",events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow","click .sort-folder-link":"sort_clicked"},rowViews:{},initialize:function(h){this.options=_.defaults(this.options||{},h);this.fetchFolder()},fetchFolder:function(h){var h=h||{};this.options.include_deleted=h.include_deleted;var i=this;this.collection=new e.Folder();this.listenTo(this.collection,"add",this.renderOne);this.listenTo(this.collection,"remove",this.removeOne);this.folderContainer=new e.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";if(this.options.include_deleted){this.folderContainer.url=this.folderContainer.url+"?include_deleted=true"}this.folderContainer.fetch({success:function(j){i.folder_container=j;i.render();i.addAll(j.get("folder").models);if(i.options.dataset_id){row=_.findWhere(i.rowViews,{id:i.options.dataset_id});if(row){row.showDatasetDetails()}else{g.error("Dataset not found. Showing folder instead.")}}},error:function(k,j){if(typeof j.responseJSON!=="undefined"){g.error(j.responseJSON.err_msg+" Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}else{g.error("An error ocurred :(. Click this to go back.","",{onclick:function(){Galaxy.libraries.library_router.back()}})}}})},render:function(h){this.options=_.defaults(this.options,h);var i=this.templateFolder();var j=this.folderContainer.attributes.metadata.full_path;var k;if(j.length===1){k=0}else{k=j[j.length-2][0]}this.$el.html(i({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:k,order:this.sort}));$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},postRender:function(){var h=this.folderContainer.attributes.metadata;h.contains_file=typeof this.collection.findWhere({type:"file"})!=="undefined";Galaxy.libraries.folderToolbarView.configureElements(h);$(".dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},addAll:function(h){_.each(h.reverse(),function(i){Galaxy.libraries.folderListView.collection.add(i)});$("#center [data-toggle]").tooltip();this.checkEmptiness();this.postRender()},renderAll:function(){var h=this;_.each(this.collection.models.reverse(),function(i){h.renderOne(i)});this.postRender()},renderOne:function(i){if(i.get("data_type")!=="folder"){this.options.contains_file=true}i.set("folder_id",this.id);var h=new a.FolderRowView(i);this.rowViews[i.get("id")]=h;this.$el.find("#first_folder_item").after(h.el);$(".dataset").hover(function(){$(this).find(".show_on_hover").show()},function(){$(this).find(".show_on_hover").hide()})},removeOne:function(h){this.$el.find("#"+h.id).remove()},checkEmptiness:function(){if((this.$el.find(".dataset_row").length===0)&&(this.$el.find(".folder_row").length===0)){this.$el.find(".empty-folder-message").show()}else{this.$el.find(".empty-folder-message").hide()}},sort_clicked:function(h){h.preventDefault();if(this.sort==="asc"){this.sortFolder("name","desc");this.sort="desc"}else{this.sortFolder("name","asc");this.sort="asc"}this.render();this.renderAll()},sortFolder:function(i,h){if(i==="name"){if(h==="asc"){return this.collection.sortByNameAsc()}else{if(h==="desc"){return this.collection.sortByNameDesc()}}}},selectAll:function(i){var h=i.target.checked;that=this;$(":checkbox","#folder_list_body").each(function(){this.checked=h;$row=$(this.parentElement.parentElement);if(h){that.makeDarkRow($row)}else{that.makeWhiteRow($row)}})},selectClickedRow:function(i){var k="";var h;var j;if(i.target.localName==="input"){k=i.target;h=$(i.target.parentElement.parentElement);j="input"}else{if(i.target.localName==="td"){k=$("#"+i.target.parentElement.id).find(":checkbox")[0];h=$(i.target.parentElement);j="td"}}if(k.checked){if(j==="td"){k.checked="";this.makeWhiteRow(h)}else{if(j==="input"){this.makeDarkRow(h)}}}else{if(j==="td"){k.checked="selected";this.makeDarkRow(h)}else{if(j==="input"){this.makeWhiteRow(h)}}}},makeDarkRow:function(h){h.removeClass("light").addClass("dark");h.find("a").removeClass("light").addClass("dark");h.find(".fa-file-o").removeClass("fa-file-o").addClass("fa-file")},makeWhiteRow:function(h){h.removeClass("dark").addClass("light");h.find("a").removeClass("dark").addClass("light");h.find(".fa-file").removeClass("fa-file").addClass("fa-file-o")},templateFolder:function(){var h=[];h.push('<ol class="breadcrumb">');h.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');h.push(" <% _.each(path, function(path_item) { %>");h.push(" <% if (path_item[0] != id) { %>");h.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');h.push("<% } else { %>");h.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');h.push(" <% } %>");h.push(" <% }); %>");h.push("</ol>");h.push('<table id="folder_table" class="grid table table-condensed">');h.push(" <thead>");h.push(' <th class="button_heading"></th>');h.push(' <th style="text-align: center; width: 20px; " title="Check to select all datasets"><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');h.push(' <th><a class="sort-folder-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');h.push(' <th style="width:5%;">data type</th>');h.push(' <th style="width:10%;">size</th>');h.push(' <th style="width:160px;">time updated (UTC)</th>');h.push(' <th style="width:10%;"></th> ');h.push(" </thead>");h.push(' <tbody id="folder_list_body">');h.push(' <tr id="first_folder_item">');h.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" <td></td>");h.push(" </tr>");h.push(" </tbody>");h.push("</table>");h.push('<div class="empty-folder-message" style="display:none;">This folder is either empty or you do not have proper access permissions to see the contents. If you expected something to show up please consult the <a href="https://wiki.galaxyproject.org/Admin/DataLibraries/LibrarySecurity">library security wikipage</a> or visit the <a href="https://biostar.usegalaxy.org/">Galaxy support site</a>.</div>');return _.template(h.join(""))}});return{FolderListView:b}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/mvc/library/library-folderrow-view.js
--- a/static/scripts/packed/mvc/library/library-folderrow-view.js
+++ b/static/scripts/packed/mvc/library/library-folderrow-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";if(f.get("deleted")){g=this.templateRowDeletedFile()}else{g=this.templateRowFile()}}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(){var i=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=i;var f=this;h.fetch({success:function(j){g.fetch({success:function(k){f.renderModalAfterFetch(j,k)},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error(k.responseJSON.err_msg)}else{e.error("An error occured during fetching histories:(")}f.renderModalAfterFetch(j)}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error(j.responseJSON.err_msg)}else{e.error("An error occured during loading dataset details :(")}}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:k.get("name"),body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}},closing_callback:function(){var l=Backbone.history.fragment.split("/datasets")[0];Galaxy.libraries.library_router.navigate("#"+l,{trigger:true,replace:true})}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var i=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=i;var g=$("#id_row").attr("data-id");var j=new c.HistoryItem();var h=this;j.url=j.urlRoot+i+"/contents";var f="/api/histories/"+i+"/set_as_current";$.ajax({url:f,type:"PUT"});j.save({content:g,source:"library"},{success:function(){e.success("Dataset imported. Click this to start analysing it.","",{onclick:function(){window.location="/"}});h.modal.enableButton("Import");h.modal.enableButton("Download")},error:function(l,k){if(typeof k.responseJSON!=="undefined"){e.error("Dataset not imported. "+k.responseJSON.err_msg)}else{e.error("An error occured! Dataset not imported. Please try again.")}h.modal.enableButton("Import");h.modal.enableButton("Download")}})},undelete_dataset:function(h){$(".tooltip").hide();var g=this;var f=$(h.target).closest("tr")[0].id;var i=Galaxy.libraries.folderListView.collection.get(f);i.url=i.urlRoot+i.id+"?undelete=true";i.destroy({success:function(k,j){Galaxy.libraries.folderListView.collection.remove(f);var l=new c.Item(j);Galaxy.libraries.folderListView.collection.add(l);e.success("Dataset undeleted. Click this to see it.","",{onclick:function(){g.showDatasetDetails()}})},error:function(k,j){if(typeof j.responseJSON!=="undefined"){e.error("Dataset was not undeleted. "+j.responseJSON.err_msg)}else{e.error("An error occured! Dataset was not undeleted. Please try again.")}}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td>");tmpl_array.push(' <% if (content_item.get("is_unrestricted")) { %><span data-toggle="tooltip" data-placement="top" title="Unrestricted dataset" style="color:grey;" class="fa fa-globe fa-lg"></span><% } %>');tmpl_array.push(' <% if (content_item.get("is_private")) { %><span data-toggle="tooltip" data-placement="top" title="Private dataset" style="color:grey;" class="fa fa-key fa-lg"></span><% } %>');tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-group fa-lg"></span>');tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none; margin-left:1em;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-dataset-view"],function(c,e,f,d,b){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .undelete_dataset_btn":"undelete_dataset"},options:{type:null},initialize:function(g){this.render(g)},render:function(g){var h=null;if(g.get("type")==="folder"){this.options.type="folder";h=this.templateRowFolder()}else{this.options.type="file";if(g.get("deleted")){h=this.templateRowDeletedFile()}else{h=this.templateRowFile()}}this.setElement(h({content_item:g}));this.$el.show();return this},showDatasetDetails:function(){this.dataset_view=new b.LibraryDatasetView({id:this.id})},undelete_dataset:function(i){$(".tooltip").hide();var h=this;var g=$(i.target).closest("tr")[0].id;var j=Galaxy.libraries.folderListView.collection.get(g);j.url=j.urlRoot+j.id+"?undelete=true";j.destroy({success:function(l,k){Galaxy.libraries.folderListView.collection.remove(g);var m=new d.Item(k);Galaxy.libraries.folderListView.collection.add(m);f.success("Dataset undeleted. Click this to see it.","",{onclick:function(){h.showDatasetDetails()}})},error:function(l,k){if(typeof k.responseJSON!=="undefined"){f.error("Dataset was not undeleted. "+k.responseJSON.err_msg)}else{f.error("An error occured! Dataset was not undeleted. Please try again.")}}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td></td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("file_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(" <td>");tmpl_array.push(' <% if (content_item.get("is_unrestricted")) { %><span data-toggle="tooltip" data-placement="top" title="Unrestricted dataset" style="color:grey;" class="fa fa-globe fa-lg"></span><% } %>');tmpl_array.push(' <% if (content_item.get("is_private")) { %><span data-toggle="tooltip" data-placement="top" title="Private dataset" style="color:grey;" class="fa fa-key fa-lg"></span><% } %>');tmpl_array.push(' <% if ((content_item.get("is_unrestricted") === false) && (content_item.get("is_private") === false)) { %><span data-toggle="tooltip" data-placement="top" title="Restricted dataset" style="color:grey;" class="fa fa-shield fa-lg"></span><% } %>');tmpl_array.push(' <% if (content_item.get("can_manage")) { %><a href="#folders/<%- content_item.get("folder_id") %>/datasets/<%- content_item.id %>/permissions"><button data-toggle="tooltip" data-placement="top" class="primary-button btn-xs permissions-dataset-btn show_on_hover" title="Manage permissions" style="display:none;"><span class="fa fa-group"></span></button></a><% } %>');tmpl_array.push(" </td>");tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowDeletedFile:function(){tmpl_array=[];tmpl_array.push('<tr class="active deleted_dataset dataset" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td style="color:grey;"><%- content_item.get("name") %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("file_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push(' <td><span data-toggle="tooltip" data-placement="top" title="Marked deleted" style="color:grey;" class="fa fa-ban fa-lg"></span><button data-toggle="tooltip" data-placement="top" title="Undelete <%- content_item.get("name") %>" class="primary-button btn-xs undelete_dataset_btn show_on_hover" type="button" style="display:none; margin-left:1em;"><span class="fa fa-unlock"> Undelete</span></button></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))}});return{FolderRowView:a}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/scripts/packed/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/packed/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/packed/mvc/library/library-foldertoolbar-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport","click .toolbtn_add_files":"addFilesToFolderModal","click #include_deleted_datasets_chk":"checkIncludeDeleted","click #toolbtn_bulk_delete":"deleteSelectedDatasets"},defaults:{can_add_library_item:false,contains_file:false,chain_call_control:{total_number:0,failed_number:0}},modal:null,histories:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(g){this.options=_.extend(this.options,g);var i=false;var f=true;if(Galaxy.currUser){i=Galaxy.currUser.isAdmin();f=Galaxy.currUser.isAnonymous()}var h=this.templateToolBar();this.$el.html(h({id:this.options.id,admin_user:i,anonym:f}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$(".add-library-items").show()}else{$(".add-library-items").hide()}if(this.options.contains_file===true){if(Galaxy.currUser){if(!Galaxy.currUser.isAnonymous()){$(".logged-dataset-manipulation").show();$(".dataset-manipulation").show()}else{$(".dataset-manipulation").show();$(".logged-dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){Galaxy.modal.hide()}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var g=new c.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];g.url=g.urlRoot+"/"+current_folder_id;g.save(f,{success:function(h){Galaxy.modal.hide();e.success("Folder created");h.set({type:"folder"});Galaxy.libraries.folderListView.collection.add(h)},error:function(i,h){Galaxy.modal.hide();if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{this.refreshUserHistoriesList(function(g){var h=g.templateBulkImportInModal();g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:h({histories:g.histories.models}),buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})}},refreshUserHistoriesList:function(g){var f=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){g(f)},error:function(i,h){if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})},importAllIntoHistory:function(){this.modal.disableButton("Import");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var k=$("select[name=dataset_import_bulk] option:selected").val();this.options.last_used_history_id=k;var n=$("select[name=dataset_import_bulk] option:selected").text();var p=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){p.push(this.parentElement.parentElement.id)}});var o=this.templateImportIntoHistoryProgressBar();this.modal.$el.find(".modal-body").html(o({history_name:n}));var l=100/p.length;this.initProgress(l);var f=[];for(var h=p.length-1;h>=0;h--){var j=p[h];var m=new c.HistoryItem();m.url=m.urlRoot+k+"/contents";m.content=j;m.source="library";f.push(m)}this.options.chain_call_control.total_number=f.length;var g="/api/histories/"+k+"/set_as_current";$.ajax({url:g,type:"PUT"});this.chainCall(f,n)},chainCall:function(g,j){var f=this;var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets imported into history. Click this to start analysing it.","",{onclick:function(){window.location="/"}})}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were imported into history.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be imported into history. Click this to see what was imported.","",{onclick:function(){window.location="/"}})}}}Galaxy.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source}));i.done(function(){f.updateProgress();f.chainCall(g,j)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCall(g,j)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h==="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},addFilesToFolderModal:function(){this.refreshUserHistoriesList(function(f){f.modal=Galaxy.modal;var g=f.templateAddFilesInModal();f.modal.show({closing_events:true,title:"Add datasets from history to "+f.options.folder_name,body:g({histories:f.histories.models}),buttons:{Add:function(){f.addAllDatasetsFromHistory()},Close:function(){Galaxy.modal.hide()}}});if(f.histories.models.length>0){f.fetchAndDisplayHistoryContents(f.histories.models[0].id);$("#dataset_add_bulk").change(function(h){f.fetchAndDisplayHistoryContents(h.target.value)})}else{e.error("An error ocurred :(")}})},fetchAndDisplayHistoryContents:function(h){var g=new c.HistoryContents({id:h});var f=this;g.fetch({success:function(j){var i=f.templateHistoryContents();f.histories.get(h).set({contents:j});f.modal.$el.find("#selected_history_content").html(i({history_contents:j.models.reverse()}))},error:function(){e.error("An error ocurred :(")}})},addAllDatasetsFromHistory:function(){this.modal.disableButton("Add");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var f=[];this.modal.$el.find("#selected_history_content").find(":checked").each(function(){var i=$(this.parentElement).data("id");if(i){f.push(i)}});var l=this.options.folder_name;var k=this.templateAddingDatasetsProgressBar();this.modal.$el.find(".modal-body").html(k({folder_name:l}));this.progressStep=100/f.length;this.progress=0;var j=[];for(var h=f.length-1;h>=0;h--){history_dataset_id=f[h];var g=new c.Item();g.url="/api/folders/"+this.options.id+"/contents";g.set({from_hda_id:history_dataset_id});j.push(g)}this.options.chain_call_control.total_number=j.length;this.chainCallAddingHdas(j)},chainCallAddingHdas:function(g){var f=this;this.added_hdas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets from history added to the folder")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were added to the folder.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be added to the folder")}}}Galaxy.modal.hide();return this.added_hdas}var i=$.when(h.save({from_hda_id:h.get("from_hda_id")}));i.done(function(j){Galaxy.libraries.folderListView.collection.add(j);f.updateProgress();f.chainCallAddingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallAddingHdas(g)})},checkIncludeDeleted:function(f){if(f.target.checked){Galaxy.libraries.folderListView.fetchFolder({include_deleted:true})}else{Galaxy.libraries.folderListView.fetchFolder({include_deleted:false})}},deleteSelectedDatasets:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{var j=this.templateDeletingDatasetsProgressBar();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Deleting selected datasets",body:j({}),buttons:{Close:function(){Galaxy.modal.hide()}}});this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var g=[];f.each(function(){if(this.parentElement.parentElement.id!==""){g.push(this.parentElement.parentElement.id)}});this.progressStep=100/g.length;this.progress=0;var l=[];for(var h=g.length-1;h>=0;h--){var k=new c.Item({id:g[h]});l.push(k)}this.options.chain_call_control.total_number=g.length;this.chainCallDeletingHdas(l)}},chainCallDeletingHdas:function(g){var f=this;this.deleted_lddas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets deleted")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were deleted.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be deleted")}}}Galaxy.modal.hide();return this.deleted_lddas}var i=$.when(h.destroy());i.done(function(k){Galaxy.libraries.folderListView.collection.remove(h.id);f.updateProgress();if(Galaxy.libraries.folderListView.options.include_deleted){var j=new c.Item(k);Galaxy.libraries.folderListView.collection.add(j)}f.chainCallDeletingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallDeletingHdas(g)})},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push('<div id="library_folder_toolbar">');tmpl_array.push('<span data-toggle="tooltip" data-placement="top" class="logged-dataset-manipulation" title="Include deleted datasets" style="display:none;"><input id="include_deleted_datasets_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push('<div class="btn-group add-library-items" style="display:none;">');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');tmpl_array.push("</div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button dataset-manipulation" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to history</button>');tmpl_array.push(' <div id="toolbtn_dl" class="btn-group dataset-manipulation" style="margin-left: 0.5em; display:none; ">');tmpl_array.push(' <button title="Download selected datasets as archive" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');tmpl_array.push(" </button>");tmpl_array.push(' <ul class="dropdown-menu" role="menu">');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');tmpl_array.push(" </ul>");tmpl_array.push(" </div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Mark selected datasets deleted" id="toolbtn_bulk_delete" class="primary-button logged-dataset-manipulation" style="margin-left: 0.5em; display:none; " type="button"><span class="fa fa-times"></span> delete</button>');tmpl_array.push(" </div>");tmpl_array.push(' <div id="folder_items_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_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("</form>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return _.template(f.join(""))},templateImportIntoHistoryProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Adding selected datasets from history to library folder <b><%= _.escape(folder_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateDeletingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-delete" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddFilesInModal:function(){var f=[];f.push('<div id="add_files_modal">');f.push('<div id="history_modal_combo_bulk">');f.push("Select history: ");f.push('<select id="dataset_add_bulk" name="dataset_add_bulk" style="width:66%; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</div>");f.push('<div id="selected_history_content">');f.push("</div>");f.push("</div>");return _.template(f.join(""))},templateHistoryContents:function(){var f=[];f.push("Choose the datasets to import:");f.push("<ul>");f.push(" <% _.each(history_contents, function(history_item) { %>");f.push(' <li data-id="<%= _.escape(history_item.get("id")) %>">');f.push(' <input style="margin: 0;" type="checkbox"><%= _.escape(history_item.get("hid")) %>: <%= _.escape(history_item.get("name")) %>');f.push(" </li>");f.push(" <% }); %>");f.push("</ul>");return _.template(f.join(""))}});return{FolderToolbarView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport","click .toolbtn_add_files":"addFilesToFolderModal","click #include_deleted_datasets_chk":"checkIncludeDeleted","click #toolbtn_bulk_delete":"deleteSelectedDatasets"},defaults:{can_add_library_item:false,contains_file:false,chain_call_control:{total_number:0,failed_number:0}},modal:null,histories:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(g){this.options=_.extend(this.options,g);var i=false;var f=true;if(Galaxy.currUser){i=Galaxy.currUser.isAdmin();f=Galaxy.currUser.isAnonymous()}var h=this.templateToolBar();this.$el.html(h({id:this.options.id,admin_user:i,anonym:f}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$(".add-library-items").show()}else{$(".add-library-items").hide()}if(this.options.contains_file===true){if(Galaxy.currUser){if(!Galaxy.currUser.isAnonymous()){$(".logged-dataset-manipulation").show();$(".dataset-manipulation").show()}else{$(".dataset-manipulation").show();$(".logged-dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}}else{$(".logged-dataset-manipulation").hide();$(".dataset-manipulation").hide()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){Galaxy.modal.hide()}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var g=new c.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];g.url=g.urlRoot+"/"+current_folder_id;g.save(f,{success:function(h){Galaxy.modal.hide();e.success("Folder created");h.set({type:"folder"});Galaxy.libraries.folderListView.collection.add(h)},error:function(i,h){Galaxy.modal.hide();if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{this.refreshUserHistoriesList(function(g){var h=g.templateBulkImportInModal();g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:h({histories:g.histories.models}),buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})}},refreshUserHistoriesList:function(g){var f=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){g(f)},error:function(i,h){if(typeof h.responseJSON!=="undefined"){e.error(h.responseJSON.err_msg)}else{e.error("An error ocurred :(")}}})},importAllIntoHistory:function(){this.modal.disableButton("Import");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var k=$("select[name=dataset_import_bulk] option:selected").val();this.options.last_used_history_id=k;var n=$("select[name=dataset_import_bulk] option:selected").text();var p=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){p.push(this.parentElement.parentElement.id)}});var o=this.templateImportIntoHistoryProgressBar();this.modal.$el.find(".modal-body").html(o({history_name:n}));var l=100/p.length;this.initProgress(l);var f=[];for(var h=p.length-1;h>=0;h--){var j=p[h];var m=new c.HistoryItem();m.url=m.urlRoot+k+"/contents";m.content=j;m.source="library";f.push(m)}this.options.chain_call_control.total_number=f.length;var g="/api/histories/"+k+"/set_as_current";$.ajax({url:g,type:"PUT"});this.chainCall(f,n)},chainCall:function(g,j){var f=this;var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets imported into history. Click this to start analysing it.","",{onclick:function(){window.location="/"}})}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were imported into history.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be imported into history. Click this to see what was imported.","",{onclick:function(){window.location="/"}})}}}Galaxy.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source}));i.done(function(){f.updateProgress();f.chainCall(g,j)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCall(g,j)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h==="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},addFilesToFolderModal:function(){this.refreshUserHistoriesList(function(f){f.modal=Galaxy.modal;var g=f.templateAddFilesInModal();f.modal.show({closing_events:true,title:"Add datasets from history to "+f.options.folder_name,body:g({histories:f.histories.models}),buttons:{Add:function(){f.addAllDatasetsFromHistory()},Close:function(){Galaxy.modal.hide()}}});if(f.histories.models.length>0){f.fetchAndDisplayHistoryContents(f.histories.models[0].id);$("#dataset_add_bulk").change(function(h){f.fetchAndDisplayHistoryContents(h.target.value)})}else{e.error("An error ocurred :(")}})},fetchAndDisplayHistoryContents:function(h){var g=new c.HistoryContents({id:h});var f=this;g.fetch({success:function(j){var i=f.templateHistoryContents();f.histories.get(h).set({contents:j});f.modal.$el.find("#selected_history_content").html(i({history_contents:j.models.reverse()}))},error:function(){e.error("An error ocurred :(")}})},addAllDatasetsFromHistory:function(){this.modal.disableButton("Add");this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var f=[];this.modal.$el.find("#selected_history_content").find(":checked").each(function(){var i=$(this.parentElement).data("id");if(i){f.push(i)}});var l=this.options.folder_name;var k=this.templateAddingDatasetsProgressBar();this.modal.$el.find(".modal-body").html(k({folder_name:l}));this.progressStep=100/f.length;this.progress=0;var j=[];for(var h=f.length-1;h>=0;h--){history_dataset_id=f[h];var g=new c.Item();g.url="/api/folders/"+this.options.id+"/contents";g.set({from_hda_id:history_dataset_id});j.push(g)}this.options.chain_call_control.total_number=j.length;this.chainCallAddingHdas(j)},chainCallAddingHdas:function(g){var f=this;this.added_hdas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets from history added to the folder")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were added to the folder.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be added to the folder")}}}Galaxy.modal.hide();return this.added_hdas}var i=$.when(h.save({from_hda_id:h.get("from_hda_id")}));i.done(function(j){Galaxy.libraries.folderListView.collection.add(j);f.updateProgress();f.chainCallAddingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallAddingHdas(g)})},checkIncludeDeleted:function(f){if(f.target.checked){Galaxy.libraries.folderListView.fetchFolder({include_deleted:true})}else{Galaxy.libraries.folderListView.fetchFolder({include_deleted:false})}},deleteSelectedDatasets:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{var j=this.templateDeletingDatasetsProgressBar();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Deleting selected datasets",body:j({}),buttons:{Close:function(){Galaxy.modal.hide()}}});this.options.chain_call_control.total_number=0;this.options.chain_call_control.failed_number=0;var g=[];f.each(function(){if(this.parentElement.parentElement.id!==""){g.push(this.parentElement.parentElement.id)}});this.progressStep=100/g.length;this.progress=0;var l=[];for(var h=g.length-1;h>=0;h--){var k=new c.Item({id:g[h]});l.push(k)}this.options.chain_call_control.total_number=g.length;this.chainCallDeletingHdas(l)}},chainCallDeletingHdas:function(g){var f=this;this.deleted_lddas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){if(this.options.chain_call_control.failed_number===0){e.success("Selected datasets deleted")}else{if(this.options.chain_call_control.failed_number===this.options.chain_call_control.total_number){e.error("There was an error and no datasets were deleted.")}else{if(this.options.chain_call_control.failed_number<this.options.chain_call_control.total_number){e.warning("Some of the datasets could not be deleted")}}}Galaxy.modal.hide();return this.deleted_lddas}var i=$.when(h.destroy());i.done(function(k){Galaxy.libraries.folderListView.collection.remove(h.id);f.updateProgress();if(Galaxy.libraries.folderListView.options.include_deleted){var j=new c.Item(k);Galaxy.libraries.folderListView.collection.add(j)}f.chainCallDeletingHdas(g)}).fail(function(){f.options.chain_call_control.failed_number+=1;f.updateProgress();f.chainCallDeletingHdas(g)})},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push('<div id="library_toolbar">');tmpl_array.push('<span data-toggle="tooltip" data-placement="top" class="logged-dataset-manipulation" title="Include deleted datasets" style="display:none;"><input id="include_deleted_datasets_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push('<div class="btn-group add-library-items" style="display:none;">');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');tmpl_array.push("</div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button dataset-manipulation" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to History</button>');tmpl_array.push(' <div id="toolbtn_dl" class="btn-group dataset-manipulation" style="margin-left: 0.5em; display:none; ">');tmpl_array.push(' <button title="Download selected datasets as archive" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');tmpl_array.push(' <span class="fa fa-download"></span> Download <span class="caret"></span>');tmpl_array.push(" </button>");tmpl_array.push(' <ul class="dropdown-menu" role="menu">');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');tmpl_array.push(" </ul>");tmpl_array.push(" </div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Mark selected datasets deleted" id="toolbtn_bulk_delete" class="primary-button logged-dataset-manipulation" style="margin-left: 0.5em; display:none; " type="button"><span class="fa fa-times"></span> Delete</button>');tmpl_array.push(" </div>");tmpl_array.push(' <div id="folder_items_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_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("</form>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return _.template(f.join(""))},templateImportIntoHistoryProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Adding selected datasets from history to library folder <b><%= _.escape(folder_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateDeletingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-delete" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddFilesInModal:function(){var f=[];f.push('<div id="add_files_modal">');f.push('<div id="history_modal_combo_bulk">');f.push("Select history: ");f.push('<select id="dataset_add_bulk" name="dataset_add_bulk" style="width:66%; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</div>");f.push('<div id="selected_history_content">');f.push("</div>");f.push("</div>");return _.template(f.join(""))},templateHistoryContents:function(){var f=[];f.push("Choose the datasets to import:");f.push("<ul>");f.push(" <% _.each(history_contents, function(history_item) { %>");f.push(' <li data-id="<%= _.escape(history_item.get("id")) %>">');f.push(' <input style="margin: 0;" type="checkbox"><%= _.escape(history_item.get("hid")) %>: <%= _.escape(history_item.get("name")) %>');f.push(" </li>");f.push(" <% }); %>");f.push("</ul>");return _.template(f.join(""))}});return{FolderToolbarView:a}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 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(["libs/toastr","mvc/library/library-model"],function(b,a){var c=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},render:function(){var f=this.templateToolBar();var e=false;var d=true;if(Galaxy.currUser){e=Galaxy.currUser.isAdmin();d=Galaxy.currUser.isAnonymous()}this.$el.html(f({admin_user:e,anon_user:d}));if(e){this.$el.find("#include_deleted_chk")[0].checked=Galaxy.libraries.preferences.get("with_deleted")}},show_library_modal:function(e){e.preventDefault();e.stopPropagation();var d=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){d.create_new_library_event()},Close:function(){d.modal.hide()}}})},create_new_library_event:function(){var f=this.serialize_new_library();if(this.validate_new_library(f)){var e=new a.Library();var d=this;e.save(f,{success:function(g){Galaxy.libraries.libraryListView.collection.add(g);d.modal.hide();d.clear_library_modal();Galaxy.libraries.libraryListView.render();b.success("Library created")},error:function(h,g){if(typeof g.responseJSON!=="undefined"){b.error(g.responseJSON.err_msg)}else{b.error("An error occured :(")}}})}else{b.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(d){return d.name!==""},check_include_deleted:function(d){if(d.target.checked){Galaxy.libraries.preferences.set({with_deleted:true});Galaxy.libraries.libraryListView.render()}else{Galaxy.libraries.preferences.set({with_deleted:false});Galaxy.libraries.libraryListView.render()}},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push(' <div id="toolbar_form" margin-top:0.5em; ">');tmpl_array.push(" <% if(admin_user === true) { %>");tmpl_array.push(' <div id="library_toolbar">');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Include deleted libraries"><input id="include_deleted_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Create New Library"><button id="create_new_library_btn" class="primary-button btn-xs" type="button"><span class="fa fa-plus"></span> New Library</button><span>');tmpl_array.push(" </div>");tmpl_array.push(" <% } %>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="libraries_element">');tmpl_array.push(" </div>");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("")}});return{LibraryToolbarView:c}});
\ No newline at end of file
+define(["libs/toastr","mvc/library/library-model"],function(b,a){var c=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal","click #include_deleted_chk":"check_include_deleted"},initialize:function(){this.render()},render:function(){var f=this.templateToolBar();var e=false;var d=true;if(Galaxy.currUser){e=Galaxy.currUser.isAdmin();d=Galaxy.currUser.isAnonymous()}this.$el.html(f({admin_user:e,anon_user:d}));if(e){this.$el.find("#include_deleted_chk")[0].checked=Galaxy.libraries.preferences.get("with_deleted")}},show_library_modal:function(e){e.preventDefault();e.stopPropagation();var d=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){d.create_new_library_event()},Close:function(){d.modal.hide()}}})},create_new_library_event:function(){var f=this.serialize_new_library();if(this.validate_new_library(f)){var e=new a.Library();var d=this;e.save(f,{success:function(g){Galaxy.libraries.libraryListView.collection.add(g);d.modal.hide();d.clear_library_modal();Galaxy.libraries.libraryListView.render();b.success("Library created")},error:function(h,g){if(typeof g.responseJSON!=="undefined"){b.error(g.responseJSON.err_msg)}else{b.error("An error occured :(")}}})}else{b.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(d){return d.name!==""},check_include_deleted:function(d){if(d.target.checked){Galaxy.libraries.preferences.set({with_deleted:true});Galaxy.libraries.libraryListView.render()}else{Galaxy.libraries.preferences.set({with_deleted:false});Galaxy.libraries.libraryListView.render()}},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push(' <div id="toolbar_form">');tmpl_array.push(" <% if(admin_user === true) { %>");tmpl_array.push(' <div id="library_toolbar">');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Include deleted libraries"><input id="include_deleted_chk" style="margin: 0;" type="checkbox"><span class="fa fa-trash-o fa-lg"></span></input></span>');tmpl_array.push(' <span data-toggle="tooltip" data-placement="top" title="Create New Library"><button id="create_new_library_btn" class="primary-button btn-xs" type="button"><span class="fa fa-plus"></span> New Library</button><span>');tmpl_array.push(" </div>");tmpl_array.push(" <% } %>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="libraries_element">');tmpl_array.push(" </div>");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("")}});return{LibraryToolbarView:c}});
\ No newline at end of file
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/style/blue/base.css
--- a/static/style/blue/base.css
+++ b/static/style/blue/base.css
@@ -1305,18 +1305,21 @@
tr.dark td{background-color:#d6b161;color:white}
tr.dark:hover td{background-color:#ebd4a4;color:white}
a.dark{color:white}
-.modal_table tr{border-bottom:1px solid #5f6990 !important}
-.modal_table th{border:none !important}
-.modal_table td{border:none !important}
+.dataset_table tr{border-bottom:1px solid #5f6990 !important}
+.dataset_table th{border:none !important}
+.dataset_table td{border:none !important}
th.button_heading{width:2em}
-#library_folder_toolbar{margin-bottom:1em}#library_folder_toolbar span{margin-right:0.2em}
+.bigdrop.select2-container .select2-results{max-height:300px}
+.bigdrop .select2-results{max-height:300px}
+.select2-container-multi{width:100%}
+.roles-selection{width:66%}
#library_toolbar{margin-bottom:1em}#library_toolbar span{margin-right:0.2em}
img.expanderIcon{padding-right:4px}
input.datasetCheckbox,li,ul{padding:0;margin:0}
.rowTitle{padding:2px}
ul{list-style:none}
.libraryTitle th{text-align:left}
-pre.peek{background:white;color:black;width:100%;overflow:auto}
+pre.peek{background:white;color:black;overflow:auto}
pre.peek th{color:white;background:#ebd9b2}
span.expandLink{padding-left:12px;display:inline-block;vertical-align:middle;background:url(../images/silk/resultset_next.png) no-repeat}
.folderRow.expanded span.expandLink{background:url(../images/silk/resultset_bottom.png) no-repeat}
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/style/blue/library.css
--- a/static/style/blue/library.css
+++ b/static/style/blue/library.css
@@ -16,18 +16,21 @@
tr.dark td{background-color:#d6b161;color:white}
tr.dark:hover td{background-color:#ebd4a4;color:white}
a.dark{color:white}
-.modal_table tr{border-bottom:1px solid #5f6990 !important}
-.modal_table th{border:none !important}
-.modal_table td{border:none !important}
+.dataset_table tr{border-bottom:1px solid #5f6990 !important}
+.dataset_table th{border:none !important}
+.dataset_table td{border:none !important}
th.button_heading{width:2em}
-#library_folder_toolbar{margin-bottom:1em}#library_folder_toolbar span{margin-right:0.2em}
+.bigdrop.select2-container .select2-results{max-height:300px}
+.bigdrop .select2-results{max-height:300px}
+.select2-container-multi{width:100%}
+.roles-selection{width:66%}
#library_toolbar{margin-bottom:1em}#library_toolbar span{margin-right:0.2em}
img.expanderIcon{padding-right:4px}
input.datasetCheckbox,li,ul{padding:0;margin:0}
.rowTitle{padding:2px}
ul{list-style:none}
.libraryTitle th{text-align:left}
-pre.peek{background:white;color:black;width:100%;overflow:auto}
+pre.peek{background:white;color:black;overflow:auto}
pre.peek th{color:white;background:#ebd9b2}
span.expandLink{padding-left:12px;display:inline-block;vertical-align:middle;background:url(../images/silk/resultset_next.png) no-repeat}
.folderRow.expanded span.expandLink{background:url(../images/silk/resultset_bottom.png) no-repeat}
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 static/style/src/less/library.less
--- a/static/style/src/less/library.less
+++ b/static/style/src/less/library.less
@@ -80,7 +80,7 @@
color: white;
}
-.modal_table{
+.dataset_table{
tr {
border-bottom: 1px solid #5f6990 !important;
}
@@ -97,12 +97,19 @@
width: 2em;
}
-#library_folder_toolbar {
- margin-bottom: 1em;
- span {
- margin-right: 0.2em;
- }
+.bigdrop.select2-container .select2-results {
+ max-height: 300px;
}
+.bigdrop .select2-results {
+ max-height: 300px;
+}
+.select2-container-multi{
+ width: 100%;
+}
+.roles-selection {
+ width: 66%;
+}
+
#library_toolbar {
margin-bottom: 1em;
span {
@@ -135,7 +142,7 @@
pre.peek {
background: white;
color: black;
- width: 100%;
+ // width: 100%;
overflow: auto;
}
diff -r b027397c99c639d5b200b88649c6e7ca75a292f8 -r 23bb24573f1370b4f6322651d471d11ff5352447 templates/webapps/galaxy/galaxy.panels.mako
--- a/templates/webapps/galaxy/galaxy.panels.mako
+++ b/templates/webapps/galaxy/galaxy.panels.mako
@@ -31,6 +31,7 @@
${h.js(
'libs/jquery/jquery',
'libs/jquery/jquery-ui',
+ "libs/jquery/select2",
'libs/bootstrap',
'libs/underscore',
'libs/backbone/backbone',
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: extended ui-select module to support multiple inputs and on-demand ajax loading of paginated data
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b027397c99c6/
Changeset: b027397c99c6
User: martenson
Date: 2014-05-14 19:50:15
Summary: extended ui-select module to support multiple inputs and on-demand ajax loading of paginated data
Affected #: 2 files
diff -r 882f51a4d9dced2ce731c5b4afa5bed9623933c2 -r b027397c99c639d5b200b88649c6e7ca75a292f8 static/scripts/mvc/ui/ui-select.js
--- a/static/scripts/mvc/ui/ui-select.js
+++ b/static/scripts/mvc/ui/ui-select.js
@@ -11,10 +11,13 @@
{
// options
optionsDefault: {
- css : '',
- placeholder : 'No data available',
- data : [],
- value : null
+ css : '',
+ placeholder : 'No data available',
+ data : [],
+ value : null,
+ multiple : false,
+ minimumInputLength : 0,
+ initialData : ''
},
// initialize
@@ -40,17 +43,19 @@
// refresh
this._refresh();
- // initial value
- if (this.options.value) {
- this._setValue(this.options.value);
- }
-
- // add change event
- var self = this;
- if (this.options.onchange) {
- this.$el.on('change', function() {
- self.options.onchange(self.value());
- });
+ if (!this.options.multiple){
+ // initial value
+ if (this.options.value) {
+ this._setValue(this.options.value);
+ }
+
+ // add change event
+ var self = this;
+ if (this.options.onchange) {
+ this.$el.on('change', function() {
+ self.options.onchange(self.value());
+ });
+ }
}
},
@@ -142,18 +147,33 @@
// refresh
_refresh: function() {
- // selected
- var selected = this._getValue();
-
- // add select2 data
- this.$el.select2({
- data : this.select_data,
- containerCssClass : this.options.css,
- placeholder : this.options.placeholder
- });
-
- // select previous value (if exists)
- this._setValue(selected);
+ // add select2 data based on type of input
+ if (!this.options.multiple){
+ var selected = this._getValue();
+ var select_opt = {
+ data : this.select_data,
+ containerCssClass : this.options.css,
+ placeholder : this.options.placeholder,
+ };
+ this.$el.select2(select_opt);
+ // select previous value (if exists)
+ this._setValue(selected);
+ } else {
+ var select_opt = {
+ multiple : this.options.multiple,
+ containerCssClass : this.options.css,
+ placeholder : this.options.placeholder,
+ minimumInputLength : this.options.minimumInputLength,
+ ajax : this.options.ajax,
+ dropdownCssClass : this.options.dropdownCssClass,
+ escapeMarkup : this.options.escapeMarkup,
+ formatResult : this.options.formatResult,
+ formatSelection : this.options.formatSelection,
+ initSelection : this.options.initSelection,
+ initialData : this.options.initialData
+ };
+ this.$el.select2(select_opt);
+ }
},
// get index
@@ -186,8 +206,8 @@
},
// element
- _template: function() {
- return '<input type="hidden"/>';
+ _template: function(options) {
+ return '<input type="hidden" value="' + this.options.initialData + '"/>';
}
});
diff -r 882f51a4d9dced2ce731c5b4afa5bed9623933c2 -r b027397c99c639d5b200b88649c6e7ca75a292f8 static/scripts/packed/mvc/ui/ui-select.js
--- a/static/scripts/packed/mvc/ui/ui-select.js
+++ b/static/scripts/packed/mvc/ui/ui-select.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{css:"",placeholder:"No data available",data:[],value:null},initialize:function(d){this.options=a.merge(d,this.optionsDefault);this.setElement(this._template(this.options));if(!this.options.container){console.log("ui-select::initialize() : container not specified.");return}this.options.container.append(this.$el);this.select_data=this.options.data;this._refresh();if(this.options.value){this._setValue(this.options.value)}var c=this;if(this.options.onchange){this.$el.on("change",function(){c.options.onchange(c.value())})}},value:function(c){var d=this._getValue();if(c!==undefined){this._setValue(c)}var e=this._getValue();if((e!=d&&this.options.onchange)){this.options.onchange(e)}return e},text:function(){return this.$el.select2("data").text},disabled:function(){return !this.$el.select2("enable")},enable:function(){this.$el.select2("enable",true)},disable:function(){this.$el.select2("enable",false)},add:function(c){this.select_data.push({id:c.id,text:c.text});this._refresh()},del:function(d){var c=this._getIndex(d);if(c!=-1){this.select_data.splice(c,1);this._refresh()}},remove:function(){this.$el.select2("destroy")},update:function(c){this.select_data=[];for(var d in c.data){this.select_data.push(c.data[d])}this._refresh()},_refresh:function(){var c=this._getValue();this.$el.select2({data:this.select_data,containerCssClass:this.options.css,placeholder:this.options.placeholder});this._setValue(c)},_getIndex:function(d){for(var c in this.select_data){if(this.select_data[c].id==d){return c}}return -1},_getValue:function(){return this.$el.select2("val")},_setValue:function(d){var c=this._getIndex(d);if(c==-1){if(this.select_data.length>0){d=this.select_data[0].id}}this.$el.select2("val",d)},_template:function(){return'<input type="hidden"/>'}});return{View:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({optionsDefault:{css:"",placeholder:"No data available",data:[],value:null,multiple:false,minimumInputLength:0,initialData:""},initialize:function(d){this.options=a.merge(d,this.optionsDefault);this.setElement(this._template(this.options));if(!this.options.container){console.log("ui-select::initialize() : container not specified.");return}this.options.container.append(this.$el);this.select_data=this.options.data;this._refresh();if(!this.options.multiple){if(this.options.value){this._setValue(this.options.value)}var c=this;if(this.options.onchange){this.$el.on("change",function(){c.options.onchange(c.value())})}}},value:function(c){var d=this._getValue();if(c!==undefined){this._setValue(c)}var e=this._getValue();if((e!=d&&this.options.onchange)){this.options.onchange(e)}return e},text:function(){return this.$el.select2("data").text},disabled:function(){return !this.$el.select2("enable")},enable:function(){this.$el.select2("enable",true)},disable:function(){this.$el.select2("enable",false)},add:function(c){this.select_data.push({id:c.id,text:c.text});this._refresh()},del:function(d){var c=this._getIndex(d);if(c!=-1){this.select_data.splice(c,1);this._refresh()}},remove:function(){this.$el.select2("destroy")},update:function(c){this.select_data=[];for(var d in c.data){this.select_data.push(c.data[d])}this._refresh()},_refresh:function(){if(!this.options.multiple){var d=this._getValue();var c={data:this.select_data,containerCssClass:this.options.css,placeholder:this.options.placeholder,};this.$el.select2(c);this._setValue(d)}else{var c={multiple:this.options.multiple,containerCssClass:this.options.css,placeholder:this.options.placeholder,minimumInputLength:this.options.minimumInputLength,ajax:this.options.ajax,dropdownCssClass:this.options.dropdownCssClass,escapeMarkup:this.options.escapeMarkup,formatResult:this.options.formatResult,formatSelection:this.options.formatSelection,initSelection:this.options.initSelection,initialData:this.options.initialData};this.$el.select2(c)}},_getIndex:function(d){for(var c in this.select_data){if(this.select_data[c].id==d){return c}}return -1},_getValue:function(){return this.$el.select2("val")},_setValue:function(d){var c=this._getIndex(d);if(c==-1){if(this.select_data.length>0){d=this.select_data[0].id}}this.$el.select2("val",d)},_template:function(c){return'<input type="hidden" value="'+this.options.initialData+'"/>'}});return{View:b}});
\ 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: dan: Fix for when hours_between_check is defined in ini.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/882f51a4d9dc/
Changeset: 882f51a4d9dc
User: dan
Date: 2014-05-14 18:04:47
Summary: Fix for when hours_between_check is defined in ini.
Affected #: 1 file
diff -r 8b8b08da7231d3ea2bf7ccb6585a20f7e0c64cad -r 882f51a4d9dced2ce731c5b4afa5bed9623933c2 lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -108,6 +108,8 @@
self.manage_dependency_relationships = string_as_bool( kwargs.get( 'manage_dependency_relationships', False ) )
self.running_functional_tests = string_as_bool( kwargs.get( 'running_functional_tests', False ) )
self.hours_between_check = kwargs.get( 'hours_between_check', 12 )
+ if isinstance( self.hours_between_check, basestring ):
+ self.hours_between_check = float( self.hours_between_check )
try:
if isinstance( self.hours_between_check, int ):
if self.hours_between_check < 1 or self.hours_between_check > 24:
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: dan: Allow for an arbitrary number of tool_data_table_config_path files to be defined in ini file. Values are comma separated.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8b8b08da7231/
Changeset: 8b8b08da7231
User: dan
Date: 2014-05-14 17:52:20
Summary: Allow for an arbitrary number of tool_data_table_config_path files to be defined in ini file. Values are comma separated.
Affected #: 2 files
diff -r 6b86b4186c455317cba726c7ad6579a030922421 -r 8b8b08da7231d3ea2bf7ccb6585a20f7e0c64cad lib/galaxy/config.py
--- a/lib/galaxy/config.py
+++ b/lib/galaxy/config.py
@@ -102,7 +102,7 @@
self.shed_tool_data_path = resolve_path( self.shed_tool_data_path, self.root )
else:
self.shed_tool_data_path = self.tool_data_path
- self.tool_data_table_config_path = resolve_path( kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ), self.root )
+ self.tool_data_table_config_path = [ resolve_path( x, self.root ) for x in kwargs.get( 'tool_data_table_config_path', 'tool_data_table_conf.xml' ).split( ',' ) ]
self.shed_tool_data_table_config = resolve_path( kwargs.get( 'shed_tool_data_table_config', 'shed_tool_data_table_conf.xml' ), self.root )
self.enable_tool_shed_check = string_as_bool( kwargs.get( 'enable_tool_shed_check', False ) )
self.manage_dependency_relationships = string_as_bool( kwargs.get( 'manage_dependency_relationships', False ) )
diff -r 6b86b4186c455317cba726c7ad6579a030922421 -r 8b8b08da7231d3ea2bf7ccb6585a20f7e0c64cad lib/galaxy/tools/data/__init__.py
--- a/lib/galaxy/tools/data/__init__.py
+++ b/lib/galaxy/tools/data/__init__.py
@@ -56,19 +56,22 @@
3. When a tool shed repository that includes a tool_data_table_conf.xml.sample file is being installed into a local
Galaxy instance. In this case, we have 2 entry types to handle, files whose root tag is <tables>, for example:
"""
- tree = util.parse_xml( config_filename )
- root = tree.getroot()
table_elems = []
- for table_elem in root.findall( 'table' ):
- table = ToolDataTable.from_elem( table_elem, tool_data_path, from_shed_config )
- table_elems.append( table_elem )
- if table.name not in self.data_tables:
- self.data_tables[ table.name ] = table
- log.debug( "Loaded tool data table '%s'", table.name )
- else:
- log.debug( "Loading another instance of data table '%s', attempting to merge content.", table.name )
- self.data_tables[ table.name ].merge_tool_data_table( table, allow_duplicates=False ) #only merge content, do not persist to disk, do not allow duplicate rows when merging
- # FIXME: This does not account for an entry with the same unique build ID, but a different path.
+ if not isinstance( config_filename, list ):
+ config_filename = [ config_filename ]
+ for filename in config_filename:
+ tree = util.parse_xml( filename )
+ root = tree.getroot()
+ for table_elem in root.findall( 'table' ):
+ table = ToolDataTable.from_elem( table_elem, tool_data_path, from_shed_config )
+ table_elems.append( table_elem )
+ if table.name not in self.data_tables:
+ self.data_tables[ table.name ] = table
+ log.debug( "Loaded tool data table '%s'", table.name )
+ else:
+ log.debug( "Loading another instance of data table '%s', attempting to merge content.", table.name )
+ self.data_tables[ table.name ].merge_tool_data_table( table, allow_duplicates=False ) #only merge content, do not persist to disk, do not allow duplicate rows when merging
+ # FIXME: This does not account for an entry with the same unique build ID, but a different path.
return table_elems
def add_new_entries_from_config_file( self, config_filename, tool_data_path, shed_tool_data_table_config, persist=False ):
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Bugfix for updating history dataset collection name.
by commits-noreply@bitbucket.org 14 May '14
by commits-noreply@bitbucket.org 14 May '14
14 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6b86b4186c45/
Changeset: 6b86b4186c45
User: jmchilton
Date: 2014-05-14 12:26:21
Summary: Bugfix for updating history dataset collection name.
Thanks to Bjoern for the bug report.
This attribute had been DatasetCollection in earlier versions of this code and the update code was only partially cut-over to use the new location for name (on HistoryDatasetCollectionAssociation).
Affected #: 2 files
diff -r e0d69ca8be55cd8cfd863ad7f128e95a42eabfd3 -r 6b86b4186c455317cba726c7ad6579a030922421 lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -2636,20 +2636,8 @@
return new_collection
def set_from_dict( self, new_data ):
- editable_keys = ( 'name' )
- changed = {}
-
- # unknown keys are ignored here
- for key in [ k for k in new_data.keys() if k in editable_keys ]:
- new_val = new_data[ key ]
- old_val = self.__getattribute__( key )
- if new_val == old_val:
- continue
-
- self.__setattr__( key, new_val )
- changed[ key ] = new_val
-
- return changed
+ # Nothing currently editable in this class.
+ return {}
class DatasetCollectionInstance( object, HasName ):
diff -r e0d69ca8be55cd8cfd863ad7f128e95a42eabfd3 -r 6b86b4186c455317cba726c7ad6579a030922421 test/api/test_history_contents.py
--- a/test/api/test_history_contents.py
+++ b/test/api/test_history_contents.py
@@ -128,12 +128,28 @@
dataset_collection = show_response.json()
assert dataset_collection[ "deleted" ]
- def __show( self, hda ):
- show_response = self._get( "histories/%s/contents/%s" % ( self.history_id, hda[ "id" ] ) )
+ def test_update_dataset_collection( self ):
+ payload = self.dataset_collection_populator.create_pair_payload(
+ self.history_id,
+ type="dataset_collection"
+ )
+ dataset_collection_response = self._post( "histories/%s/contents" % self.history_id, payload )
+ self._assert_status_code_is( dataset_collection_response, 200 )
+ hdca = dataset_collection_response.json()
+ update_url = self._api_url( "histories/%s/contents/dataset_collections/%s" % ( self.history_id, hdca[ "id" ] ), use_key=True )
+ # Awkward json.dumps required here because of https://trello.com/c/CQwmCeG6
+ body = json.dumps( dict( name="newnameforpair" ) )
+ update_response = put_request( update_url, data=body )
+ self._assert_status_code_is( update_response, 200 )
+ show_response = self.__show( hdca )
+ assert str( show_response.json()[ "name" ] ) == "newnameforpair"
+
+ def __show( self, contents ):
+ show_response = self._get( "histories/%s/contents/%ss/%s" % ( self.history_id, contents["history_content_type"], contents[ "id" ] ) )
return show_response
def __count_contents( self, history_id=None, **kwds ):
- if history_id == None:
+ if history_id is None:
history_id = self.history_id
contents_response = self._get( "histories/%s/contents" % history_id, kwds )
return len( contents_response.json() )
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: jmchilton: Fix duplicated names in on_text when using multiple data inputs.
by commits-noreply@bitbucket.org 13 May '14
by commits-noreply@bitbucket.org 13 May '14
13 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e0d69ca8be55/
Changeset: e0d69ca8be55
User: jmchilton
Date: 2014-05-14 00:47:57
Summary: Fix duplicated names in on_text when using multiple data inputs.
Unit tests verifing the fixed, correct behavior included. Bug introduced in e8c84dd715782e7c1d709d8068e6033b835f7f39 as an unintended consequence of duplicating the first dataset in the dictionary of input datasets generated by the tool action code.
Fixes https://trello.com/c/LCEKxImR.
Affected #: 2 files
diff -r c1873e4d23fa2c496990e5bdef83300e929ae40c -r e0d69ca8be55cd8cfd863ad7f128e95a42eabfd3 lib/galaxy/tools/actions/__init__.py
--- a/lib/galaxy/tools/actions/__init__.py
+++ b/lib/galaxy/tools/actions/__init__.py
@@ -472,6 +472,15 @@
def on_text_for_names( input_names ):
+ # input_names may contain duplicates... this is because the first value in
+ # multiple input dataset parameters will appear twice once as param_name
+ # and once as param_name1.
+ unique_names = []
+ for name in input_names:
+ if name not in unique_names:
+ unique_names.append( name )
+ input_names = unique_names
+
# Build name for output datasets based on tool name and input names
if len( input_names ) == 1:
on_text = input_names[0]
diff -r c1873e4d23fa2c496990e5bdef83300e929ae40c -r e0d69ca8be55cd8cfd863ad7f128e95a42eabfd3 test/unit/tools/test_actions.py
--- a/test/unit/tools/test_actions.py
+++ b/test/unit/tools/test_actions.py
@@ -2,6 +2,7 @@
from galaxy import model
from galaxy.tools.actions import DefaultToolAction
+from galaxy.tools.actions import on_text_for_names
import tools_support
@@ -25,6 +26,19 @@
'''
+def test_on_text_for_names():
+ def assert_on_text_is( expected, *names ):
+ on_text = on_text_for_names( names )
+ assert on_text == expected, "Wrong on text value %s, expected %s" % ( on_text, expected )
+
+ assert_on_text_is( "data 1", "data 1" )
+ assert_on_text_is( "data 1 and data 2", "data 1", "data 2" )
+ assert_on_text_is( "data 1, data 2, and data 3", "data 1", "data 2", "data 3" )
+ assert_on_text_is( "data 1, data 2, and others", "data 1", "data 2", "data 3", "data 4" )
+
+ assert_on_text_is( "data 1 and data 2", "data 1", "data 1", "data 2" )
+
+
class DefaultToolActionTestCase( unittest.TestCase, tools_support.UsesApp, tools_support.UsesTools ):
def setUp( self ):
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
13 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/c1873e4d23fa/
Changeset: c1873e4d23fa
User: dannon
Date: 2014-05-13 23:39:55
Summary: Merge from stable.
Affected #: 1 file
diff -r b4680b54994ad6c62f05d354a2af5743344152e8 -r c1873e4d23fa2c496990e5bdef83300e929ae40c lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -177,10 +177,16 @@
while external_job_id is None and trynum < 5:
try:
external_job_id = self.ds.runJob(jt)
- except drmaa.InternalException, e:
+ break
+ except ( drmaa.InternalException, drmaa.DeniedByDrmException ), e:
trynum += 1
log.warning( '(%s) drmaa.Session.runJob() failed, will retry: %s', galaxy_id_tag, e )
time.sleep( 5 )
+ else:
+ log.error( "(%s) All attempts to submit job failed" % galaxy_id_tag )
+ job_wrapper.fail( "Unable to run this job due to a cluster error, please retry it later" )
+ self.ds.deleteJobTemplate( jt )
+ return
else:
job_wrapper.change_ownership_for_run()
log.debug( '(%s) submitting with credentials: %s [uid: %s]' % ( galaxy_id_tag, job_wrapper.user_system_pwent[0], job_wrapper.user_system_pwent[2] ) )
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: jmchilton: Fixes for DRMAA submission failures.
by commits-noreply@bitbucket.org 13 May '14
by commits-noreply@bitbucket.org 13 May '14
13 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/cc0fe62e54dc/
Changeset: cc0fe62e54dc
Branch: stable
User: jmchilton
Date: 2014-05-12 20:32:34
Summary: Fixes for DRMAA submission failures.
Mark job as failed once Galaxy is done attempting to submit the job, catch and retry drmaa.DeniedByDrmException like drmaa.InternalException.
Affected #: 1 file
diff -r 3534f67acd2a4f84899335326ac2cc8bcf05201d -r cc0fe62e54dc59607c26cd9152ef1ea7c85af625 lib/galaxy/jobs/runners/drmaa.py
--- a/lib/galaxy/jobs/runners/drmaa.py
+++ b/lib/galaxy/jobs/runners/drmaa.py
@@ -177,10 +177,16 @@
while external_job_id is None and trynum < 5:
try:
external_job_id = self.ds.runJob(jt)
- except drmaa.InternalException, e:
+ break
+ except ( drmaa.InternalException, drmaa.DeniedByDrmException ), e:
trynum += 1
log.warning( '(%s) drmaa.Session.runJob() failed, will retry: %s', galaxy_id_tag, e )
time.sleep( 5 )
+ else:
+ log.error( "(%s) All attempts to submit job failed" % galaxy_id_tag )
+ job_wrapper.fail( "Unable to run this job due to a cluster error, please retry it later" )
+ self.ds.deleteJobTemplate( jt )
+ return
else:
job_wrapper.change_ownership_for_run()
log.debug( '(%s) submitting with credentials: %s [uid: %s]' % ( galaxy_id_tag, job_wrapper.user_system_pwent[0], job_wrapper.user_system_pwent[2] ) )
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: jmchilton: Merged in natefoo/galaxy-central (pull request #392)
by commits-noreply@bitbucket.org 13 May '14
by commits-noreply@bitbucket.org 13 May '14
13 May '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/b4680b54994a/
Changeset: b4680b54994a
User: jmchilton
Date: 2014-05-13 22:38:04
Summary: Merged in natefoo/galaxy-central (pull request #392)
SSL client certificate support for LWR AMQP connections
Affected #: 5 files
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 job_conf.xml.sample_advanced
--- a/job_conf.xml.sample_advanced
+++ b/job_conf.xml.sample_advanced
@@ -41,6 +41,16 @@
<!-- If multiple managers configured on the LWR, specify which one
this plugin targets. --><!-- <param id="manager">_default_</param> -->
+ <!-- The AMQP client can provide an SSL client certificate (e.g. for
+ validation), the following options configure that certificate
+ (see for reference:
+ http://kombu.readthedocs.org/en/latest/reference/kombu.connection.html
+ ). If you simply want to use SSL but not use/validate a client
+ cert, just use the ?ssl=1 query on the amqp URL instead. -->
+ <!-- <param id="amqp_connect_ssl_ca_certs">/path/to/cacert.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_keyfile">/path/to/key.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_certfile">/path/to/cert.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_cert_reqs">cert_required</param> --></plugin><plugin id="cli" type="runner" load="galaxy.jobs.runners.cli:ShellJobRunner" /><plugin id="condor" type="runner" load="galaxy.jobs.runners.condor:CondorJobRunner" />
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -40,13 +40,17 @@
"""
runner_name = "LWRRunner"
- def __init__( self, app, nworkers, transport=None, cache=None, url=None, galaxy_url=DEFAULT_GALAXY_URL ):
+ def __init__( self, app, nworkers, transport=None, cache=None, url=None, galaxy_url=DEFAULT_GALAXY_URL, **kwds ):
"""Start the job runner """
super( LwrJobRunner, self ).__init__( app, nworkers )
self.async_status_updates = dict()
self._init_monitor_thread()
self._init_worker_threads()
- client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url}
+ amqp_connect_ssl_args = {}
+ for kwd in kwds.keys():
+ if kwd.startswith('amqp_connect_ssl_'):
+ amqp_connect_ssl_args[kwd] = kwds[kwd]
+ client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url, 'amqp_connect_ssl_args': amqp_connect_ssl_args or None}
self.galaxy_url = galaxy_url
self.client_manager = build_client_manager(**client_manager_kwargs)
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
--- a/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
+++ b/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
@@ -30,13 +30,14 @@
name _default_.
"""
- def __init__(self, url, manager_name, timeout=DEFAULT_TIMEOUT):
+ def __init__(self, url, manager_name, connect_ssl=None, timeout=DEFAULT_TIMEOUT):
"""
"""
if not kombu:
raise Exception(KOMBU_UNAVAILABLE)
self.__url = url
self.__manager_name = manager_name
+ self.__connect_ssl = connect_ssl
self.__exchange = kombu.Exchange(DEFAULT_EXCHANGE_NAME, DEFAULT_EXCHANGE_TYPE)
self.__timeout = timeout
@@ -46,7 +47,7 @@
def consume(self, queue_name, callback, check=True, connection_kwargs={}):
queue = self.__queue(queue_name)
- with self.connection(self.__url, **connection_kwargs) as connection:
+ with self.connection(self.__url, ssl=self.__connect_ssl, **connection_kwargs) as connection:
with kombu.Consumer(connection, queues=[queue], callbacks=[callback], accept=['json']):
while check:
try:
@@ -55,7 +56,7 @@
pass
def publish(self, name, payload):
- with self.connection(self.__url) as connection:
+ with self.connection(self.__url, ssl=self.__connect_ssl) as connection:
with pools.producers[connection].acquire() as producer:
key = self.__queue_name(name)
producer.publish(
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr_client/manager.py
--- a/lib/galaxy/jobs/runners/lwr_client/manager.py
+++ b/lib/galaxy/jobs/runners/lwr_client/manager.py
@@ -13,6 +13,7 @@
from .object_client import ObjectStoreClient
from .transport import get_transport
from .util import TransferEventManager
+from .util import parse_amqp_connect_ssl_params
from .destination import url_to_destination_params
from .amqp_exchange import LwrExchange
@@ -76,7 +77,8 @@
def __init__(self, **kwds):
self.url = kwds.get('url')
self.manager_name = kwds.get("manager", "_default_")
- self.exchange = LwrExchange(self.url, self.manager_name)
+ self.connect_ssl = parse_amqp_connect_ssl_params(kwds.get('amqp_connect_ssl_args', None))
+ self.exchange = LwrExchange(self.url, self.manager_name, self.connect_ssl)
self.status_cache = {}
self.callback_lock = threading.Lock()
self.callback_thread = None
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr_client/util.py
--- a/lib/galaxy/jobs/runners/lwr_client/util.py
+++ b/lib/galaxy/jobs/runners/lwr_client/util.py
@@ -62,6 +62,21 @@
contents.append(name)
return contents
+def parse_amqp_connect_ssl_params(params):
+ ssl = None
+ rval = None
+ ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
+ if ssl_options:
+ ssl = __import__('ssl')
+ rval = {}
+ for option in ssl_options:
+ value = params.get(option)
+ option = option.replace('amqp_connect_ssl_', '', 1)
+ if option == 'cert_reqs':
+ value = getattr(ssl, value.upper())
+ rval[option] = value
+ return rval
+
def filter_destination_params(destination_params, prefix):
destination_params = destination_params or {}
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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0405422ab342/
Changeset: 0405422ab342
User: natefoo
Date: 2014-05-13 22:22:03
Summary: Allow specification of SSL client authentication parameters to the kombu
connection. This is done via the `amqp_connect_ssl_*` options in `server.ini`.
Affected #: 5 files
diff -r e5b545b85b836b6f1be76164543d7e4613f25d87 -r 0405422ab3422f1b1373c0b00398885a4d8423f6 job_conf.xml.sample_advanced
--- a/job_conf.xml.sample_advanced
+++ b/job_conf.xml.sample_advanced
@@ -41,6 +41,16 @@
<!-- If multiple managers configured on the LWR, specify which one
this plugin targets. --><!-- <param id="manager">_default_</param> -->
+ <!-- The AMQP client can provide an SSL client certificate (e.g. for
+ validation), the following options configure that certificate
+ (see for reference:
+ http://kombu.readthedocs.org/en/latest/reference/kombu.connection.html
+ ). If you simply want to use SSL but not use/validate a client
+ cert, just use the ?ssl=1 query on the amqp URL instead. -->
+ <!-- <param id="amqp_connect_ssl_ca_certs">/path/to/cacert.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_keyfile">/path/to/key.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_certfile">/path/to/cert.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_cert_reqs">cert_required</param> --></plugin><plugin id="cli" type="runner" load="galaxy.jobs.runners.cli:ShellJobRunner" /><plugin id="condor" type="runner" load="galaxy.jobs.runners.condor:CondorJobRunner" />
diff -r e5b545b85b836b6f1be76164543d7e4613f25d87 -r 0405422ab3422f1b1373c0b00398885a4d8423f6 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -40,13 +40,17 @@
"""
runner_name = "LWRRunner"
- def __init__( self, app, nworkers, transport=None, cache=None, url=None, galaxy_url=DEFAULT_GALAXY_URL ):
+ def __init__( self, app, nworkers, transport=None, cache=None, url=None, galaxy_url=DEFAULT_GALAXY_URL, **kwds ):
"""Start the job runner """
super( LwrJobRunner, self ).__init__( app, nworkers )
self.async_status_updates = dict()
self._init_monitor_thread()
self._init_worker_threads()
- client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url}
+ amqp_connect_ssl_args = {}
+ for kwd in kwds.keys():
+ if kwd.startswith('amqp_connect_ssl_'):
+ amqp_connect_ssl_args[kwd] = kwds[kwd]
+ client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url, 'amqp_connect_ssl_args': amqp_connect_ssl_args or None}
self.galaxy_url = galaxy_url
self.client_manager = build_client_manager(**client_manager_kwargs)
diff -r e5b545b85b836b6f1be76164543d7e4613f25d87 -r 0405422ab3422f1b1373c0b00398885a4d8423f6 lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
--- a/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
+++ b/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
@@ -30,13 +30,14 @@
name _default_.
"""
- def __init__(self, url, manager_name, timeout=DEFAULT_TIMEOUT):
+ def __init__(self, url, manager_name, connect_ssl=None, timeout=DEFAULT_TIMEOUT):
"""
"""
if not kombu:
raise Exception(KOMBU_UNAVAILABLE)
self.__url = url
self.__manager_name = manager_name
+ self.__connect_ssl = connect_ssl
self.__exchange = kombu.Exchange(DEFAULT_EXCHANGE_NAME, DEFAULT_EXCHANGE_TYPE)
self.__timeout = timeout
@@ -46,7 +47,7 @@
def consume(self, queue_name, callback, check=True, connection_kwargs={}):
queue = self.__queue(queue_name)
- with self.connection(self.__url, **connection_kwargs) as connection:
+ with self.connection(self.__url, ssl=self.__connect_ssl, **connection_kwargs) as connection:
with kombu.Consumer(connection, queues=[queue], callbacks=[callback], accept=['json']):
while check:
try:
@@ -55,7 +56,7 @@
pass
def publish(self, name, payload):
- with self.connection(self.__url) as connection:
+ with self.connection(self.__url, ssl=self.__connect_ssl) as connection:
with pools.producers[connection].acquire() as producer:
key = self.__queue_name(name)
producer.publish(
diff -r e5b545b85b836b6f1be76164543d7e4613f25d87 -r 0405422ab3422f1b1373c0b00398885a4d8423f6 lib/galaxy/jobs/runners/lwr_client/manager.py
--- a/lib/galaxy/jobs/runners/lwr_client/manager.py
+++ b/lib/galaxy/jobs/runners/lwr_client/manager.py
@@ -13,6 +13,7 @@
from .object_client import ObjectStoreClient
from .transport import get_transport
from .util import TransferEventManager
+from .util import parse_amqp_connect_ssl_params
from .destination import url_to_destination_params
from .amqp_exchange import LwrExchange
@@ -76,7 +77,8 @@
def __init__(self, **kwds):
self.url = kwds.get('url')
self.manager_name = kwds.get("manager", "_default_")
- self.exchange = LwrExchange(self.url, self.manager_name)
+ self.connect_ssl = parse_amqp_connect_ssl_params(kwds.get('amqp_connect_ssl_args', None))
+ self.exchange = LwrExchange(self.url, self.manager_name, self.connect_ssl)
self.status_cache = {}
self.callback_lock = threading.Lock()
self.callback_thread = None
diff -r e5b545b85b836b6f1be76164543d7e4613f25d87 -r 0405422ab3422f1b1373c0b00398885a4d8423f6 lib/galaxy/jobs/runners/lwr_client/util.py
--- a/lib/galaxy/jobs/runners/lwr_client/util.py
+++ b/lib/galaxy/jobs/runners/lwr_client/util.py
@@ -62,6 +62,21 @@
contents.append(name)
return contents
+def parse_amqp_connect_ssl_params(params):
+ ssl = None
+ rval = None
+ ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
+ if ssl_options:
+ ssl = __import__('ssl')
+ rval = {}
+ for option in ssl_options:
+ value = params.get(option)
+ option = option.replace('amqp_connect_ssl_', '', 1)
+ if option == 'cert_reqs':
+ value = getattr(ssl, value.upper())
+ rval[option] = value
+ return rval
+
def filter_destination_params(destination_params, prefix):
destination_params = destination_params or {}
https://bitbucket.org/galaxy/galaxy-central/commits/b4680b54994a/
Changeset: b4680b54994a
User: jmchilton
Date: 2014-05-13 22:38:04
Summary: Merged in natefoo/galaxy-central (pull request #392)
SSL client certificate support for LWR AMQP connections
Affected #: 5 files
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 job_conf.xml.sample_advanced
--- a/job_conf.xml.sample_advanced
+++ b/job_conf.xml.sample_advanced
@@ -41,6 +41,16 @@
<!-- If multiple managers configured on the LWR, specify which one
this plugin targets. --><!-- <param id="manager">_default_</param> -->
+ <!-- The AMQP client can provide an SSL client certificate (e.g. for
+ validation), the following options configure that certificate
+ (see for reference:
+ http://kombu.readthedocs.org/en/latest/reference/kombu.connection.html
+ ). If you simply want to use SSL but not use/validate a client
+ cert, just use the ?ssl=1 query on the amqp URL instead. -->
+ <!-- <param id="amqp_connect_ssl_ca_certs">/path/to/cacert.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_keyfile">/path/to/key.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_certfile">/path/to/cert.pem</param> -->
+ <!-- <param id="amqp_connect_ssl_cert_reqs">cert_required</param> --></plugin><plugin id="cli" type="runner" load="galaxy.jobs.runners.cli:ShellJobRunner" /><plugin id="condor" type="runner" load="galaxy.jobs.runners.condor:CondorJobRunner" />
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr.py
--- a/lib/galaxy/jobs/runners/lwr.py
+++ b/lib/galaxy/jobs/runners/lwr.py
@@ -40,13 +40,17 @@
"""
runner_name = "LWRRunner"
- def __init__( self, app, nworkers, transport=None, cache=None, url=None, galaxy_url=DEFAULT_GALAXY_URL ):
+ def __init__( self, app, nworkers, transport=None, cache=None, url=None, galaxy_url=DEFAULT_GALAXY_URL, **kwds ):
"""Start the job runner """
super( LwrJobRunner, self ).__init__( app, nworkers )
self.async_status_updates = dict()
self._init_monitor_thread()
self._init_worker_threads()
- client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url}
+ amqp_connect_ssl_args = {}
+ for kwd in kwds.keys():
+ if kwd.startswith('amqp_connect_ssl_'):
+ amqp_connect_ssl_args[kwd] = kwds[kwd]
+ client_manager_kwargs = {'transport_type': transport, 'cache': string_as_bool_or_none(cache), "url": url, 'amqp_connect_ssl_args': amqp_connect_ssl_args or None}
self.galaxy_url = galaxy_url
self.client_manager = build_client_manager(**client_manager_kwargs)
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
--- a/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
+++ b/lib/galaxy/jobs/runners/lwr_client/amqp_exchange.py
@@ -30,13 +30,14 @@
name _default_.
"""
- def __init__(self, url, manager_name, timeout=DEFAULT_TIMEOUT):
+ def __init__(self, url, manager_name, connect_ssl=None, timeout=DEFAULT_TIMEOUT):
"""
"""
if not kombu:
raise Exception(KOMBU_UNAVAILABLE)
self.__url = url
self.__manager_name = manager_name
+ self.__connect_ssl = connect_ssl
self.__exchange = kombu.Exchange(DEFAULT_EXCHANGE_NAME, DEFAULT_EXCHANGE_TYPE)
self.__timeout = timeout
@@ -46,7 +47,7 @@
def consume(self, queue_name, callback, check=True, connection_kwargs={}):
queue = self.__queue(queue_name)
- with self.connection(self.__url, **connection_kwargs) as connection:
+ with self.connection(self.__url, ssl=self.__connect_ssl, **connection_kwargs) as connection:
with kombu.Consumer(connection, queues=[queue], callbacks=[callback], accept=['json']):
while check:
try:
@@ -55,7 +56,7 @@
pass
def publish(self, name, payload):
- with self.connection(self.__url) as connection:
+ with self.connection(self.__url, ssl=self.__connect_ssl) as connection:
with pools.producers[connection].acquire() as producer:
key = self.__queue_name(name)
producer.publish(
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr_client/manager.py
--- a/lib/galaxy/jobs/runners/lwr_client/manager.py
+++ b/lib/galaxy/jobs/runners/lwr_client/manager.py
@@ -13,6 +13,7 @@
from .object_client import ObjectStoreClient
from .transport import get_transport
from .util import TransferEventManager
+from .util import parse_amqp_connect_ssl_params
from .destination import url_to_destination_params
from .amqp_exchange import LwrExchange
@@ -76,7 +77,8 @@
def __init__(self, **kwds):
self.url = kwds.get('url')
self.manager_name = kwds.get("manager", "_default_")
- self.exchange = LwrExchange(self.url, self.manager_name)
+ self.connect_ssl = parse_amqp_connect_ssl_params(kwds.get('amqp_connect_ssl_args', None))
+ self.exchange = LwrExchange(self.url, self.manager_name, self.connect_ssl)
self.status_cache = {}
self.callback_lock = threading.Lock()
self.callback_thread = None
diff -r d963b05c497cc17d36a16696077e5a0f3158e52b -r b4680b54994ad6c62f05d354a2af5743344152e8 lib/galaxy/jobs/runners/lwr_client/util.py
--- a/lib/galaxy/jobs/runners/lwr_client/util.py
+++ b/lib/galaxy/jobs/runners/lwr_client/util.py
@@ -62,6 +62,21 @@
contents.append(name)
return contents
+def parse_amqp_connect_ssl_params(params):
+ ssl = None
+ rval = None
+ ssl_options = filter(lambda x: x.startswith('amqp_connect_ssl_'), params.keys())
+ if ssl_options:
+ ssl = __import__('ssl')
+ rval = {}
+ for option in ssl_options:
+ value = params.get(option)
+ option = option.replace('amqp_connect_ssl_', '', 1)
+ if option == 'cert_reqs':
+ value = getattr(ssl, value.upper())
+ rval[option] = value
+ return rval
+
def filter_destination_params(destination_params, prefix):
destination_params = destination_params or {}
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