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
commit/galaxy-central: guerler: Charts: Add basic customization capabilities, modularize chart types
by commits-noreply@bitbucket.org 07 Mar '14
by commits-noreply@bitbucket.org 07 Mar '14
07 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/8ffa9ee61864/
Changeset: 8ffa9ee61864
User: guerler
Date: 2014-03-07 23:01:39
Summary: Charts: Add basic customization capabilities, modularize chart types
Affected #: 32 files
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,7 +1,7 @@
// dependencies
define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
'plugin/views/charts', 'plugin/views/chart',
- 'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
+ 'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/charts/types'],
function( Modal, Portlet, Ui, Utils, Jobs, Datasets,
ChartsView, ChartView,
Config, Chart, Charts, Types
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/bardiagram.js
--- a/config/plugins/visualizations/charts/static/charts/bardiagram.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// dependencies
-define([], function() {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // render
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarChart();
-
- self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
-
- self.options.svg.datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/bardiagram/bardiagram.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/bardiagram/bardiagram.js
@@ -0,0 +1,41 @@
+// dependencies
+define([], function() {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // render
+ draw : function(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarChart();
+
+ self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
+ .axisLabel(chart.settings.get('y_axis_label', 'Frequency'))
+ .axisLabelDistance(30);
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
+ .axisLabel(chart.settings.get('x_axis_label', 'Breaks'));
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/bardiagram/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/bardiagram/config.js
@@ -0,0 +1,28 @@
+define([], function() {
+
+return {
+ title : 'Bar diagram',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ },
+ settings : {
+ x_axis_label : {
+ title : 'Axis label (x)',
+ info : 'Provide a label for the \'x\' axis.',
+ type : 'text',
+ init : '',
+ placeholder : 'Axis label'
+ },
+ y_axis_label : {
+ title : 'Axis label (y)',
+ info : 'Provide a label for the \'y\' axis.',
+ type : 'text',
+ init : '',
+ placeholder : 'Axis label'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/histogram.js
--- a/config/plugins/visualizations/charts/static/charts/histogram.js
+++ /dev/null
@@ -1,52 +0,0 @@
-// dependencies
-define([], function() {
-
-// widget
-return Backbone.View.extend(
-{
- // initialize
- initialize: function(app, options) {
- this.app = app;
- this.options = options;
- },
-
- // plot
- plot: function(chart, request_dictionary) {
-
- // update request dataset id
- request_dictionary.id = chart.get('dataset_id_job');
-
- // configure request
- var index = 0;
- for (var i in request_dictionary.groups) {
- var group = request_dictionary.groups[i];
- group.columns = {
- x: index++,
- y: index++
- }
- }
-
- // send request
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- chart.set('state', 'ok');
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarChart();
-
- self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
- .axisLabel('Breaks');
-
- self.d3_chart.yAxis.tickFormat(d3.format('.3f'))
- .axisLabel('Frequency')
- .axisLabelDistance(30);
-
- self.options.svg.datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/histogram/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/histogram/config.js
@@ -0,0 +1,30 @@
+define([], function() {
+
+return {
+ title : 'Histogram',
+ mode : 'execute',
+ columns : {
+ y : {
+ title : 'Derive frequencies'
+ }
+ },
+ settings : {
+ x_axis_label : {
+ title : 'Axis label (x)',
+ info : 'Provide a label for the \'x\' axis.',
+ type : 'text',
+ init : 'Breaks',
+ placeholder : 'Axis label'
+ },
+ bin_size : {
+ title : 'Number of Bins',
+ info : 'Provide the number of histogram bins. The parsed data will be evenly distributed into bins according to the minimum and maximum values of the dataset.',
+ type : 'slider',
+ init : 10,
+ min : 10,
+ max : 1000,
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/histogram/histogram.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/histogram/histogram.js
@@ -0,0 +1,55 @@
+// dependencies
+define([], function() {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // draw
+ draw: function(chart, request_dictionary) {
+
+ // update request dataset id
+ request_dictionary.id = chart.get('dataset_id_job');
+
+ // configure request
+ var index = 0;
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = {
+ x: index++,
+ y: index++
+ }
+ }
+
+ // send request
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ // set chart state
+ chart.set('state', 'ok');
+
+ // draw graph
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarChart();
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
+ .axisLabel('Breaks');
+
+ self.d3_chart.yAxis.tickFormat(d3.format('.3f'))
+ .axisLabel('Frequency')
+ .axisLabelDistance(30);
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/horizontal.js
--- a/config/plugins/visualizations/charts/static/charts/horizontal.js
+++ /dev/null
@@ -1,37 +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
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- // add graph to screen
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarHorizontalChart();
-
- self.d3_chart.xAxis.tickFormat(function() { return ''; });
-
- self.options.svg.datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/horizontal/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/horizontal/config.js
@@ -0,0 +1,12 @@
+define([], function() {
+
+return {
+ title : 'Bar diagram (horizontal)',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/horizontal/horizontal.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/horizontal/horizontal.js
@@ -0,0 +1,37 @@
+// 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(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ // add graph to screen
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarHorizontalChart();
+
+ self.d3_chart.xAxis.tickFormat(function() { return ''; });
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/line.js
--- a/config/plugins/visualizations/charts/static/charts/line.js
+++ /dev/null
@@ -1,40 +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
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- nv.addGraph(function() {
- self.chart_3d = nv.models.lineChart();
-
- self.chart_3d.xAxis
- .tickFormat(d3.format(',f'));
-
- self.chart_3d.yAxis
- .tickFormat(d3.format(',.2f'));
-
- self.options.svg.datum(data)
- .call(self.chart_3d);
-
- nv.utils.windowResize(self.chart_3d.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/line/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/line/config.js
@@ -0,0 +1,12 @@
+define([], function() {
+
+return {
+ title : 'Line chart',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/line/line.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/line/line.js
@@ -0,0 +1,40 @@
+// 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(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.lineChart();
+
+ self.chart_3d.xAxis
+ .tickFormat(d3.format(',f'));
+
+ self.chart_3d.yAxis
+ .tickFormat(d3.format(',.2f'));
+
+ self.options.svg.datum(data)
+ .call(self.chart_3d);
+
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/linewithfocus.js
--- a/config/plugins/visualizations/charts/static/charts/linewithfocus.js
+++ /dev/null
@@ -1,40 +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
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- nv.addGraph(function() {
- self.chart_3d = nv.models.lineWithFocusChart();
-
- self.chart_3d.xAxis
- .tickFormat(d3.format(',f'));
-
- self.chart_3d.yAxis
- .tickFormat(d3.format(',.2f'));
-
- self.options.svg.datum(data)
- .call(self.chart_3d);
-
- nv.utils.windowResize(self.chart_3d.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/linewithfocus/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/linewithfocus/config.js
@@ -0,0 +1,12 @@
+define([], function() {
+
+return {
+ title : 'Line chart (with focus)',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/linewithfocus/linewithfocus.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/linewithfocus/linewithfocus.js
@@ -0,0 +1,40 @@
+// 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(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.lineWithFocusChart();
+
+ self.chart_3d.xAxis
+ .tickFormat(d3.format(',f'));
+
+ self.chart_3d.yAxis
+ .tickFormat(d3.format(',.2f'));
+
+ self.options.svg.datum(data)
+ .call(self.chart_3d);
+
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/piechart.js
--- a/config/plugins/visualizations/charts/static/charts/piechart.js
+++ /dev/null
@@ -1,54 +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
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
-
- // loop through data groups
- for (var key in request_dictionary.groups) {
- // get group
- var group = request_dictionary.groups[key];
-
- // format chart data
- var pie_data = [];
- for (var key in group.values) {
- var value = group.values[key];
- pie_data.push ({
- key : value.x,
- y : value.y
- });
- }
-
- // add graph to screen
- nv.addGraph(function() {
- self.chart_3d = nv.models.pieChart()
- .donut(true)
- .showLegend(false);
-
- self.options.svg.datum(pie_data)
- .call(self.chart_3d);
-
- nv.utils.windowResize(self.chart_3d.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- }
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/piechart/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/piechart/config.js
@@ -0,0 +1,12 @@
+define([], function() {
+
+return {
+ title : 'Pie chart',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/piechart/piechart.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/piechart/piechart.js
@@ -0,0 +1,54 @@
+// 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(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+
+ // loop through data groups
+ for (var key in request_dictionary.groups) {
+ // get group
+ var group = request_dictionary.groups[key];
+
+ // format chart data
+ var pie_data = [];
+ for (var key in group.values) {
+ var value = group.values[key];
+ pie_data.push ({
+ key : value.x,
+ y : value.y
+ });
+ }
+
+ // add graph to screen
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.pieChart()
+ .donut(true)
+ .showLegend(false);
+
+ self.options.svg.datum(pie_data)
+ .call(self.chart_3d);
+
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ }
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/scatterplot.js
--- a/config/plugins/visualizations/charts/static/charts/scatterplot.js
+++ /dev/null
@@ -1,40 +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
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- nv.addGraph(function() {
- self.d3_chart = nv.models.scatterChart()
- .showDistX(true)
- .showDistY(true)
- .color(d3.scale.category10().range());
-
- self.d3_chart.xAxis.tickFormat(d3.format('.02f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.02f'))
-
- self.options.svg.datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/scatterplot/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/scatterplot/config.js
@@ -0,0 +1,15 @@
+define([], function() {
+
+return {
+ title : 'Scatter plot',
+ columns : {
+ x : {
+ title : 'Values for x-axis'
+ },
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/scatterplot/scatterplot.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/scatterplot/scatterplot.js
@@ -0,0 +1,40 @@
+// 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(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.scatterChart()
+ .showDistX(true)
+ .showDistY(true)
+ .color(d3.scale.category10().range());
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.02f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.02f'))
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/stackedarea.js
--- a/config/plugins/visualizations/charts/static/charts/stackedarea.js
+++ /dev/null
@@ -1,44 +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
- plot : function(chart, request_dictionary)
- {
- // request data
- var self = this;
- this.app.datasets.request(request_dictionary, function(data) {
- nv.addGraph(function() {
- // make plot
- self.d3_chart = nv.models.stackedAreaChart()
- .x(function(d) {
- return d.x
- })
- .y(function(d) {
- return d.y
- })
- .clipEdge(true);
-
- self.d3_chart.xAxis.tickFormat(function() { return ''; });
-
- self.options.svg.datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
-
- // set chart state
- chart.set('state', 'ok');
- });
- });
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/stackedarea/config.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/stackedarea/config.js
@@ -0,0 +1,12 @@
+define([], function() {
+
+return {
+ title : 'Stacked area',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+};
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/stackedarea/stackedarea.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/stackedarea/stackedarea.js
@@ -0,0 +1,44 @@
+// 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(chart, request_dictionary)
+ {
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ // make plot
+ self.d3_chart = nv.models.stackedAreaChart()
+ .x(function(d) {
+ return d.x
+ })
+ .y(function(d) {
+ return d.y
+ })
+ .clipEdge(true);
+
+ self.d3_chart.xAxis.tickFormat(function() { return ''; });
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/charts/types.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/types.js
@@ -0,0 +1,36 @@
+// dependencies
+define(['plugin/charts/bardiagram/config',
+ 'plugin/charts/histogram/config',
+ 'plugin/charts/horizontal/config',
+ 'plugin/charts/line/config',
+ 'plugin/charts/linewithfocus/config',
+ 'plugin/charts/piechart/config',
+ 'plugin/charts/scatterplot/config',
+ 'plugin/charts/stackedarea/config',
+ ], function(bardiagram,
+ histogram,
+ horizontal,
+ line,
+ linewithfocus,
+ piechart,
+ scatterplot,
+ stackedarea
+ ) {
+
+// widget
+return Backbone.Model.extend(
+{
+ // types
+ defaults: {
+ 'bardiagram' : bardiagram,
+ 'horizontal' : horizontal,
+ 'histogram' : histogram,
+ 'line' : line,
+ 'linewithfocus' : linewithfocus,
+ 'piechart' : piechart,
+ 'scatterplot' : scatterplot,
+ 'stackedarea' : stackedarea
+ }
+});
+
+});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 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
@@ -69,6 +69,35 @@
});
// plugin
+var Icon = Backbone.View.extend(
+{
+ // options
+ optionsDefault: {
+ float : 'right',
+ icon : '',
+ tooltip : '',
+ placement : 'bottom'
+ },
+
+ // 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 '<span class="fa ' + options.icon + '" style="font-size: 1.2em;"/>';
+ }
+});
+
+// plugin
var ButtonIcon = Backbone.View.extend(
{
// options
@@ -481,6 +510,7 @@
return {
Label : Label,
Button : Button,
+ Icon : Icon,
ButtonIcon : ButtonIcon,
Input : Input,
Anchor : Anchor,
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -19,6 +19,7 @@
initialize: function(options)
{
this.groups = new Groups();
+ this.settings = new Backbone.Model();
},
// reset
@@ -26,6 +27,7 @@
{
this.clear({silent: true}).set(this.defaults);
this.groups.reset();
+ this.settings.clear();
this.trigger('reset', this);
},
@@ -33,11 +35,19 @@
copy: function(new_chart) {
// copy chart/groups
var current = this;
+
+ // set attributes
+ current.clear({silent: true}).set(this.defaults);
current.set(new_chart.attributes);
+
+ // set nested models/collections
+ current.settings = new_chart.settings.clone();
current.groups.reset();
new_chart.groups.each(function(group) {
current.groups.add(group.clone());
});
+
+ // trigger change
current.trigger('change', current);
},
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/models/types.js
--- a/config/plugins/visualizations/charts/static/models/types.js
+++ /dev/null
@@ -1,80 +0,0 @@
-// dependencies
-define([], function() {
-
-// widget
-return Backbone.Model.extend(
-{
- // types
- defaults: {
- 'bardiagram' : {
- title : 'Bar diagram',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- },
- 'horizontal' : {
- title : 'Bar diagram (horizontal)',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- },
- 'histogram' : {
- title : 'Histogram',
- mode : 'execute',
- columns : {
- y : {
- title : 'Derive frequencies'
- }
- }
- },
- 'line' : {
- title : 'Line chart',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- },
- 'linewithfocus' : {
- title : 'Line chart (with focus)',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- },
- 'piechart' : {
- title : 'Pie chart',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- },
- 'scatterplot' : {
- title : 'Scatter plot',
- columns : {
- x : {
- title : 'Values for x-axis'
- },
- y : {
- title : 'Values for y-axis'
- }
- }
- },
- 'stackedarea' : {
- title : 'Stacked area',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- }
- }
-});
-
-});
\ No newline at end of file
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -1,6 +1,8 @@
// dependencies
-define(['mvc/ui/ui-tabs', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/chart', 'plugin/models/group', 'plugin/views/group'],
- function(Tabs, Table, Ui, Utils, Chart, Group, GroupView) {
+define(['mvc/ui/ui-tabs', 'plugin/library/table', 'plugin/library/ui', 'utils/utils',
+ 'plugin/models/chart', 'plugin/models/group',
+ 'plugin/views/group', 'plugin/views/settings'],
+ function(Tabs, Table, Ui, Utils, Chart, Group, GroupView, SettingsView) {
// widget
return Backbone.View.extend(
@@ -33,8 +35,8 @@
if (self.chart.groups.length > 0) {
// show modal
self.app.modal.show({
- title : 'Switching the chart type?',
- body : 'If you continue your data selections will cleared.',
+ title : 'Switching to another chart type?',
+ body : 'If you continue your settings and selections will be reseted.',
buttons : {
'Cancel' : function() {
// hide modal
@@ -55,11 +57,12 @@
}
},
onchange : function(type) {
+ // reset type relevant chart content
+ self.chart.groups.reset();
+ self.chart.settings.clear();
+
// update chart type
self.chart.set({type: type});
-
- // reset groups
- self.chart.groups.reset();
},
content: 'No chart types available'
});
@@ -127,17 +130,31 @@
});
// append element
- var $settings = $('<div/>');
- $settings.append(Utils.wrap((new Ui.Label({ title : 'Provide a chart title:'})).$el));
- $settings.append(Utils.wrap(this.title.$el));
- $settings.append(Utils.wrap((new Ui.Label({ title : 'Select a chart type:'})).$el));
- $settings.append(Utils.wrap(this.table.$el));
+ var $main = $('<div/>');
+ $main.append(Utils.wrap((new Ui.Label({ title : 'Provide a chart title:'})).$el));
+ $main.append(Utils.wrap(this.title.$el));
+ $main.append(Utils.wrap((new Ui.Label({ title : 'Select a chart type:'})).$el));
+ $main.append(Utils.wrap(this.table.$el));
+
+ // add tab
+ this.tabs.add({
+ id : 'main',
+ title : 'Start',
+ $el : $main
+ });
+
+ //
+ // main settings tab
+ //
+
+ // create settings view
+ this.settings = new SettingsView(this.app);
// add tab
this.tabs.add({
id : 'settings',
- title : 'Start',
- $el : $settings
+ title : 'Configuration',
+ $el : this.settings.$el
});
// elements
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 config/plugins/visualizations/charts/static/views/charts.js
--- a/config/plugins/visualizations/charts/static/views/charts.js
+++ b/config/plugins/visualizations/charts/static/views/charts.js
@@ -156,11 +156,13 @@
// change
_changeChart: function(chart) {
- // add chart
- this._addChart(chart);
+ if (chart.get('type')) {
+ // add chart
+ this._addChart(chart);
- // select available chart
- this.table.value(chart.id);
+ // select available chart
+ this.table.value(chart.id);
+ }
}
});
diff -r feec63e4fc986281fdd3a00478d410bc6280848b -r 8ffa9ee618649b042292610cf8d10cff161c5235 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
@@ -135,7 +135,7 @@
var id = '#' + chart_id;
// create element
- var $chart_el = $(this._template({id: id, height : this.options.height}));
+ var $chart_el = $(this._template({id: id}));
// add to portlet
this.portlet.append($chart_el);
@@ -194,7 +194,7 @@
// create chart view
var self = this;
- require(['plugin/charts/' + chart_type], function(ChartView) {
+ require(['plugin/charts/' + chart_type + '/' + chart_type], function(ChartView) {
// create chart
var view = new ChartView(self.app, {svg : svg});
@@ -202,10 +202,10 @@
var mode = chart_settings.mode;
if (mode == 'execute') {
self.app.jobs.submit(chart, self._defaultRequestString(chart), function() {
- view.plot(chart, self._defaultRequestDictionary(chart));
+ view.draw(chart, self._defaultRequestDictionary(chart));
});
} else {
- view.plot(chart, self._defaultRequestDictionary(chart));
+ view.draw(chart, self._defaultRequestDictionary(chart));
}
});
},
@@ -229,7 +229,7 @@
'<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;"/>' +
'</span>' +
- '<svg style="height: ' + options.height + 'px;"/>' +
+ '<svg style="height: auto;"/>' +
'</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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bc16b9140ee9/
Changeset: bc16b9140ee9
User: davebgx
Date: 2014-03-07 16:38:16
Summary: More informative logging when the env.sh file doesn't meet expectations.
Affected #: 1 file
diff -r 880281e5f42210852a87724b01b4b2411e15a405 -r bc16b9140ee9762ebcb6c2fcd1be1bfee268c388 test/tool_shed/functional/test_1420_tool_dependency_environment_inheritance.py
--- a/test/tool_shed/functional/test_1420_tool_dependency_environment_inheritance.py
+++ b/test/tool_shed/functional/test_1420_tool_dependency_environment_inheritance.py
@@ -316,5 +316,7 @@
tool_dependency_version='1.53.0',
repository=package_boost_repository )
rdkit_env_file_contents = file( rdkit_env_sh, 'r' ).read()
- assert numpy_tool_dependency_path in rdkit_env_file_contents, 'Environment file for package_rdkit_2012_12_1420 does not contain numpy path.'
- assert boost_tool_dependency_path in rdkit_env_file_contents, 'Environment file for package_rdkit_2012_12_1420 does not contain boost path.'
+ if numpy_tool_dependency_path not in rdkit_env_file_contents or boost_tool_dependency_path not in rdkit_env_file_contents:
+ message = 'Environment file for package_rdkit_2012_12_1420 does not contain expected path.'
+ message += '\nExpected:\n%s\n%s\nContents:\n%s' % ( numpy_tool_dependency_path, boost_tool_dependency_path, rdkit_env_file_contents )
+ raise AssertionError( message )
https://bitbucket.org/galaxy/galaxy-central/commits/1bbc2b265fba/
Changeset: 1bbc2b265fba
Branch: stable
User: greg
Date: 2014-03-07 16:36:03
Summary: A few enhancements to the very basic tool shed statistics manager.
Affected #: 3 files
diff -r af15bddfe6854f72d828b46490f8b6c3a4f79bfb -r 1bbc2b265fba40a40ebab9cd03d91a3a7e7d2e18 lib/galaxy/webapps/tool_shed/util/shed_statistics.py
--- a/lib/galaxy/webapps/tool_shed/util/shed_statistics.py
+++ b/lib/galaxy/webapps/tool_shed/util/shed_statistics.py
@@ -1,51 +1,60 @@
-from time import strftime, gmtime
+from time import gmtime
+from time import strftime
+
class ShedCounter( object ):
def __init__( self, model ):
# TODO: Enhance the ShedCounter to retrieve information from the db instead of displaying what's currently in memory.
self.model = model
+ self.custom_datatypes = 0
self.generation_time = strftime( "%b %d, %Y", gmtime() )
+ self.deleted_repositories = 0
+ self.deprecated_repositories = 0
+ self.invalid_versions_of_tools = 0
self.repositories = 0
- #self.new_repositories = 0
- self.deleted_repositories = 0
- self.invalid_tools = 0
- self.valid_tools = 0
+ self.total_clones = 0
+ self.valid_versions_of_tools = 0
+ self.unique_owners = 0
+ self.unique_valid_tools = 0
self.workflows = 0
- self.proprietary_datatypes = 0
- self.total_clones = 0
self.generate_statistics()
+
@property
def sa_session( self ):
"""Returns a SQLAlchemy session"""
return self.model.context
+
def generate_statistics( self ):
+ self.custom_datatypes = 0
+ self.deleted_repositories = 0
+ self.deprecated_repositories = 0
+ self.invalid_versions_of_tools = 0
self.repositories = 0
- #self.new_repositories = 0
- self.deleted_repositories = 0
- self.invalid_tools = 0
- self.valid_tools = 0
+ self.total_clones = 0
+ self.unique_owners = 0
+ self.valid_versions_of_tools = 0
+ self.unique_valid_tools = 0
self.workflows = 0
- self.proprietary_datatypes = 0
- self.total_clones = 0
+ unique_user_ids = []
for repository in self.sa_session.query( self.model.Repository ):
self.repositories += 1
self.total_clones += repository.times_downloaded
is_deleted = repository.deleted
- #is_new = repository.is_new
- #if is_deleted and is_new:
if is_deleted:
self.deleted_repositories += 1
- # self.new_repositories += 1
- #elif is_deleted:
- # self.deleted_repositories += 1
- #elif is_new:
- # self.new_repositories += 1
else:
+ if repository.deprecated:
+ self.deprecated_repositories += 1
+ if repository.user_id not in unique_user_ids:
+ self.unique_owners += 1
+ unique_user_ids.append( repository.user_id )
+ processed_datatypes = []
processed_guids = []
processed_invalid_tool_configs = []
processed_relative_workflow_paths = []
- processed_datatypes = []
- # A repository's metadata_revisions are those that ignore the value of the repository_metadata.downloadable column.
+ processed_tool_ids = []
+ # A repository's metadata_revisions are those that ignore the value of the
+ # repository_metadata.downloadable column.
for metadata_revision in repository.metadata_revisions:
metadata = metadata_revision.metadata
if 'tools' in metadata:
@@ -54,13 +63,18 @@
if 'guid' in tool_dict:
guid = tool_dict[ 'guid' ]
if guid not in processed_guids:
- self.valid_tools += 1
+ self.valid_versions_of_tools += 1
processed_guids.append( guid )
+ if 'id' in tool_dict:
+ tool_id = tool_dict[ 'id' ]
+ if tool_id not in processed_tool_ids:
+ self.unique_valid_tools += 1
+ processed_tool_ids.append( tool_id )
if 'invalid_tools' in metadata:
invalid_tool_configs = metadata[ 'invalid_tools' ]
for invalid_tool_config in invalid_tool_configs:
if invalid_tool_config not in processed_invalid_tool_configs:
- self.invalid_tools += 1
+ self.invalid_versions_of_tools += 1
processed_invalid_tool_configs.append( invalid_tool_config )
if 'datatypes' in metadata:
datatypes = metadata[ 'datatypes' ]
@@ -68,7 +82,7 @@
if 'extension' in datatypes_dict:
extension = datatypes_dict[ 'extension' ]
if extension not in processed_datatypes:
- self.proprietary_datatypes += 1
+ self.custom_datatypes += 1
processed_datatypes.append( extension )
if 'workflows' in metadata:
workflows = metadata[ 'workflows' ]
diff -r af15bddfe6854f72d828b46490f8b6c3a4f79bfb -r 1bbc2b265fba40a40ebab9cd03d91a3a7e7d2e18 templates/webapps/tool_shed/admin/statistics.mako
--- a/templates/webapps/tool_shed/admin/statistics.mako
+++ b/templates/webapps/tool_shed/admin/statistics.mako
@@ -18,29 +18,37 @@
<td>Total repositories</td><td>${trans.app.shed_counter.repositories | h}</td></tr>
- ##<tr>
- ## <td>Empty repositories</td>
- ## <td>${trans.app.shed_counter.new_repositories | h}</td>
- ##</tr>
+ <tr>
+ <td>Unique owners</td>
+ <td>${trans.app.shed_counter.unique_owners | h}</td>
+ </tr>
+ <tr>
+ <td>Deprecated repositories</td>
+ <td>${trans.app.shed_counter.deprecated_repositories | h}</td>
+ </tr><tr><td>Deleted repositories</td><td>${trans.app.shed_counter.deleted_repositories | h}</td></tr><tr><td>Valid tools</td>
- <td>${trans.app.shed_counter.valid_tools | h}</td>
+ <td>${trans.app.shed_counter.unique_valid_tools | h}</td></tr><tr>
- <td>Invalid tools</td>
- <td>${trans.app.shed_counter.invalid_tools | h}</td>
+ <td>Valid versions of tools</td>
+ <td>${trans.app.shed_counter.valid_versions_of_tools | h}</td></tr><tr>
- <td>Workflows</td>
+ <td>Invalid versions of tools</td>
+ <td>${trans.app.shed_counter.invalid_versions_of_tools | h}</td>
+ </tr>
+ <tr>
+ <td>Exported Galaxy workflows</td><td>${trans.app.shed_counter.workflows | h}</td></tr><tr>
- <td>Proprietary datatypes</td>
- <td>${trans.app.shed_counter.proprietary_datatypes | h}</td>
+ <td>Custom datatypes</td>
+ <td>${trans.app.shed_counter.custom_datatypes | h}</td></tr><tr><td>Total clones</td>
diff -r af15bddfe6854f72d828b46490f8b6c3a4f79bfb -r 1bbc2b265fba40a40ebab9cd03d91a3a7e7d2e18 templates/webapps/tool_shed/index.mako
--- a/templates/webapps/tool_shed/index.mako
+++ b/templates/webapps/tool_shed/index.mako
@@ -44,7 +44,7 @@
<%def name="left_panel()"><% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %><div class="unified-panel-header" unselectable="on">
- <div class='unified-panel-header-inner'>${trans.app.shed_counter.valid_tools | h} valid tools on ${trans.app.shed_counter.generation_time | h}</div>
+ <div class='unified-panel-header-inner'>${trans.app.shed_counter.unique_valid_tools | h} valid tools on ${trans.app.shed_counter.generation_time | h}</div></div><div class="unified-panel-body"><div class="toolMenu">
https://bitbucket.org/galaxy/galaxy-central/commits/feec63e4fc98/
Changeset: feec63e4fc98
User: davebgx
Date: 2014-03-07 16:39:08
Summary: Merge with stable.
Affected #: 0 files
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: A few enhancements to the very basic tool shed statistics manager.
by commits-noreply@bitbucket.org 07 Mar '14
by commits-noreply@bitbucket.org 07 Mar '14
07 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/880281e5f422/
Changeset: 880281e5f422
User: greg
Date: 2014-03-07 16:36:03
Summary: A few enhancements to the very basic tool shed statistics manager.
Affected #: 3 files
diff -r 9850950581c7792409ceb0fbfea06bac8fcda6f7 -r 880281e5f42210852a87724b01b4b2411e15a405 lib/galaxy/webapps/tool_shed/util/shed_statistics.py
--- a/lib/galaxy/webapps/tool_shed/util/shed_statistics.py
+++ b/lib/galaxy/webapps/tool_shed/util/shed_statistics.py
@@ -1,51 +1,60 @@
-from time import strftime, gmtime
+from time import gmtime
+from time import strftime
+
class ShedCounter( object ):
def __init__( self, model ):
# TODO: Enhance the ShedCounter to retrieve information from the db instead of displaying what's currently in memory.
self.model = model
+ self.custom_datatypes = 0
self.generation_time = strftime( "%b %d, %Y", gmtime() )
+ self.deleted_repositories = 0
+ self.deprecated_repositories = 0
+ self.invalid_versions_of_tools = 0
self.repositories = 0
- #self.new_repositories = 0
- self.deleted_repositories = 0
- self.invalid_tools = 0
- self.valid_tools = 0
+ self.total_clones = 0
+ self.valid_versions_of_tools = 0
+ self.unique_owners = 0
+ self.unique_valid_tools = 0
self.workflows = 0
- self.proprietary_datatypes = 0
- self.total_clones = 0
self.generate_statistics()
+
@property
def sa_session( self ):
"""Returns a SQLAlchemy session"""
return self.model.context
+
def generate_statistics( self ):
+ self.custom_datatypes = 0
+ self.deleted_repositories = 0
+ self.deprecated_repositories = 0
+ self.invalid_versions_of_tools = 0
self.repositories = 0
- #self.new_repositories = 0
- self.deleted_repositories = 0
- self.invalid_tools = 0
- self.valid_tools = 0
+ self.total_clones = 0
+ self.unique_owners = 0
+ self.valid_versions_of_tools = 0
+ self.unique_valid_tools = 0
self.workflows = 0
- self.proprietary_datatypes = 0
- self.total_clones = 0
+ unique_user_ids = []
for repository in self.sa_session.query( self.model.Repository ):
self.repositories += 1
self.total_clones += repository.times_downloaded
is_deleted = repository.deleted
- #is_new = repository.is_new
- #if is_deleted and is_new:
if is_deleted:
self.deleted_repositories += 1
- # self.new_repositories += 1
- #elif is_deleted:
- # self.deleted_repositories += 1
- #elif is_new:
- # self.new_repositories += 1
else:
+ if repository.deprecated:
+ self.deprecated_repositories += 1
+ if repository.user_id not in unique_user_ids:
+ self.unique_owners += 1
+ unique_user_ids.append( repository.user_id )
+ processed_datatypes = []
processed_guids = []
processed_invalid_tool_configs = []
processed_relative_workflow_paths = []
- processed_datatypes = []
- # A repository's metadata_revisions are those that ignore the value of the repository_metadata.downloadable column.
+ processed_tool_ids = []
+ # A repository's metadata_revisions are those that ignore the value of the
+ # repository_metadata.downloadable column.
for metadata_revision in repository.metadata_revisions:
metadata = metadata_revision.metadata
if 'tools' in metadata:
@@ -54,13 +63,18 @@
if 'guid' in tool_dict:
guid = tool_dict[ 'guid' ]
if guid not in processed_guids:
- self.valid_tools += 1
+ self.valid_versions_of_tools += 1
processed_guids.append( guid )
+ if 'id' in tool_dict:
+ tool_id = tool_dict[ 'id' ]
+ if tool_id not in processed_tool_ids:
+ self.unique_valid_tools += 1
+ processed_tool_ids.append( tool_id )
if 'invalid_tools' in metadata:
invalid_tool_configs = metadata[ 'invalid_tools' ]
for invalid_tool_config in invalid_tool_configs:
if invalid_tool_config not in processed_invalid_tool_configs:
- self.invalid_tools += 1
+ self.invalid_versions_of_tools += 1
processed_invalid_tool_configs.append( invalid_tool_config )
if 'datatypes' in metadata:
datatypes = metadata[ 'datatypes' ]
@@ -68,7 +82,7 @@
if 'extension' in datatypes_dict:
extension = datatypes_dict[ 'extension' ]
if extension not in processed_datatypes:
- self.proprietary_datatypes += 1
+ self.custom_datatypes += 1
processed_datatypes.append( extension )
if 'workflows' in metadata:
workflows = metadata[ 'workflows' ]
diff -r 9850950581c7792409ceb0fbfea06bac8fcda6f7 -r 880281e5f42210852a87724b01b4b2411e15a405 templates/webapps/tool_shed/admin/statistics.mako
--- a/templates/webapps/tool_shed/admin/statistics.mako
+++ b/templates/webapps/tool_shed/admin/statistics.mako
@@ -18,29 +18,37 @@
<td>Total repositories</td><td>${trans.app.shed_counter.repositories | h}</td></tr>
- ##<tr>
- ## <td>Empty repositories</td>
- ## <td>${trans.app.shed_counter.new_repositories | h}</td>
- ##</tr>
+ <tr>
+ <td>Unique owners</td>
+ <td>${trans.app.shed_counter.unique_owners | h}</td>
+ </tr>
+ <tr>
+ <td>Deprecated repositories</td>
+ <td>${trans.app.shed_counter.deprecated_repositories | h}</td>
+ </tr><tr><td>Deleted repositories</td><td>${trans.app.shed_counter.deleted_repositories | h}</td></tr><tr><td>Valid tools</td>
- <td>${trans.app.shed_counter.valid_tools | h}</td>
+ <td>${trans.app.shed_counter.unique_valid_tools | h}</td></tr><tr>
- <td>Invalid tools</td>
- <td>${trans.app.shed_counter.invalid_tools | h}</td>
+ <td>Valid versions of tools</td>
+ <td>${trans.app.shed_counter.valid_versions_of_tools | h}</td></tr><tr>
- <td>Workflows</td>
+ <td>Invalid versions of tools</td>
+ <td>${trans.app.shed_counter.invalid_versions_of_tools | h}</td>
+ </tr>
+ <tr>
+ <td>Exported Galaxy workflows</td><td>${trans.app.shed_counter.workflows | h}</td></tr><tr>
- <td>Proprietary datatypes</td>
- <td>${trans.app.shed_counter.proprietary_datatypes | h}</td>
+ <td>Custom datatypes</td>
+ <td>${trans.app.shed_counter.custom_datatypes | h}</td></tr><tr><td>Total clones</td>
diff -r 9850950581c7792409ceb0fbfea06bac8fcda6f7 -r 880281e5f42210852a87724b01b4b2411e15a405 templates/webapps/tool_shed/index.mako
--- a/templates/webapps/tool_shed/index.mako
+++ b/templates/webapps/tool_shed/index.mako
@@ -44,7 +44,7 @@
<%def name="left_panel()"><% can_review_repositories = trans.app.security_agent.user_can_review_repositories( trans.user ) %><div class="unified-panel-header" unselectable="on">
- <div class='unified-panel-header-inner'>${trans.app.shed_counter.valid_tools | h} valid tools on ${trans.app.shed_counter.generation_time | h}</div>
+ <div class='unified-panel-header-inner'>${trans.app.shed_counter.unique_valid_tools | h} valid tools on ${trans.app.shed_counter.generation_time | h}</div></div><div class="unified-panel-body"><div class="toolMenu">
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: Make sure metadata is associated with a repository when displaying values in the Verified column in the tool shed.
by commits-noreply@bitbucket.org 07 Mar '14
by commits-noreply@bitbucket.org 07 Mar '14
07 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9850950581c7/
Changeset: 9850950581c7
User: greg
Date: 2014-03-07 16:00:40
Summary: Make sure metadata is associated with a repository when displaying values in the Verified column in the tool shed.
Affected #: 1 file
diff -r 49d20516d8605f36590729564a83d188ec4d29bd -r 9850950581c7792409ceb0fbfea06bac8fcda6f7 lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -163,12 +163,13 @@
# This column will display the value associated with the currently displayed metadata revision.
if repository.type == rt_util.UNRESTRICTED:
try:
- displayed_metadata_revision = repository.metadata_revisions[ -1 ]
- if displayed_metadata_revision.includes_tools:
- if displayed_metadata_revision.tools_functionally_correct:
- return 'yes'
- else:
- return 'no'
+ if len( repository.metadata_revisions ) > 0:
+ displayed_metadata_revision = repository.metadata_revisions[ -1 ]
+ if displayed_metadata_revision.includes_tools:
+ if displayed_metadata_revision.tools_functionally_correct:
+ return 'yes'
+ else:
+ return 'no'
return 'n/a'
except Exception, e:
log.exception( str( e ) )
@@ -176,23 +177,23 @@
else:
# Here repository.type must be rt_util.TOOL_DEPENDENCY_DEFINITION.
try:
- displayed_metadata_revision = repository.metadata_revisions[ -1 ]
- if displayed_metadata_revision.test_install_error:
- return 'no'
- tool_test_results = listify( displayed_metadata_revision.tool_test_results )
- if len( tool_test_results ) > 0:
- last_tool_test_result = tool_test_results[ 0 ]
- installation_error_dict = last_tool_test_result.get( 'installation_errors', {} )
- if len( installation_error_dict ) > 0:
- current_repository_installation_error_dicts = installation_error_dict.get( 'current_repository', [] )
- if len( current_repository_installation_error_dicts ) > 0:
- return 'no'
+ if len( repository.metadata_revisions ) > 0:
+ displayed_metadata_revision = repository.metadata_revisions[ -1 ]
+ if displayed_metadata_revision.test_install_error:
+ return 'no'
+ tool_test_results = listify( displayed_metadata_revision.tool_test_results )
+ if len( tool_test_results ) > 0:
+ last_tool_test_result = tool_test_results[ 0 ]
+ installation_error_dict = last_tool_test_result.get( 'installation_errors', {} )
+ if len( installation_error_dict ) > 0:
+ current_repository_installation_error_dicts = installation_error_dict.get( 'current_repository', [] )
+ if len( current_repository_installation_error_dicts ) > 0:
+ return 'no'
+ else:
+ return 'yes'
else:
return 'yes'
- else:
- return 'yes'
- else:
- return 'no'
+ return 'no'
except Exception, e:
log.exception( str( e ) )
return 'unknown'
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/af15bddfe685/
Changeset: af15bddfe685
Branch: stable
User: davebgx
Date: 2014-03-07 15:42:39
Summary: Clean up another incorrectly resolved merge conflict.
Affected #: 1 file
diff -r 0bd594fc429dbad899a86495a3ab8683d6184159 -r af15bddfe6854f72d828b46490f8b6c3a4f79bfb lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -420,7 +420,6 @@
for tarball_name in tarball_names:
cmd = '''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
Rscript -e "install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)"''' % ( str( tarball_name ) )
- ( str( tarball_name ) )
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
return_code = handle_command( app, tool_dependency, install_dir, cmd )
if return_code:
https://bitbucket.org/galaxy/galaxy-central/commits/49d20516d860/
Changeset: 49d20516d860
User: davebgx
Date: 2014-03-07 15:45:24
Summary: Merge stable.
Affected #: 1 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
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0bd594fc429d/
Changeset: 0bd594fc429d
Branch: stable
User: greg
Date: 2014-03-06 17:39:48
Summary: Fixes to handle case where a tool dependency recipe defines an <actions_group> tag set for installing pre-compiled binaries which fail to install, so the fall back recipe for installing and compileing from souce is used. Prior to this change set, the recipe from source would not work, but the install process would finish in such a way that the recipe seemed to work.
Affected #: 5 files
diff -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 -r 0bd594fc429dbad899a86495a3ab8683d6184159 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
@@ -1111,10 +1111,12 @@
no_changes_checked = CheckboxField.is_checked( no_changes )
install_repository_dependencies = CheckboxField.is_checked( kwd.get( 'install_repository_dependencies', '' ) )
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
- shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
+ shed_tool_conf, tool_path, relative_install_dir = \
+ suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
repository_clone_url = suc.generate_clone_url_for_installed_repository( trans.app, tool_shed_repository )
- clone_dir = os.path.join( tool_path, suc.generate_tool_shed_repository_install_dir( repository_clone_url,
- tool_shed_repository.installed_changeset_revision ) )
+ clone_dir = os.path.join( tool_path,
+ suc.generate_tool_shed_repository_install_dir( repository_clone_url,
+ tool_shed_repository.installed_changeset_revision ) )
relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name )
tool_shed_url = suc.get_url_from_tool_shed( trans.app, tool_shed_repository.tool_shed )
tool_section = None
@@ -1123,7 +1125,8 @@
tool_panel_section_key = None
tool_panel_section_keys = []
metadata = tool_shed_repository.metadata
- # Keep track of tool dependencies defined for the current repository or those defined for any of it's repository dependencies.
+ # Keep track of tool dependencies defined for the current repository or those defined for any of
+ # it's repository dependencies.
includes_tool_dependencies = tool_shed_repository.includes_tool_dependencies
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle the selected tool panel location for loading tools included in the tool shed repository.
@@ -1137,7 +1140,8 @@
# Just in case the tool_section.id differs from tool_panel_section_id, which it shouldn't...
tool_panel_section_id = str( tool_section.id )
if tool_shed_repository.status == trans.install_model.ToolShedRepository.installation_status.UNINSTALLED:
- # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall so the repository_installation_updater will function.
+ # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall
+ # so the repository_installation_updater will function.
tool_shed_repository = suc.create_or_update_tool_shed_repository( trans.app,
tool_shed_repository.name,
tool_shed_repository.description,
@@ -1163,7 +1167,8 @@
# Entering this else block occurs only if the tool_shed_repository does not include any valid tools.
if install_repository_dependencies:
repository_dependencies = \
- repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans, tool_shed_repository )
+ repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans,
+ tool_shed_repository )
else:
repository_dependencies = None
if metadata:
@@ -1220,7 +1225,8 @@
clause_list = []
for tsr_id in tsr_ids:
clause_list.append( trans.install_model.ToolShedRepository.table.c.id == tsr_id )
- query = trans.install_model.context.current.query( trans.install_model.ToolShedRepository ).filter( or_( *clause_list ) )
+ query = trans.install_model.context.current.query( trans.install_model.ToolShedRepository ) \
+ .filter( or_( *clause_list ) )
return trans.fill_template( 'admin/tool_shed_repository/initiate_repository_installation.mako',
encoded_kwd=encoded_kwd,
query=query,
@@ -1378,7 +1384,9 @@
raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
readme_files_dict = json.from_json_string( raw_text )
tool_dependencies = metadata.get( 'tool_dependencies', None )
- repository_dependencies = repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans, tool_shed_repository )
+ repository_dependencies = \
+ repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans,
+ tool_shed_repository )
repo_info_dict = repository_util.create_repo_info_dict( trans=trans,
repository_clone_url=repository_clone_url,
changeset_revision=tool_shed_repository.installed_changeset_revision,
diff -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 -r 0bd594fc429dbad899a86495a3ab8683d6184159 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
@@ -30,36 +30,43 @@
log = logging.getLogger( __name__ )
-def create_repo_info_dict( trans, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None, repository=None,
- repository_metadata=None, tool_dependencies=None, repository_dependencies=None ):
+def create_repo_info_dict( trans, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None,
+ repository=None, repository_metadata=None, tool_dependencies=None, repository_dependencies=None ):
"""
- Return a dictionary that includes all of the information needed to install a repository into a local Galaxy instance. The dictionary will also
- contain the recursive list of repository dependencies defined for the repository, as well as the defined tool dependencies.
+ Return a dictionary that includes all of the information needed to install a repository into a local
+ Galaxy instance. The dictionary will also contain the recursive list of repository dependencies defined
+ for the repository, as well as the defined tool dependencies.
This method is called from Galaxy under three scenarios:
- 1. During the tool shed repository installation process via the tool shed's get_repository_information() method. In this case both the received
- repository and repository_metadata will be objects., but tool_dependencies and repository_dependencies will be None
- 2. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with no updates available. In this case, both
- repository and repository_metadata will be None, but tool_dependencies and repository_dependencies will be objects previously retrieved from the
- tool shed if the repository includes definitions for them.
- 3. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with updates available. In this case, this
- method is reached via the tool shed's get_updated_repository_information() method, and both repository and repository_metadata will be objects
- but tool_dependencies and repository_dependencies will be None.
+ 1. During the tool shed repository installation process via the tool shed's get_repository_information()
+ method. In this case both the received repository and repository_metadata will be objects., but
+ tool_dependencies and repository_dependencies will be None.
+ 2. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with no
+ updates available. In this case, both repository and repository_metadata will be None, but tool_dependencies
+ and repository_dependencies will be objects previously retrieved from the tool shed if the repository includes
+ definitions for them.
+ 3. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with updates
+ available. In this case, this method is reached via the tool shed's get_updated_repository_information()
+ method, and both repository and repository_metadata will be objects but tool_dependencies and
+ repository_dependencies will be None.
"""
repo_info_dict = {}
repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
if trans.webapp.name == 'tool_shed':
# We're in the tool shed.
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
+ trans.security.encode_id( repository.id ),
+ changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
if metadata:
+ toolshed_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
# Get a dictionary of all repositories upon which the contents of the received repository depends.
repository_dependencies = \
repository_dependency_util.get_repository_dependencies_for_changeset_revision( trans=trans,
repository=repository,
repository_metadata=repository_metadata,
- toolshed_base_url=str( web.url_for( '/', qualified=True ) ).rstrip( '/' ),
+ toolshed_base_url=toolshed_url,
key_rd_dicts_to_be_processed=None,
all_repository_dependencies=None,
handled_key_rd_dicts=None,
diff -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 -r 0bd594fc429dbad899a86495a3ab8683d6184159 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -132,7 +132,6 @@
# Explicitly set the file to the received mode if valid.
with settings( hide( 'everything' ), warn_only=True ):
local( 'chmod +x %s' % file_path )
- return_code = 0
# 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 ]
@@ -152,7 +151,6 @@
if return_code:
# Return upon the first error encountered.
return return_code
- return return_code
def filter_actions_after_binary_installation( actions ):
'''Filter out actions that should not be processed if a binary download succeeded.'''
@@ -189,13 +187,15 @@
def handle_environment_variables( app, tool_dependency, install_dir, env_var_dict, set_prior_environment_commands ):
"""
- This method works with with a combination of three tool dependency definition tag sets, which are defined in the tool_dependencies.xml file in the
- order discussed here. The example for this discussion is the tool_dependencies.xml file contained in the osra repository, which is available at:
+ This method works with with a combination of three tool dependency definition tag sets, which are defined
+ in the tool_dependencies.xml file in the order discussed here. The example for this discussion is the
+ tool_dependencies.xml file contained in the osra repository, which is available at:
http://testtoolshed.g2.bx.psu.edu/view/bgruening/osra
- The first tag set defines a complex repository dependency like this. This tag set ensures that changeset revision XXX of the repository named
- package_graphicsmagick_1_3 owned by YYY in the tool shed ZZZ has been previously installed.
+ The first tag set defines a complex repository dependency like this. This tag set ensures that changeset
+ revision XXX of the repository named package_graphicsmagick_1_3 owned by YYY in the tool shed ZZZ has been
+ previously installed.
<tool_dependency><package name="graphicsmagick" version="1.3.18">
@@ -203,19 +203,21 @@
</package>
...
- * By the way, there is an env.sh file associated with version 1.3.18 of the graphicsmagick package which looks something like this (we'll reference
- this file later in this discussion.
+ * By the way, there is an env.sh file associated with version 1.3.18 of the graphicsmagick package which looks
+ something like this (we'll reference this file later in this discussion.
----
GRAPHICSMAGICK_ROOT_DIR=/<my configured tool dependency path>/graphicsmagick/1.3.18/YYY/package_graphicsmagick_1_3/XXX/gmagick;
export GRAPHICSMAGICK_ROOT_DIR
----
- The second tag set defines a specific package dependency that has been previously installed (guaranteed by the tag set discussed above) and compiled,
- where the compiled dependency is needed by the tool dependency currently being installed (osra version 2.0.0 in this case) and complied in order for
- it's installation and compilation to succeed. This tag set is contained within the <package name="osra" version="2.0.0"> tag set, which implies that
- version 2.0.0 of the osra package requires version 1.3.18 of the graphicsmagick package in order to successfully compile. When this tag set is handled,
- one of the effects is that the env.sh file associated with graphicsmagick version 1.3.18 is "sourced", which undoubtedly sets or alters certain environment
- variables (e.g. PATH, PYTHONPATH, etc).
+ The second tag set defines a specific package dependency that has been previously installed (guaranteed by the
+ tag set discussed above) and compiled, where the compiled dependency is needed by the tool dependency currently
+ being installed (osra version 2.0.0 in this case) and complied in order for it's installation and compilation to
+ succeed. This tag set is contained within the <package name="osra" version="2.0.0"> tag set, which implies that
+ version 2.0.0 of the osra package requires version 1.3.18 of the graphicsmagick package in order to successfully
+ compile. When this tag set is handled, one of the effects is that the env.sh file associated with graphicsmagick
+ version 1.3.18 is "sourced", which undoubtedly sets or alters certain environment variables (e.g. PATH, PYTHONPATH,
+ etc).
<!-- populate the environment variables from the dependent repositories --><action type="set_environment_for_install">
@@ -224,11 +226,12 @@
</repository></action>
- The third tag set enables discovery of the same required package dependency discussed above for correctly compiling the osra version 2.0.0 package, but
- in this case the package can be discovered at tool execution time. Using the $ENV[] option as shown in this example, the value of the environment
- variable named GRAPHICSMAGICK_ROOT_DIR (which was set in the environment using the second tag set described above) will be used to automatically alter
- the env.sh file associated with the osra version 2.0.0 tool dependency when it is installed into Galaxy. * Refer to where we discussed the env.sh file
- for version 1.3.18 of the graphicsmagick package above.
+ The third tag set enables discovery of the same required package dependency discussed above for correctly compiling
+ the osra version 2.0.0 package, but in this case the package can be discovered at tool execution time. Using the
+ $ENV[] option as shown in this example, the value of the environment variable named GRAPHICSMAGICK_ROOT_DIR (which
+ was set in the environment using the second tag set described above) will be used to automatically alter the env.sh
+ file associated with the osra version 2.0.0 tool dependency when it is installed into Galaxy. * Refer to where we
+ discussed the env.sh file for version 1.3.18 of the graphicsmagick package above.
<action type="set_environment"><environment_variable action="prepend_to" name="LD_LIBRARY_PATH">$ENV[GRAPHICSMAGICK_ROOT_DIR]/lib/</environment_variable>
@@ -238,8 +241,9 @@
<environment_variable action="set_to" name="OSRA_DATA_FILES">$INSTALL_DIR/share</environment_variable></action>
- The above tag will produce an env.sh file for version 2.0.0 of the osra package when it it installed into Galaxy that looks something like this. Notice
- that the path to the gmagick binary is included here since it expands the defined $ENV[GRAPHICSMAGICK_ROOT_DIR] value in the above tag set.
+ The above tag will produce an env.sh file for version 2.0.0 of the osra package when it it installed into Galaxy
+ that looks something like this. Notice that the path to the gmagick binary is included here since it expands the
+ defined $ENV[GRAPHICSMAGICK_ROOT_DIR] value in the above tag set.
----
LD_LIBRARY_PATH=/<my configured tool dependency path>/graphicsmagick/1.3.18/YYY/package_graphicsmagick_1_3/XXX/gmagick/lib/:$LD_LIBRARY_PATH;
@@ -416,6 +420,7 @@
for tarball_name in tarball_names:
cmd = '''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
Rscript -e "install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)"''' % ( str( tarball_name ) )
+ ( str( tarball_name ) )
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
return_code = handle_command( app, tool_dependency, install_dir, cmd )
if return_code:
@@ -528,7 +533,8 @@
elif os.path.exists( os.path.join( tmp_work_dir, 'Build.PL' ) ):
cmd += '''perl Build.PL --install_base $INSTALL_DIR && perl Build && perl Build install'''
else:
- log.debug( 'No Makefile.PL or Build.PL file found in %s. Skipping installation of %s.' % ( url, perl_package_name ) )
+ log.debug( 'No Makefile.PL or Build.PL file found in %s. Skipping installation of %s.' % \
+ ( url, perl_package_name ) )
return tool_dependency
with lcd( tmp_work_dir ):
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
diff -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 -r 0bd594fc429dbad899a86495a3ab8683d6184159 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -300,7 +300,10 @@
return tool_dependency
def install_package( app, elem, tool_shed_repository, tool_dependencies=None, from_install_manager=False ):
- # The value of tool_dependencies is a partial or full list of ToolDependency records associated with the tool_shed_repository.
+ """
+ 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.
@@ -363,8 +366,8 @@
type='package',
status=app.install_model.ToolDependency.installation_status.INSTALLING,
set_status=True )
- # Get the information about the current platform in case the tool dependency definition includes tag sets for installing
- # compiled binaries.
+ # 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.
@@ -372,24 +375,29 @@
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.
+ # 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 in_actions_group, actions_elems in actions_elem_tuples:
+ 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.
+ # 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 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 look here because there may be <action> tags at the end of the <actions_group>
- # tag set that must be processed.
+ # 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.
@@ -400,41 +408,50 @@
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.
+ # 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.
+ # 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 no <actions> tags have been defined that match our current platform, or none of the matching
- # <actions> tags resulted in a successful tool dependency status, proceed with one and only one
- # <actions> tag that is not defined to be platform-specific.
- if not binary_installed:
- log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % str( tool_dependency.name ) )
- # Make sure to reset for installation if attempt at binary installation resulted in an error.
- can_install = True
- if tool_dependency.status != app.install_model.ToolDependency.installation_status.NEVER_INSTALLED:
- removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
- if not removed:
- log.debug( 'Error removing old files from installation directory %s: %s' % \
- ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
- can_install = False
- if can_install:
+ 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_dependency,
install_dir,
package_name=package_name,
actions_elem=actions_elem,
action_elem=None )
- # Perform any final actions that have been defined within the actions_group tag set, but outside of
- # an <actions> tag, such as a set_environment entry, or a download_file or download_by_url command to
- # retrieve extra data for this tool dependency. Only do this if the tool dependency is not in an error
- # state, otherwise skip this action.
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_dependency,
install_dir,
@@ -442,9 +459,9 @@
actions_elem=None,
action_elem=actions_elem )
else:
- # <actions> tags outside of an <actions_group> tag shall not check os or architecture, and if the attributes are
- # defined, they will be ignored. All <actions> tags outside of an <actions_group> tag set shall always be processed.
- # This is the default and original behavior of the install_package method.
+ # 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_dependency,
install_dir,
diff -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 -r 0bd594fc429dbad899a86495a3ab8683d6184159 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -227,18 +227,21 @@
return file_path
return None
-def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url, metadata_dict,
- status, current_changeset_revision=None, owner='', dist_to_shed=False ):
+def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url,
+ metadata_dict, status, current_changeset_revision=None, owner='', dist_to_shed=False ):
"""
- Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed,
- repository name and owner does not exist, create a new record with the received information.
+ Update a tool shed repository record in the Galaxy database with the new information received.
+ If a record defined by the received tool shed, repository name and owner does not exist, create
+ a new record with the received information.
"""
- # The received value for dist_to_shed will be True if the InstallManager is installing a repository that contains tools or datatypes that used
- # to be in the Galaxy distribution, but have been moved to the main Galaxy tool shed.
+ # The received value for dist_to_shed will be True if the InstallManager is installing a repository
+ # that contains tools or datatypes that used to be in the Galaxy distribution, but have been moved
+ # to the main Galaxy tool shed.
if current_changeset_revision is None:
- # The current_changeset_revision is not passed if a repository is being installed for the first time. If a previously installed repository
- # was later uninstalled, this value should be received as the value of that change set to which the repository had been updated just prior
- # to it being uninstalled.
+ # The current_changeset_revision is not passed if a repository is being installed for the first
+ # time. If a previously installed repository was later uninstalled, this value should be received
+ # as the value of that change set to which the repository had been updated just prior to it being
+ # uninstalled.
current_changeset_revision = installed_changeset_revision
context = app.install_model.context
tool_shed = get_tool_shed_from_clone_url( repository_clone_url )
@@ -255,9 +258,14 @@
deleted = False
uninstalled = False
tool_shed_repository = \
- get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app, tool_shed, name, owner, installed_changeset_revision )
+ get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app,
+ tool_shed,
+ name,
+ owner,
+ installed_changeset_revision )
if tool_shed_repository:
- log.debug( "Updating an existing row for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
+ log.debug( "Updating an existing row for repository '%s' in the tool_shed_repository table, status set to '%s'." % \
+ ( str( name ), str( status ) ) )
tool_shed_repository.description = description
tool_shed_repository.changeset_revision = current_changeset_revision
tool_shed_repository.ctx_rev = ctx_rev
@@ -267,7 +275,8 @@
tool_shed_repository.uninstalled = uninstalled
tool_shed_repository.status = status
else:
- log.debug( "Adding new row for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
+ log.debug( "Adding new row for repository '%s' in the tool_shed_repository table, status set to '%s'." % \
+ ( str( name ), str( status ) ) )
tool_shed_repository = \
app.install_model.ToolShedRepository( tool_shed=tool_shed,
name=name,
@@ -1028,8 +1037,8 @@
owner=owner,
changeset_revision=changeset_revision )
if not repository:
- # The received changeset_revision is no longer installable, so get the next changeset_revision in the repository's changelog in the
- # tool shed that is associated with repository_metadata.
+ # The received changeset_revision is no longer installable, so get the next changeset_revision
+ # in the repository's changelog in the tool shed that is associated with repository_metadata.
tool_shed_url = get_url_from_tool_shed( app, tool_shed )
url = url_join( tool_shed_url,
'repository/next_installable_changeset_revision?name=%s&owner=%s&changeset_revision=%s' % \
@@ -1305,7 +1314,10 @@
.first()
def get_tool_shed_repository_by_shed_name_owner_changeset_revision( app, tool_shed, name, owner, changeset_revision ):
- """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and current changeet_revision."""
+ """
+ Return a tool shed repository database record defined by the combination of a tool_shed, repository name,
+ repository owner and current changeet_revision.
+ """
# This method is used only in Galaxy, not the tool shed.
repository_query = __repository_query( app )
if tool_shed.find( '//' ) > 0:
@@ -1319,7 +1331,10 @@
.first()
def get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app, tool_shed, name, owner, installed_changeset_revision ):
- """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and installed_changeet_revision."""
+ """
+ Return a tool shed repository database record defined by the combination of a tool_shed,
+ repository name, repository owner and installed_changeet_revision.
+ """
# This method is used only in Galaxy, not the tool shed.
repository_query = __repository_query( app )
if tool_shed.find( '//' ) > 0:
https://bitbucket.org/galaxy/galaxy-central/commits/45b4499e1b0f/
Changeset: 45b4499e1b0f
User: davebgx
Date: 2014-03-07 15:25:51
Summary: Merge stable.
Affected #: 2 files
diff -r af5577a24c155fa04aa607ff2fec283634df2fb0 -r 45b4499e1b0f90f0bfa7b6bdc93f408cfb3b7d38 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -938,7 +938,10 @@
return tool_dependency
def log_results( command, fabric_AttributeString, file_path ):
- """Write attributes of fabric.operations._AttributeString to a specified log file."""
+ """
+ Write attributes of fabric.operations._AttributeString (which is the output of executing command using fabric's local() method)
+ to a specified log file.
+ """
if os.path.exists( file_path ):
logfile = open( file_path, 'ab' )
else:
https://bitbucket.org/galaxy/galaxy-central/commits/0eb68f4ec8ca/
Changeset: 0eb68f4ec8ca
User: davebgx
Date: 2014-03-07 15:28:30
Summary: Fix incorrectly merged comment.
Affected #: 1 file
diff -r 45b4499e1b0f90f0bfa7b6bdc93f408cfb3b7d38 -r 0eb68f4ec8ca0806991c7a1bdccf96350f3f0ef9 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -938,10 +938,7 @@
return tool_dependency
def log_results( command, fabric_AttributeString, file_path ):
- """
- Write attributes of fabric.operations._AttributeString (which is the output of executing command using fabric's local() method)
- to a specified log file.
- """
+ """Write attributes of fabric.operations._AttributeString to a specified log file."""
if os.path.exists( file_path ):
logfile = open( file_path, 'ab' )
else:
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: Prevent 'unicode' strings being sent to pbs library as hostname.
by commits-noreply@bitbucket.org 07 Mar '14
by commits-noreply@bitbucket.org 07 Mar '14
07 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/af5577a24c15/
Changeset: af5577a24c15
User: jmchilton
Date: 2014-03-07 15:18:16
Summary: Prevent 'unicode' strings being sent to pbs library as hostname.
Full details here:
http://dev.list.galaxyproject.org/pbs-runner-deserializes-server-names-as-u…
Not sure this is the right thing to do - so I would welcome advice/comments.
Affected #: 1 file
diff -r 1b8b87437c7e0b8e7a9f6a51b0ec910237e514f1 -r af5577a24c155fa04aa607ff2fec283634df2fb0 lib/galaxy/jobs/runners/pbs.py
--- a/lib/galaxy/jobs/runners/pbs.py
+++ b/lib/galaxy/jobs/runners/pbs.py
@@ -5,6 +5,7 @@
from datetime import timedelta
from galaxy import model
+from galaxy import util
from galaxy.util.bunch import Bunch
from galaxy.util import DATABASE_MAX_STRING_SIZE, shrink_stream_by_size
from galaxy.jobs import JobDestination
@@ -233,7 +234,7 @@
# Explicitly set the determined PBS destination in the persisted job destination for recovery
job_destination.params['destination'] = '%s@%s' % (pbs_queue_name or '', pbs_server_name)
- c = pbs.pbs_connect( pbs_server_name )
+ c = pbs.pbs_connect( util.smart_str( pbs_server_name ) )
if c <= 0:
errno, text = pbs.error()
job_wrapper.fail( "Unable to queue job for execution. Resubmitting the job may succeed." )
@@ -449,7 +450,7 @@
servers.append( pbs_server_name )
pbs_job_state.check_count += 1
for pbs_server_name in servers:
- c = pbs.pbs_connect( pbs_server_name )
+ c = pbs.pbs_connect( util.smart_str( pbs_server_name ) )
if c <= 0:
log.debug("connection to PBS server %s for state check failed" % pbs_server_name )
failures.append( pbs_server_name )
@@ -482,7 +483,7 @@
Returns the state of a single job, used to make sure a job is
really dead.
"""
- c = pbs.pbs_connect( pbs_server_name )
+ c = pbs.pbs_connect( util.smart_str( pbs_server_name ) )
if c <= 0:
log.debug("connection to PBS server %s for state check failed" % pbs_server_name )
return None
@@ -584,7 +585,7 @@
log.debug("(%s) Job queued but no destination stored in job params, cannot delete"
% job_tag )
return
- c = pbs.pbs_connect( pbs_server_name )
+ c = pbs.pbs_connect( util.smart_str( pbs_server_name ) )
if c <= 0:
log.debug("(%s) Connection to PBS server for job delete failed"
% job_tag )
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: Fix column number
by commits-noreply@bitbucket.org 07 Mar '14
by commits-noreply@bitbucket.org 07 Mar '14
07 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1b8b87437c7e/
Changeset: 1b8b87437c7e
User: guerler
Date: 2014-03-07 02:24:08
Summary: Charts: Fix column number
Affected #: 4 files
diff -r c58e14ae86d182f8152edbfe2569857da54ccb49 -r 1b8b87437c7e0b8e7a9f6a51b0ec910237e514f1 config/plugins/visualizations/charts/static/charts/histogram.js
--- a/config/plugins/visualizations/charts/static/charts/histogram.js
+++ b/config/plugins/visualizations/charts/static/charts/histogram.js
@@ -34,7 +34,11 @@
self.d3_chart = nv.models.multiBarChart();
self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
+ .axisLabel('Breaks');
+
+ self.d3_chart.yAxis.tickFormat(d3.format('.3f'))
+ .axisLabel('Frequency')
+ .axisLabelDistance(30);
self.options.svg.datum(data)
.call(self.d3_chart);
diff -r c58e14ae86d182f8152edbfe2569857da54ccb49 -r 1b8b87437c7e0b8e7a9f6a51b0ec910237e514f1 config/plugins/visualizations/charts/static/library/datasets.js
--- a/config/plugins/visualizations/charts/static/library/datasets.js
+++ b/config/plugins/visualizations/charts/static/library/datasets.js
@@ -115,7 +115,7 @@
// read value from row
var v = row[index];
- if(isNaN(v)) {
+ if(isNaN(v) || !v) {
v = 0;
}
diff -r c58e14ae86d182f8152edbfe2569857da54ccb49 -r 1b8b87437c7e0b8e7a9f6a51b0ec910237e514f1 config/plugins/visualizations/charts/static/models/types.js
--- a/config/plugins/visualizations/charts/static/models/types.js
+++ b/config/plugins/visualizations/charts/static/models/types.js
@@ -14,6 +14,14 @@
}
}
},
+ 'horizontal' : {
+ title : 'Bar diagram (horizontal)',
+ columns : {
+ y : {
+ title : 'Values for y-axis'
+ }
+ }
+ },
'histogram' : {
title : 'Histogram',
mode : 'execute',
@@ -23,14 +31,6 @@
}
}
},
- 'horizontal' : {
- title : 'Bar diagram (horizontal)',
- columns : {
- y : {
- title : 'Values for y-axis'
- }
- }
- },
'line' : {
title : 'Line chart',
columns : {
diff -r c58e14ae86d182f8152edbfe2569857da54ccb49 -r 1b8b87437c7e0b8e7a9f6a51b0ec910237e514f1 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
@@ -246,13 +246,12 @@
var group_index = 0;
chart.groups.each(function(group) {
for (var key in chart_settings.columns) {
- request_string += key + '_' + (++group_index) + ':' + group.get(key) + ', ';
+ request_string += key + '_' + (++group_index) + ':' + (parseInt(group.get(key)) + 1) + ', ';
}
});
// return
- return 'columns : 2';
- //return request_string.substring(0, request_string.length - 2);
+ return request_string.substring(0, request_string.length - 2);
},
// create default chart request
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/18fa1f7340b3/
Changeset: 18fa1f7340b3
Branch: stable
User: natefoo
Date: 2014-03-06 22:58:22
Summary: Fix incorrect example of remote_user_header in sample config.
Affected #: 1 file
diff -r ccfb1805efd075ebb2ab56f4b75509e7d6d99ebb -r 18fa1f7340b3a5c99dda2e195b20373841d807e9 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -606,7 +606,7 @@
# by WSGI). This option allows you to change the header. Note, you still need
# to prepend 'HTTP_' to the header in this option, but your proxy server should
# *not* include 'HTTP_' at the beginning of the header name.
-#remote_user_header = 'HTTP_REMOTE_USER'
+#remote_user_header = HTTP_REMOTE_USER
# If use_remote_user is enabled, you can set this to a URL that will log your
# users out.
https://bitbucket.org/galaxy/galaxy-central/commits/c58e14ae86d1/
Changeset: c58e14ae86d1
User: natefoo
Date: 2014-03-06 22:59:19
Summary: merge stable.
Affected #: 1 file
diff -r d2ba52e5ec11909a058c698d625aa139aa3c78d4 -r c58e14ae86d182f8152edbfe2569857da54ccb49 universe_wsgi.ini.sample
--- a/universe_wsgi.ini.sample
+++ b/universe_wsgi.ini.sample
@@ -616,7 +616,7 @@
# by WSGI). This option allows you to change the header. Note, you still need
# to prepend 'HTTP_' to the header in this option, but your proxy server should
# *not* include 'HTTP_' at the beginning of the header name.
-#remote_user_header = 'HTTP_REMOTE_USER'
+#remote_user_header = HTTP_REMOTE_USER
# If use_remote_user is enabled, you can set this to a URL that will log your
# users out.
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: Pass raw strings to handle_command so that python won't automatically unescape the double quotes being sent on to subprocess.Popen.
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d2ba52e5ec11/
Changeset: d2ba52e5ec11
User: davebgx
Date: 2014-03-06 22:03:49
Summary: Pass raw strings to handle_command so that python won't automatically unescape the double quotes being sent on to subprocess.Popen.
Affected #: 1 file
diff -r 03f935bb636e0f4fa63782ce5d6a551ac508144a -r d2ba52e5ec11909a058c698d625aa139aa3c78d4 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -604,7 +604,7 @@
return tool_dependency
else:
install_environment.add_env_shell_file_paths( env_shell_file_paths )
- log.debug( 'Handling setup_r_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s"' % \
+ log.debug( 'Handling setup_r_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \
( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) )
tarball_names = []
for url in action_dict[ 'r_packages' ]:
@@ -616,8 +616,10 @@
with lcd( current_dir ):
with settings( warn_only=True ):
for tarball_name in tarball_names:
- cmd = '''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
- Rscript -e \\"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\\"''' % \
+ # Use raw strings so that python won't automatically unescape the \", needed because handle_command wraps
+ # the provided command in /bin/sh -c "<command>".
+ cmd = r'''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
+ Rscript -e \"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\"''' % \
( str( tarball_name ) )
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
return_code = handle_command( app, tool_dependency, install_dir, cmd )
@@ -649,7 +651,7 @@
return tool_dependency
else:
install_environment.add_env_shell_file_paths( env_shell_file_paths )
- log.debug( 'Handling setup_ruby_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s"' % \
+ log.debug( 'Handling setup_ruby_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \
( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) )
dir = os.path.curdir
current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
@@ -672,9 +674,11 @@
else:
# gem file from rubygems.org with or without version number
if gem_version:
- # version number was specified
- cmd = '''PATH=$PATH:$RUBY_HOME/bin; export PATH; GEM_HOME=$INSTALL_DIR; export GEM_HOME;
- gem install %s --version "=%s"''' % ( gem, gem_version)
+ # Specific ruby gem version was requested.
+ # Use raw strings so that python won't automatically unescape the \", needed because handle_command wraps
+ # the provided command in /bin/sh -c "<command>".
+ cmd = r'''PATH=$PATH:$RUBY_HOME/bin; export PATH; GEM_HOME=$INSTALL_DIR; export GEM_HOME;
+ gem install %s --version \"=%s\"''' % ( gem, gem_version)
else:
# no version number given
cmd = '''PATH=$PATH:$RUBY_HOME/bin; export PATH; GEM_HOME=$INSTALL_DIR; export GEM_HOME;
@@ -708,7 +712,7 @@
return tool_dependency
else:
install_environment.add_env_shell_file_paths( env_shell_file_paths )
- log.debug( 'Handling setup_perl_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s"' % \
+ log.debug( 'Handling setup_perl_environment for tool dependency %s with install_environment.env_shell_file_paths:\n%s' % \
( str( tool_dependency.name ), str( install_environment.env_shell_file_paths ) ) )
dir = os.path.curdir
current_dir = os.path.abspath( os.path.join( work_dir, dir ) )
@@ -831,7 +835,9 @@
return_code = handle_command( app, tool_dependency, install_dir, full_setup_command )
if return_code:
return tool_dependency
- site_packages_command = "%s -c 'import os, sys; print os.path.join(sys.prefix, \"lib\", \"python\" + sys.version[:3], \"site-packages\")'" % os.path.join( venv_directory, "bin", "python" )
+ # Use raw strings so that python won't automatically unescape the \", needed because handle_command wraps
+ # the provided command in /bin/sh -c "<command>".
+ site_packages_command = r"%s -c 'import os, sys; print os.path.join(sys.prefix, \"lib\", \"python\" + sys.version[:3], \"site-packages\")'" % os.path.join( venv_directory, "bin", "python" )
output = handle_command( app, tool_dependency, install_dir, site_packages_command, return_output=True )
if output.return_code:
return tool_dependency
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 job cleanup procedure, handle multiple job requests
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/03f935bb636e/
Changeset: 03f935bb636e
User: guerler
Date: 2014-03-06 22:02:55
Summary: Charts: Add job cleanup procedure, handle multiple job requests
Affected #: 5 files
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/charts/histogram.js
--- a/config/plugins/visualizations/charts/static/charts/histogram.js
+++ b/config/plugins/visualizations/charts/static/charts/histogram.js
@@ -29,6 +29,7 @@
// send request
var self = this;
this.app.datasets.request(request_dictionary, function(data) {
+ chart.set('state', 'ok');
nv.addGraph(function() {
self.d3_chart = nv.models.multiBarChart();
@@ -39,8 +40,6 @@
.call(self.d3_chart);
nv.utils.windowResize(self.d3_chart.update);
-
- chart.set('state', 'ok');
});
});
}
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/library/jobs.js
--- a/config/plugins/visualizations/charts/static/library/jobs.js
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -28,24 +28,29 @@
// configure tool
data = {
'tool_id' : 'rkit',
- 'history_id' : chart.history_id,
+ 'history_id' : chart.get('history_id'),
'inputs' : {
- 'input' : chart.dataset_hid,
+ 'input' : chart.get('dataset_hid'),
'module' : chart_type,
'options' : request_string
}
}
+ // cleanup previous dataset file
+ var previous = chart.get('dataset_id_job');
+ if (previous) {
+ Utils.request('PUT', config.root + 'api/histories/' + chart.get('history_id') + '/contents/' + previous, { deleted: true });
+ }
+
// set chart state
chart.state('submit', 'Sending job request...');
-
+
// post job
Utils.request('POST', config.root + 'api/tools', data,
// success handler
function(response) {
if (!response.outputs || response.outputs.length == 0) {
chart.state('failed', 'Job submission failed. No response.');
- self.app.log('handle::load()', 'Job submission failed.');
} else {
// update galaxy history
if (Galaxy && Galaxy.currHistoryPanel) {
@@ -65,7 +70,7 @@
self._loop(job.id, function(job) {
switch (job.state) {
case 'ok':
- chart.state('ok', 'Job completed successfully...');
+ chart.state('success', 'Job completed successfully...');
callback(job);
return true;
case 'error':
@@ -80,8 +85,7 @@
},
// error handler
function(response) {
- chart.state('failed', 'Job submission failed.');
- self.app.log('handle::load()', 'Job submission failed.');
+ chart.state('failed', 'Job submission failed. Please make sure that \'R-kit\' is installed.');
}
);
},
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -11,7 +11,7 @@
title : '',
type : '',
date : null,
- state : '',
+ state : 'ok',
state_info : ''
},
@@ -44,6 +44,10 @@
state: function(value, info) {
this.set('state_info', info);
this.set('state', value);
+ },
+
+ ready: function() {
+ return (this.get('state') == 'ok') || (this.get('state') == 'failed');
}
});
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -286,7 +286,7 @@
}
// trigger redraw
- current.set('state', 'redraw');
+ current.trigger('redraw', current);
}
});
diff -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c -r 03f935bb636e0f4fa63782ce5d6a551ac508144a 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
@@ -48,10 +48,18 @@
self._removeChart(chart.id);
});
- // replace
- this.app.charts.on('change', function(chart) {
- if (chart.get('state') == 'redraw') {
+ // redraw
+ this.app.charts.on('redraw', function(chart) {
+ // redraw if chart is not currently processed
+ if (chart.ready()) {
self._refreshChart(chart);
+ } else {
+ // redraw once current drawing process has finished
+ chart.on('change:state', function() {
+ if (chart.ready()) {
+ self._refreshChart(chart);
+ }
+ });
}
});
},
@@ -111,6 +119,12 @@
// link this
var self = this;
+ // check
+ if (!chart.ready()) {
+ self.app.log('viewport:_refreshChart()', 'Invalid attempt to refresh chart before completion.');
+ return;
+ }
+
// backup chart details
var chart_id = chart.id;
@@ -138,6 +152,9 @@
// show chart from list
this.showChart(chart_id);
+ // clear all previous handlers (including redraw listeners)
+ chart.off('change:state');
+
// link status handler
chart.on('change:state', function() {
// get info element
@@ -185,10 +202,10 @@
var mode = chart_settings.mode;
if (mode == 'execute') {
self.app.jobs.submit(chart, self._defaultRequestString(chart), function() {
- view.plot(chart, self._defaultRequestDictionary(chart))
+ view.plot(chart, self._defaultRequestDictionary(chart));
});
} else {
- view.plot(chart, self._defaultRequestDictionary(chart))
+ view.plot(chart, self._defaultRequestDictionary(chart));
}
});
},
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: Enhance Tools Verified grid column in the tool shed to be useful for Tool dependency definitions repositories as well as Unrestricted repositories that contain tools.
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/7f4aa510ab2c/
Changeset: 7f4aa510ab2c
User: greg
Date: 2014-03-06 21:26:02
Summary: Enhance Tools Verified grid column in the tool shed to be useful for Tool dependency definitions repositories as well as Unrestricted repositories that contain tools.
Affected #: 1 file
diff -r ac45b47a15693c9cc71050c9dd16a4ed6738d1a9 -r 7f4aa510ab2c3a60b2171d20051af4b1257acc5c lib/tool_shed/grids/repository_grids.py
--- a/lib/tool_shed/grids/repository_grids.py
+++ b/lib/tool_shed/grids/repository_grids.py
@@ -5,8 +5,10 @@
from galaxy.model.orm import and_
from galaxy.model.orm import or_
from galaxy.util import json
+from galaxy.util import listify
import tool_shed.util.shed_util_common as suc
import tool_shed.grids.util as grids_util
+import tool_shed.repository_types.util as rt_util
from tool_shed.util import metadata_util
from galaxy import eggs
@@ -159,16 +161,41 @@
def get_value( self, trans, grid, repository ):
# This column will display the value associated with the currently displayed metadata revision.
- try:
- displayed_metadata_revision = repository.metadata_revisions[ -1 ]
- if displayed_metadata_revision.includes_tools:
- if displayed_metadata_revision.tools_functionally_correct:
- return 'yes'
+ if repository.type == rt_util.UNRESTRICTED:
+ try:
+ displayed_metadata_revision = repository.metadata_revisions[ -1 ]
+ if displayed_metadata_revision.includes_tools:
+ if displayed_metadata_revision.tools_functionally_correct:
+ return 'yes'
+ else:
+ return 'no'
+ return 'n/a'
+ except Exception, e:
+ log.exception( str( e ) )
+ return 'unknown'
+ else:
+ # Here repository.type must be rt_util.TOOL_DEPENDENCY_DEFINITION.
+ try:
+ displayed_metadata_revision = repository.metadata_revisions[ -1 ]
+ if displayed_metadata_revision.test_install_error:
+ return 'no'
+ tool_test_results = listify( displayed_metadata_revision.tool_test_results )
+ if len( tool_test_results ) > 0:
+ last_tool_test_result = tool_test_results[ 0 ]
+ installation_error_dict = last_tool_test_result.get( 'installation_errors', {} )
+ if len( installation_error_dict ) > 0:
+ current_repository_installation_error_dicts = installation_error_dict.get( 'current_repository', [] )
+ if len( current_repository_installation_error_dicts ) > 0:
+ return 'no'
+ else:
+ return 'yes'
+ else:
+ return 'yes'
else:
return 'no'
- return 'n/a'
- except:
- return 'n/a'
+ except Exception, e:
+ log.exception( str( e ) )
+ return 'unknown'
class DescriptionColumn( grids.TextColumn ):
@@ -247,7 +274,7 @@
attach_popup=False ),
TypeColumn( "Type" ),
MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
@@ -404,7 +431,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( operation="repositories_by_user", id=item.id ) ),
@@ -452,7 +479,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.CategoryColumn( "Category",
model_class=model.Category,
key="Category.name",
@@ -489,7 +516,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.UserColumn( "Owner",
model_class=model.User,
link=( lambda item: dict( controller="repository", operation="repositories_by_user", id=item.id ) ),
@@ -538,7 +565,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.DeprecatedColumn( "Deprecated" )
]
columns.append( grids.MulticolFilterColumn( "Search repository name",
@@ -566,7 +593,7 @@
attach_popup=False ),
RepositoryGrid.UserColumn( "Owner" ),
RepositoryGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.DeprecatedColumn( "Deprecated" )
]
columns.append( grids.MulticolFilterColumn( "Search repository name",
@@ -874,7 +901,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
RepositoriesIOwnGrid.MetadataRevisionColumn( "Metadata<br/>Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoriesIOwnGrid.CategoryColumn( "Category",
model_class=model.Category,
key="Category.name",
@@ -1697,7 +1724,7 @@
attach_popup=False ),
RepositoryGrid.TypeColumn( "Type" ),
InstallableRevisionColumn( "Installable Revisions" ),
- RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools<br/>Verified" ),
+ RepositoryGrid.ToolsFunctionallyCorrectColumn( "Tools or<br/>Package<br/>Verified" ),
RepositoryGrid.UserColumn( "Owner",
model_class=model.User,
attach_popup=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: martenson: API libraries improvements, easier prefixing to folders, some refactoring
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/ac45b47a1569/
Changeset: ac45b47a1569
User: martenson
Date: 2014-03-06 20:20:21
Summary: API libraries improvements, easier prefixing to folders, some refactoring
Affected #: 1 file
diff -r f5a119ac52a957204ab968a78638fe2a942c6893 -r ac45b47a15693c9cc71050c9dd16a4ed6738d1a9 lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -35,27 +35,23 @@
query = trans.sa_session.query( trans.app.model.Library )
deleted = util.string_as_bool( deleted )
if deleted:
- route = 'deleted_library'
query = query.filter( trans.app.model.Library.table.c.deleted == True )
else:
- route = 'library'
query = query.filter( trans.app.model.Library.table.c.deleted == False )
current_user_role_ids = [ role.id for role in trans.get_current_user_roles() ]
library_access_action = trans.app.security_agent.permitted_actions.LIBRARY_ACCESS.action
- restricted_library_ids = [ lp.library_id for lp in trans.sa_session.query( trans.model.LibraryPermissions ) \
- .filter( trans.model.LibraryPermissions.table.c.action == library_access_action ) \
- .distinct() ]
- accessible_restricted_library_ids = [ lp.library_id for lp in trans.sa_session.query( trans.model.LibraryPermissions ) \
+ restricted_library_ids = [ lp.library_id for lp in ( trans.sa_session.query( trans.model.LibraryPermissions )
+ .filter( trans.model.LibraryPermissions.table.c.action == library_access_action )
+ .distinct() ) ]
+ accessible_restricted_library_ids = [ lp.library_id for lp in ( trans.sa_session.query( trans.model.LibraryPermissions )
.filter( and_( trans.model.LibraryPermissions.table.c.action == library_access_action,
- trans.model.LibraryPermissions.table.c.role_id.in_( current_user_role_ids ) ) ) ]
+ trans.model.LibraryPermissions.table.c.role_id.in_( current_user_role_ids ) ) ) ) ]
query = query.filter( or_( not_( trans.model.Library.table.c.id.in_( restricted_library_ids ) ),
trans.model.Library.table.c.id.in_( accessible_restricted_library_ids ) ) )
libraries = []
for library in query:
- item = library.to_dict( view='element' )
- item[ 'url' ] = url_for( route, id=trans.security.encode_id( library.id ) )
- item[ 'id' ] = trans.security.encode_id( item[ 'id' ] )
- item[ 'root_folder_id' ] = 'F' + trans.security.encode_id( item[ 'root_folder_id' ] )
+ item = self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
libraries.append( item )
return libraries
@@ -91,7 +87,8 @@
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
@expose_api
def create( self, trans, payload, **kwd ):
@@ -126,7 +123,8 @@
library.root_folder = root_folder
trans.sa_session.add_all( ( library, root_folder ) )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
@expose_api
def update( self, trans, id, **kwd ):
@@ -134,7 +132,7 @@
* PATCH /api/libraries/{encoded_id}
Updates the library defined by an ``encoded_id`` with the data in the payload.
- .. note:: Currently, only admin users can update libraries.
+ .. note:: Currently, only admin users can update libraries. Also the library must not be `deleted`.
:param payload: (required) dictionary structure containing::
'name': new library's name, cannot be empty
@@ -159,7 +157,8 @@
library = None
if not library:
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
-
+ if library.deleted:
+ raise exceptions.RequestParameterInvalidException( 'You cannot modify a deleted library. Undelete it first.' )
payload = kwd.get( 'payload', None )
if payload:
name = payload.get( 'name', None )
@@ -174,7 +173,8 @@
raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
@expose_api
def delete( self, trans, id, **kwd ):
@@ -217,4 +217,24 @@
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+ return self._prepend_folder_prefix( library.to_dict( view='element',
+ value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } ) )
+
+ def _prepend_folder_prefix (self, dictionary, type='library' ):
+ """
+ In Galaxy folders have 'F' as a prefix to the encoded id to distinguish between folders and libraries
+ """
+ if not ( type in [ 'library', 'folder' ] ):
+ raise TypeError( 'Prepending is not implemented for given type of dictionary.' )
+ return_dict = dictionary
+ if type == 'library':
+ if return_dict[ 'root_folder_id' ]:
+ return_dict[ 'root_folder_id' ] = 'F' + return_dict[ 'root_folder_id' ]
+ else:
+ raise ValueError( 'Given library does not contain root_folder_id to prepend to.' )
+ elif type == 'folder':
+ if return_dict[ 'id' ]:
+ return_dict[ 'id' ] = 'F' + return_dict[ 'id' ]
+ else:
+ raise ValueError( 'Given folder does not contain id to prepend to.' )
+ return return_dict
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
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f5a119ac52a9/
Changeset: f5a119ac52a9
User: greg
Date: 2014-03-06 17:39:48
Summary: Fixes to handle case where a tool dependency recipe defines an <actions_group> tag set for installing pre-compiled binaries which fail to install, so the fall back recipe for installing and compileing from souce is used. Prior to this change set, the recipe from source would not work, but the install process would finish in such a way that the recipe seemed to work.
Affected #: 5 files
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 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
@@ -1111,10 +1111,12 @@
no_changes_checked = CheckboxField.is_checked( no_changes )
install_repository_dependencies = CheckboxField.is_checked( kwd.get( 'install_repository_dependencies', '' ) )
install_tool_dependencies = CheckboxField.is_checked( kwd.get( 'install_tool_dependencies', '' ) )
- shed_tool_conf, tool_path, relative_install_dir = suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
+ shed_tool_conf, tool_path, relative_install_dir = \
+ suc.get_tool_panel_config_tool_path_install_dir( trans.app, tool_shed_repository )
repository_clone_url = suc.generate_clone_url_for_installed_repository( trans.app, tool_shed_repository )
- clone_dir = os.path.join( tool_path, suc.generate_tool_shed_repository_install_dir( repository_clone_url,
- tool_shed_repository.installed_changeset_revision ) )
+ clone_dir = os.path.join( tool_path,
+ suc.generate_tool_shed_repository_install_dir( repository_clone_url,
+ tool_shed_repository.installed_changeset_revision ) )
relative_install_dir = os.path.join( clone_dir, tool_shed_repository.name )
tool_shed_url = suc.get_url_from_tool_shed( trans.app, tool_shed_repository.tool_shed )
tool_section = None
@@ -1123,7 +1125,8 @@
tool_panel_section_key = None
tool_panel_section_keys = []
metadata = tool_shed_repository.metadata
- # Keep track of tool dependencies defined for the current repository or those defined for any of it's repository dependencies.
+ # Keep track of tool dependencies defined for the current repository or those defined for any of
+ # it's repository dependencies.
includes_tool_dependencies = tool_shed_repository.includes_tool_dependencies
if tool_shed_repository.includes_tools_for_display_in_tool_panel:
# Handle the selected tool panel location for loading tools included in the tool shed repository.
@@ -1137,7 +1140,8 @@
# Just in case the tool_section.id differs from tool_panel_section_id, which it shouldn't...
tool_panel_section_id = str( tool_section.id )
if tool_shed_repository.status == trans.install_model.ToolShedRepository.installation_status.UNINSTALLED:
- # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall so the repository_installation_updater will function.
+ # The repository's status must be updated from 'Uninstalled' to 'New' when initiating reinstall
+ # so the repository_installation_updater will function.
tool_shed_repository = suc.create_or_update_tool_shed_repository( trans.app,
tool_shed_repository.name,
tool_shed_repository.description,
@@ -1163,7 +1167,8 @@
# Entering this else block occurs only if the tool_shed_repository does not include any valid tools.
if install_repository_dependencies:
repository_dependencies = \
- repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans, tool_shed_repository )
+ repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans,
+ tool_shed_repository )
else:
repository_dependencies = None
if metadata:
@@ -1220,7 +1225,8 @@
clause_list = []
for tsr_id in tsr_ids:
clause_list.append( trans.install_model.ToolShedRepository.table.c.id == tsr_id )
- query = trans.install_model.context.current.query( trans.install_model.ToolShedRepository ).filter( or_( *clause_list ) )
+ query = trans.install_model.context.current.query( trans.install_model.ToolShedRepository ) \
+ .filter( or_( *clause_list ) )
return trans.fill_template( 'admin/tool_shed_repository/initiate_repository_installation.mako',
encoded_kwd=encoded_kwd,
query=query,
@@ -1378,7 +1384,9 @@
raw_text = common_util.tool_shed_get( trans.app, tool_shed_url, url )
readme_files_dict = json.from_json_string( raw_text )
tool_dependencies = metadata.get( 'tool_dependencies', None )
- repository_dependencies = repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans, tool_shed_repository )
+ repository_dependencies = \
+ repository_dependency_util.get_repository_dependencies_for_installed_tool_shed_repository( trans,
+ tool_shed_repository )
repo_info_dict = repository_util.create_repo_info_dict( trans=trans,
repository_clone_url=repository_clone_url,
changeset_revision=tool_shed_repository.installed_changeset_revision,
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 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
@@ -30,36 +30,43 @@
log = logging.getLogger( __name__ )
-def create_repo_info_dict( trans, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None, repository=None,
- repository_metadata=None, tool_dependencies=None, repository_dependencies=None ):
+def create_repo_info_dict( trans, repository_clone_url, changeset_revision, ctx_rev, repository_owner, repository_name=None,
+ repository=None, repository_metadata=None, tool_dependencies=None, repository_dependencies=None ):
"""
- Return a dictionary that includes all of the information needed to install a repository into a local Galaxy instance. The dictionary will also
- contain the recursive list of repository dependencies defined for the repository, as well as the defined tool dependencies.
+ Return a dictionary that includes all of the information needed to install a repository into a local
+ Galaxy instance. The dictionary will also contain the recursive list of repository dependencies defined
+ for the repository, as well as the defined tool dependencies.
This method is called from Galaxy under three scenarios:
- 1. During the tool shed repository installation process via the tool shed's get_repository_information() method. In this case both the received
- repository and repository_metadata will be objects., but tool_dependencies and repository_dependencies will be None
- 2. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with no updates available. In this case, both
- repository and repository_metadata will be None, but tool_dependencies and repository_dependencies will be objects previously retrieved from the
- tool shed if the repository includes definitions for them.
- 3. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with updates available. In this case, this
- method is reached via the tool shed's get_updated_repository_information() method, and both repository and repository_metadata will be objects
- but tool_dependencies and repository_dependencies will be None.
+ 1. During the tool shed repository installation process via the tool shed's get_repository_information()
+ method. In this case both the received repository and repository_metadata will be objects., but
+ tool_dependencies and repository_dependencies will be None.
+ 2. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with no
+ updates available. In this case, both repository and repository_metadata will be None, but tool_dependencies
+ and repository_dependencies will be objects previously retrieved from the tool shed if the repository includes
+ definitions for them.
+ 3. When a tool shed repository that was uninstalled from a Galaxy instance is being reinstalled with updates
+ available. In this case, this method is reached via the tool shed's get_updated_repository_information()
+ method, and both repository and repository_metadata will be objects but tool_dependencies and
+ repository_dependencies will be None.
"""
repo_info_dict = {}
repository = suc.get_repository_by_name_and_owner( trans.app, repository_name, repository_owner )
if trans.webapp.name == 'tool_shed':
# We're in the tool shed.
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, trans.security.encode_id( repository.id ), changeset_revision )
+ repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans,
+ trans.security.encode_id( repository.id ),
+ changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
if metadata:
+ toolshed_url = str( web.url_for( '/', qualified=True ) ).rstrip( '/' )
# Get a dictionary of all repositories upon which the contents of the received repository depends.
repository_dependencies = \
repository_dependency_util.get_repository_dependencies_for_changeset_revision( trans=trans,
repository=repository,
repository_metadata=repository_metadata,
- toolshed_base_url=str( web.url_for( '/', qualified=True ) ).rstrip( '/' ),
+ toolshed_base_url=toolshed_url,
key_rd_dicts_to_be_processed=None,
all_repository_dependencies=None,
handled_key_rd_dicts=None,
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/fabric_util.py
@@ -228,24 +228,23 @@
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 ] )
+ os.chmod( file_path, int( '111', base=8 ) | os.stat( file_path )[ stat.ST_MODE ] )
except Exception, e:
log.exception( str( e ) )
return 1
- return_code = 0
# 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 not in env_file_contents:
+ 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 return_code
+ return 0
def filter_actions_after_binary_installation( actions ):
'''Filter out actions that should not be processed if a binary download succeeded.'''
@@ -262,8 +261,13 @@
env_file_builder.append_line( action="source", value=shell_file_path )
def handle_command( app, tool_dependency, install_dir, cmd, return_output=False ):
+ """
+ Handle a command by determining if it is "simple" or "complex" and redirecting appropriately and then
+ logging the results.
+ """
context = app.install_model.context
- output = handle_complex_command( cmd )
+ command = str( cmd )
+ output = handle_complex_command( command )
log_results( cmd, output, os.path.join( install_dir, INSTALLATION_LOG ) )
stdout = output.stdout
stderr = output.stderr
@@ -381,13 +385,15 @@
def handle_environment_variables( app, tool_dependency, install_dir, env_var_dict, set_prior_environment_commands ):
"""
- This method works with with a combination of three tool dependency definition tag sets, which are defined in the tool_dependencies.xml file in the
- order discussed here. The example for this discussion is the tool_dependencies.xml file contained in the osra repository, which is available at:
+ This method works with with a combination of three tool dependency definition tag sets, which are defined
+ in the tool_dependencies.xml file in the order discussed here. The example for this discussion is the
+ tool_dependencies.xml file contained in the osra repository, which is available at:
http://testtoolshed.g2.bx.psu.edu/view/bgruening/osra
- The first tag set defines a complex repository dependency like this. This tag set ensures that changeset revision XXX of the repository named
- package_graphicsmagick_1_3 owned by YYY in the tool shed ZZZ has been previously installed.
+ The first tag set defines a complex repository dependency like this. This tag set ensures that changeset
+ revision XXX of the repository named package_graphicsmagick_1_3 owned by YYY in the tool shed ZZZ has been
+ previously installed.
<tool_dependency><package name="graphicsmagick" version="1.3.18">
@@ -395,19 +401,21 @@
</package>
...
- * By the way, there is an env.sh file associated with version 1.3.18 of the graphicsmagick package which looks something like this (we'll reference
- this file later in this discussion.
+ * By the way, there is an env.sh file associated with version 1.3.18 of the graphicsmagick package which looks
+ something like this (we'll reference this file later in this discussion.
----
GRAPHICSMAGICK_ROOT_DIR=/<my configured tool dependency path>/graphicsmagick/1.3.18/YYY/package_graphicsmagick_1_3/XXX/gmagick;
export GRAPHICSMAGICK_ROOT_DIR
----
- The second tag set defines a specific package dependency that has been previously installed (guaranteed by the tag set discussed above) and compiled,
- where the compiled dependency is needed by the tool dependency currently being installed (osra version 2.0.0 in this case) and complied in order for
- it's installation and compilation to succeed. This tag set is contained within the <package name="osra" version="2.0.0"> tag set, which implies that
- version 2.0.0 of the osra package requires version 1.3.18 of the graphicsmagick package in order to successfully compile. When this tag set is handled,
- one of the effects is that the env.sh file associated with graphicsmagick version 1.3.18 is "sourced", which undoubtedly sets or alters certain environment
- variables (e.g. PATH, PYTHONPATH, etc).
+ The second tag set defines a specific package dependency that has been previously installed (guaranteed by the
+ tag set discussed above) and compiled, where the compiled dependency is needed by the tool dependency currently
+ being installed (osra version 2.0.0 in this case) and complied in order for it's installation and compilation to
+ succeed. This tag set is contained within the <package name="osra" version="2.0.0"> tag set, which implies that
+ version 2.0.0 of the osra package requires version 1.3.18 of the graphicsmagick package in order to successfully
+ compile. When this tag set is handled, one of the effects is that the env.sh file associated with graphicsmagick
+ version 1.3.18 is "sourced", which undoubtedly sets or alters certain environment variables (e.g. PATH, PYTHONPATH,
+ etc).
<!-- populate the environment variables from the dependent repositories --><action type="set_environment_for_install">
@@ -416,11 +424,12 @@
</repository></action>
- The third tag set enables discovery of the same required package dependency discussed above for correctly compiling the osra version 2.0.0 package, but
- in this case the package can be discovered at tool execution time. Using the $ENV[] option as shown in this example, the value of the environment
- variable named GRAPHICSMAGICK_ROOT_DIR (which was set in the environment using the second tag set described above) will be used to automatically alter
- the env.sh file associated with the osra version 2.0.0 tool dependency when it is installed into Galaxy. * Refer to where we discussed the env.sh file
- for version 1.3.18 of the graphicsmagick package above.
+ The third tag set enables discovery of the same required package dependency discussed above for correctly compiling
+ the osra version 2.0.0 package, but in this case the package can be discovered at tool execution time. Using the
+ $ENV[] option as shown in this example, the value of the environment variable named GRAPHICSMAGICK_ROOT_DIR (which
+ was set in the environment using the second tag set described above) will be used to automatically alter the env.sh
+ file associated with the osra version 2.0.0 tool dependency when it is installed into Galaxy. * Refer to where we
+ discussed the env.sh file for version 1.3.18 of the graphicsmagick package above.
<action type="set_environment"><environment_variable action="prepend_to" name="LD_LIBRARY_PATH">$ENV[GRAPHICSMAGICK_ROOT_DIR]/lib/</environment_variable>
@@ -430,8 +439,9 @@
<environment_variable action="set_to" name="OSRA_DATA_FILES">$INSTALL_DIR/share</environment_variable></action>
- The above tag will produce an env.sh file for version 2.0.0 of the osra package when it it installed into Galaxy that looks something like this. Notice
- that the path to the gmagick binary is included here since it expands the defined $ENV[GRAPHICSMAGICK_ROOT_DIR] value in the above tag set.
+ The above tag will produce an env.sh file for version 2.0.0 of the osra package when it it installed into Galaxy
+ that looks something like this. Notice that the path to the gmagick binary is included here since it expands the
+ defined $ENV[GRAPHICSMAGICK_ROOT_DIR] value in the above tag set.
----
LD_LIBRARY_PATH=/<my configured tool dependency path>/graphicsmagick/1.3.18/YYY/package_graphicsmagick_1_3/XXX/gmagick/lib/:$LD_LIBRARY_PATH;
@@ -607,7 +617,8 @@
with settings( warn_only=True ):
for tarball_name in tarball_names:
cmd = '''PATH=$PATH:$R_HOME/bin; export PATH; R_LIBS=$INSTALL_DIR; export R_LIBS;
- Rscript -e \\"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\\"''' % ( str( tarball_name ) )
+ Rscript -e \\"install.packages(c('%s'),lib='$INSTALL_DIR', repos=NULL, dependencies=FALSE)\\"''' % \
+ ( str( tarball_name ) )
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
return_code = handle_command( app, tool_dependency, install_dir, cmd )
if return_code:
@@ -720,7 +731,8 @@
elif os.path.exists( os.path.join( tmp_work_dir, 'Build.PL' ) ):
cmd += '''perl Build.PL --install_base $INSTALL_DIR && perl Build && perl Build install'''
else:
- log.debug( 'No Makefile.PL or Build.PL file found in %s. Skipping installation of %s.' % ( url, perl_package_name ) )
+ log.debug( 'No Makefile.PL or Build.PL file found in %s. Skipping installation of %s.' % \
+ ( url, perl_package_name ) )
return tool_dependency
with lcd( tmp_work_dir ):
cmd = install_environment.build_command( td_common_util.evaluate_template( cmd, install_dir ) )
@@ -920,9 +932,7 @@
return tool_dependency
def log_results( command, fabric_AttributeString, file_path ):
- """
- Write attributes of fabric.operations._AttributeString to a specified log file.
- """
+ """Write attributes of fabric.operations._AttributeString to a specified log file."""
if os.path.exists( file_path ):
logfile = open( file_path, 'ab' )
else:
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
--- a/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
+++ b/lib/tool_shed/galaxy_install/tool_dependencies/install_util.py
@@ -300,7 +300,10 @@
return tool_dependency
def install_package( app, elem, tool_shed_repository, tool_dependencies=None, from_install_manager=False ):
- # The value of tool_dependencies is a partial or full list of ToolDependency records associated with the tool_shed_repository.
+ """
+ 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.
@@ -363,8 +366,8 @@
type='package',
status=app.install_model.ToolDependency.installation_status.INSTALLING,
set_status=True )
- # Get the information about the current platform in case the tool dependency definition includes tag sets for installing
- # compiled binaries.
+ # 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.
@@ -372,24 +375,29 @@
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.
+ # 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 in_actions_group, actions_elems in actions_elem_tuples:
+ 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.
+ # 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 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 look here because there may be <action> tags at the end of the <actions_group>
- # tag set that must be processed.
+ # 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.
@@ -400,41 +408,50 @@
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.
+ # 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.
+ # 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 no <actions> tags have been defined that match our current platform, or none of the matching
- # <actions> tags resulted in a successful tool dependency status, proceed with one and only one
- # <actions> tag that is not defined to be platform-specific.
- if not binary_installed:
- log.debug( 'Proceeding with install and compile recipe for tool dependency %s.' % str( tool_dependency.name ) )
- # Make sure to reset for installation if attempt at binary installation resulted in an error.
- can_install = True
- if tool_dependency.status != app.install_model.ToolDependency.installation_status.NEVER_INSTALLED:
- removed, error_message = tool_dependency_util.remove_tool_dependency( app, tool_dependency )
- if not removed:
- log.debug( 'Error removing old files from installation directory %s: %s' % \
- ( str( tool_dependency.installation_directory( app ), str( error_message ) ) ) )
- can_install = False
- if can_install:
+ 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_dependency,
install_dir,
package_name=package_name,
actions_elem=actions_elem,
action_elem=None )
- # Perform any final actions that have been defined within the actions_group tag set, but outside of
- # an <actions> tag, such as a set_environment entry, or a download_file or download_by_url command to
- # retrieve extra data for this tool dependency. Only do this if the tool dependency is not in an error
- # state, otherwise skip this action.
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_dependency,
install_dir,
@@ -442,9 +459,9 @@
actions_elem=None,
action_elem=actions_elem )
else:
- # <actions> tags outside of an <actions_group> tag shall not check os or architecture, and if the attributes are
- # defined, they will be ignored. All <actions> tags outside of an <actions_group> tag set shall always be processed.
- # This is the default and original behavior of the install_package method.
+ # 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_dependency,
install_dir,
diff -r 8093e5f39efb831da042a20fa2bb850470355d7a -r f5a119ac52a957204ab968a78638fe2a942c6893 lib/tool_shed/util/shed_util_common.py
--- a/lib/tool_shed/util/shed_util_common.py
+++ b/lib/tool_shed/util/shed_util_common.py
@@ -227,18 +227,21 @@
return file_path
return None
-def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url, metadata_dict,
- status, current_changeset_revision=None, owner='', dist_to_shed=False ):
+def create_or_update_tool_shed_repository( app, name, description, installed_changeset_revision, ctx_rev, repository_clone_url,
+ metadata_dict, status, current_changeset_revision=None, owner='', dist_to_shed=False ):
"""
- Update a tool shed repository record in the Galaxy database with the new information received. If a record defined by the received tool shed,
- repository name and owner does not exist, create a new record with the received information.
+ Update a tool shed repository record in the Galaxy database with the new information received.
+ If a record defined by the received tool shed, repository name and owner does not exist, create
+ a new record with the received information.
"""
- # The received value for dist_to_shed will be True if the InstallManager is installing a repository that contains tools or datatypes that used
- # to be in the Galaxy distribution, but have been moved to the main Galaxy tool shed.
+ # The received value for dist_to_shed will be True if the InstallManager is installing a repository
+ # that contains tools or datatypes that used to be in the Galaxy distribution, but have been moved
+ # to the main Galaxy tool shed.
if current_changeset_revision is None:
- # The current_changeset_revision is not passed if a repository is being installed for the first time. If a previously installed repository
- # was later uninstalled, this value should be received as the value of that change set to which the repository had been updated just prior
- # to it being uninstalled.
+ # The current_changeset_revision is not passed if a repository is being installed for the first
+ # time. If a previously installed repository was later uninstalled, this value should be received
+ # as the value of that change set to which the repository had been updated just prior to it being
+ # uninstalled.
current_changeset_revision = installed_changeset_revision
context = app.install_model.context
tool_shed = get_tool_shed_from_clone_url( repository_clone_url )
@@ -255,9 +258,14 @@
deleted = False
uninstalled = False
tool_shed_repository = \
- get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app, tool_shed, name, owner, installed_changeset_revision )
+ get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app,
+ tool_shed,
+ name,
+ owner,
+ installed_changeset_revision )
if tool_shed_repository:
- log.debug( "Updating an existing row for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
+ log.debug( "Updating an existing row for repository '%s' in the tool_shed_repository table, status set to '%s'." % \
+ ( str( name ), str( status ) ) )
tool_shed_repository.description = description
tool_shed_repository.changeset_revision = current_changeset_revision
tool_shed_repository.ctx_rev = ctx_rev
@@ -267,7 +275,8 @@
tool_shed_repository.uninstalled = uninstalled
tool_shed_repository.status = status
else:
- log.debug( "Adding new row for repository '%s' in the tool_shed_repository table, status set to '%s'." % ( str( name ), str( status ) ) )
+ log.debug( "Adding new row for repository '%s' in the tool_shed_repository table, status set to '%s'." % \
+ ( str( name ), str( status ) ) )
tool_shed_repository = \
app.install_model.ToolShedRepository( tool_shed=tool_shed,
name=name,
@@ -1028,8 +1037,8 @@
owner=owner,
changeset_revision=changeset_revision )
if not repository:
- # The received changeset_revision is no longer installable, so get the next changeset_revision in the repository's changelog in the
- # tool shed that is associated with repository_metadata.
+ # The received changeset_revision is no longer installable, so get the next changeset_revision
+ # in the repository's changelog in the tool shed that is associated with repository_metadata.
tool_shed_url = get_url_from_tool_shed( app, tool_shed )
url = url_join( tool_shed_url,
'repository/next_installable_changeset_revision?name=%s&owner=%s&changeset_revision=%s' % \
@@ -1305,7 +1314,10 @@
.first()
def get_tool_shed_repository_by_shed_name_owner_changeset_revision( app, tool_shed, name, owner, changeset_revision ):
- """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and current changeet_revision."""
+ """
+ Return a tool shed repository database record defined by the combination of a tool_shed, repository name,
+ repository owner and current changeet_revision.
+ """
# This method is used only in Galaxy, not the tool shed.
repository_query = __repository_query( app )
if tool_shed.find( '//' ) > 0:
@@ -1319,7 +1331,10 @@
.first()
def get_tool_shed_repository_by_shed_name_owner_installed_changeset_revision( app, tool_shed, name, owner, installed_changeset_revision ):
- """Return a tool shed repository database record defined by the combination of a tool_shed, repository name, repository owner and installed_changeet_revision."""
+ """
+ Return a tool shed repository database record defined by the combination of a tool_shed,
+ repository name, repository owner and installed_changeet_revision.
+ """
# This method is used only in Galaxy, not the tool shed.
repository_query = __repository_query( app )
if tool_shed.find( '//' ) > 0:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
3 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d339a00374b9/
Changeset: d339a00374b9
User: martenson
Date: 2014-03-05 21:07:42
Summary: library API improvements - DELETE and PATCH; addition of http error codes and exceptions; slight refator; small bugfix
Affected #: 4 files
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/exceptions/__init__.py
--- a/lib/galaxy/exceptions/__init__.py
+++ b/lib/galaxy/exceptions/__init__.py
@@ -31,42 +31,68 @@
pass
-class ItemAccessibilityException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+class ObjectInvalid( Exception ):
+ """ Accessed object store ID is invalid """
+ pass
+# Please keep the exceptions ordered by status code
-class ItemOwnershipException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_DOES_NOT_OWN_ITEM
+class ActionInputError( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+ def __init__( self, err_msg, type="error" ):
+ super( ActionInputError, self ).__init__( err_msg, type )
class DuplicatedSlugException( MessageException ):
status_code = 400
err_code = error_codes.USER_SLUG_DUPLICATE
-
class ObjectAttributeInvalidException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_INVALID
-
class ObjectAttributeMissingException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_MISSING
+class MalformedId( MessageException ):
+ status_code = 400
+ err_code = error_codes.MALFORMED_ID
-class ActionInputError( MessageException ):
- def __init__( self, err_msg, type="error" ):
- super( ActionInputError, self ).__init__( err_msg, type )
+class RequestParameterMissingException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_MISSING_PARAMETER
+class RequestParameterInvalidException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+
+class ItemAccessibilityException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+
+class ItemOwnershipException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_DOES_NOT_OWN_ITEM
class ObjectNotFound( MessageException ):
""" Accessed object was not found """
status_code = 404
err_code = error_codes.USER_OBJECT_NOT_FOUND
+class Conflict( MessageException ):
+ status_code = 409
+ err_code = error_codes.CONFLICT
-class ObjectInvalid( Exception ):
- """ Accessed object store ID is invalid """
- pass
+class InconsistentDatabase ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INCONSISTENT_DATABASE
+
+class InternalServerError ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INTERNAL_SERVER_ERROR
+
+class NotImplemented ( MessageException ):
+ status_code = 501
+ err_code = error_codes.NOT_IMPLEMENTED
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -3,7 +3,7 @@
"name": "UNKNOWN",
"code": 0,
"message": "Unknown error occurred while processing request."
- },
+ },
{
"name": "USER_CANNOT_RUN_AS",
"code": 400001,
@@ -35,6 +35,21 @@
"message": "Slug must be unique per user."
},
{
+ "name": "USER_REQUEST_MISSING_PARAMETER",
+ "code": 400007,
+ "message": "Request is missing parameter required to complete desired action."
+ },
+ {
+ "name": "USER_REQUEST_INVALID_PARAMETER",
+ "code": 400008,
+ "message": "Request contained invalid parameter, action could not be completed."
+ },
+ {
+ "name": "MALFORMED_ID",
+ "code": 400009,
+ "message": "The id of the resource is malformed."
+ },
+ {
"name": "USER_NO_API_KEY",
"code": 403001,
"message": "API Authentication Required for this request"
@@ -53,5 +68,25 @@
"name": "USER_OBJECT_NOT_FOUND",
"code": 404001,
"message": "No such object found."
+ },
+ {
+ "name": "CONFLICT",
+ "code": 409001,
+ "message": "Database conflict prevented fulfilling the request."
+ },
+ {
+ "name": "INTERNAL_SERVER_ERROR",
+ "code": 500001,
+ "message": "Internal server error."
+ },
+ {
+ "name": "INCONSISTENT_DATABASE",
+ "code": 500001,
+ "message": "Inconsistent database prevented fulfilling the request."
+ },
+ {
+ "name": "NOT_IMPLEMENTED",
+ "code": 501001,
+ "message": "Method is not implemented."
}
]
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -2,10 +2,12 @@
API operations on a data library.
"""
from galaxy import util
+from galaxy.util import string_as_bool
from galaxy import web
+from galaxy import exceptions
+from galaxy.web import _future_expose_api as expose_api
from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController, url_for
-from paste.httpexceptions import HTTPBadRequest, HTTPForbidden
import logging
log = logging.getLogger( __name__ )
@@ -13,7 +15,7 @@
class LibrariesController( BaseAPIController ):
- @web.expose_api
+ @expose_api
def index( self, trans, deleted='False', **kwd ):
"""
index( self, trans, deleted='False', **kwd )
@@ -22,11 +24,12 @@
* GET /api/libraries/deleted:
Returns a list of summary data for ``deleted`` libraries.
- :param deleted: if True, show only deleted libraries, if False, ``non-deleted``
+ :param deleted: if True, show only ``deleted`` libraries, if False or nonpresent show only ``non-deleted``
:type deleted: boolean
+ :returns: list of dictionaries containing library information
:rtype: list
- :returns: list of dictionaries containing library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_collection_visible_keys`
"""
query = trans.sa_session.query( trans.app.model.Library )
@@ -50,13 +53,13 @@
libraries = []
for library in query:
item = library.to_dict( view='element' )
- item['url'] = url_for( route, id=trans.security.encode_id( library.id ) )
- item['id'] = trans.security.encode_id( item['id'] )
- item['root_folder_id'] = 'F' + trans.security.encode_id( item['root_folder_id'] )
+ item[ 'url' ] = url_for( route, id=trans.security.encode_id( library.id ) )
+ item[ 'id' ] = trans.security.encode_id( item[ 'id' ] )
+ item[ 'root_folder_id' ] = 'F' + trans.security.encode_id( item[ 'root_folder_id' ] )
libraries.append( item )
return libraries
- @web.expose_api
+ @expose_api
def show( self, trans, id, deleted='False', **kwd ):
"""
show( self, trans, id, deleted='False', **kwd )
@@ -70,50 +73,50 @@
:param deleted: if True, allow information on a ``deleted`` library
:type deleted: boolean
+ :returns: detailed library information
:rtype: dictionary
- :returns: detailed library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
library_id = id
deleted = util.string_as_bool( deleted )
try:
decoded_library_id = trans.security.decode_id( library_id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
assert library.deleted == deleted
except:
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- item = library.to_dict( view='element' )
- item['contents_url'] = url_for( 'library_contents', library_id=library_id )
- return item
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- @web.expose_api
+ @expose_api
def create( self, trans, payload, **kwd ):
"""
create( self, trans, payload, **kwd )
* POST /api/libraries:
Creates a new library. Only ``name`` parameter is required.
+
.. note:: Currently, only admin users can create libraries.
- :param payload: (optional) dictionary structure containing::
- 'name': the new library's name
- 'description': the new library's description
- 'synopsis': the new library's synopsis
+ :param payload: dictionary structure containing::
+ 'name': the new library's name (required)
+ 'description': the new library's description (optional)
+ 'synopsis': the new library's synopsis (optional)
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the new library
"""
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to create a new library.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can create libraries.' )
params = util.Params( payload )
name = util.restore_text( params.get( 'name', None ) )
if not name:
- raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
description = util.restore_text( params.get( 'description', '' ) )
synopsis = util.restore_text( params.get( 'synopsis', '' ) )
if synopsis in [ 'None', None ]:
@@ -123,63 +126,95 @@
library.root_folder = root_folder
trans.sa_session.add_all( ( library, root_folder ) )
trans.sa_session.flush()
- encoded_id = trans.security.encode_id( library.id )
- new_library = {}
- new_library['url'] = url_for( 'library', id=encoded_id )
- new_library['name'] = name
- new_library['description'] = description
- new_library['synopsis'] = synopsis
- new_library['id'] = encoded_id
- new_library['root_folder_id'] = trans.security.encode_id( root_folder.id )
- return new_library
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- def edit( self, trans, encoded_id, payload, **kwd ):
+ @expose_api
+ def update( self, trans, id, **kwd ):
"""
- * PUT /api/libraries/{encoded_id}
+ * PATCH /api/libraries/{encoded_id}
Updates the library defined by an ``encoded_id`` with the data in the payload.
- .. note:: Currently, only admin users can edit libraries.
+ .. note:: Currently, only admin users can update libraries.
:param payload: (required) dictionary structure containing::
- 'name': new library's name
+ 'name': new library's name, cannot be empty
'description': new library's description
'synopsis': new library's synopsis
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the updated library
- """
- return "Not implemented yet"
-
- @web.expose_api
- def delete( self, trans, id, **kwd ):
- """
- delete( self, trans, id, **kwd )
- * DELETE /api/histories/{id}
- mark the library with the given ``id`` as deleted
-
- .. note:: Currently, only admin users can delete libraries.
-
- :param id: the encoded id of the library to delete
- :type id: str
-
- :rtype: dictionary
- :returns: detailed library information
- .. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to delete libraries.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can update libraries.' )
+
try:
decoded_id = trans.security.decode_id( id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
+ library = None
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
except:
library = None
if not library:
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- library.deleted = True
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ payload = kwd.get( 'payload', None )
+ if payload:
+ name = payload.get( 'name', None )
+ if name == '':
+ raise exceptions.RequestParameterMissingException( "Parameter 'name' of library is required. You cannot remove it." )
+ library.name = name
+ if payload.get( 'description', None ) or payload.get( 'description', None ) == '':
+ library.description = payload.get( 'description', None )
+ if payload.get( 'synopsis', None ) or payload.get( 'synopsis', None ) == '':
+ library.synopsis = payload.get( 'synopsis', None )
+ else:
+ raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id } )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+
+ @expose_api
+ def delete( self, trans, id, **kwd ):
+ """
+ delete( self, trans, id, **kwd )
+ * DELETE /api/libraries/{id}
+ marks the library with the given ``id`` as `deleted` (or removes the `deleted` mark if the `undelete` param is true)
+
+ .. note:: Currently, only admin users can un/delete libraries.
+
+ :param id: the encoded id of the library to un/delete
+ :type id: str
+
+ :param undelete: flag specifying whether the item should be deleted or undeleted, defaults to false:
+ :type undelete: bool
+
+ :returns: detailed library information
+ :rtype: dictionary
+
+ .. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
+ """
+ undelete = string_as_bool( kwd.get( 'undelete', False ) )
+ if not trans.user_is_admin():
+ raise exceptions.ItemAccessibilityException( 'Only administrators can delete and undelete libraries.' )
+ try:
+ decoded_id = trans.security.decode_id( id )
+ except:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
+ except:
+ library = None
+ if not library:
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ if undelete:
+ library.deleted = False
+ else:
+ library.deleted = True
+
+ trans.sa_session.add( library )
+ trans.sa_session.flush()
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
diff -r 4cad859d032560a123f57eac78a81f852dc7531e -r d339a00374b9fea91e659256be9db20ed226e9fe lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -135,7 +135,6 @@
path_prefix='/api/histories/:history_id/contents/:history_content_id' )
webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
- webapp.mapper.resource_with_deleted( 'library', 'libraries', path_prefix='/api' )
webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
@@ -206,6 +205,18 @@
# ===== LIBRARY API =====
# =======================
+ webapp.mapper.connect( 'delete_library',
+ '/api/libraries/:id',
+ controller='libraries',
+ action='delete',
+ conditions=dict( method=[ "DELETE" ] ) )
+
+ webapp.mapper.connect( 'update_library',
+ '/api/libraries/:id',
+ controller='libraries',
+ action='update',
+ conditions=dict( method=[ "PATCH" ] ) )
+
webapp.mapper.connect( 'show_lda_item',
'/api/libraries/datasets/:id',
controller='lda_datasets',
https://bitbucket.org/galaxy/galaxy-central/commits/03dd71b129e5/
Changeset: 03dd71b129e5
User: martenson
Date: 2014-03-06 16:49:36
Summary: API libraries exceptions improvement, unnecessary endpoint removal
Affected #: 3 files
diff -r d339a00374b9fea91e659256be9db20ed226e9fe -r 03dd71b129e5dd19b0687ef56f75a270816433b0 lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -81,7 +81,7 @@
},
{
"name": "INCONSISTENT_DATABASE",
- "code": 500001,
+ "code": 500002,
"message": "Inconsistent database prevented fulfilling the request."
},
{
diff -r d339a00374b9fea91e659256be9db20ed226e9fe -r 03dd71b129e5dd19b0687ef56f75a270816433b0 lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -82,12 +82,12 @@
deleted = util.string_as_bool( deleted )
try:
decoded_library_id = trans.security.decode_id( library_id )
- except:
+ except Exception:
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
assert library.deleted == deleted
- except:
+ except Exception:
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
@@ -150,12 +150,12 @@
try:
decoded_id = trans.security.decode_id( id )
- except:
+ except Exception:
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
library = None
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
- except:
+ except Exception:
library = None
if not library:
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
@@ -201,11 +201,11 @@
raise exceptions.ItemAccessibilityException( 'Only administrators can delete and undelete libraries.' )
try:
decoded_id = trans.security.decode_id( id )
- except:
+ except Exception:
raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
- except:
+ except Exception:
library = None
if not library:
raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
diff -r d339a00374b9fea91e659256be9db20ed226e9fe -r 03dd71b129e5dd19b0687ef56f75a270816433b0 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -205,12 +205,6 @@
# ===== LIBRARY API =====
# =======================
- webapp.mapper.connect( 'delete_library',
- '/api/libraries/:id',
- controller='libraries',
- action='delete',
- conditions=dict( method=[ "DELETE" ] ) )
-
webapp.mapper.connect( 'update_library',
'/api/libraries/:id',
controller='libraries',
https://bitbucket.org/galaxy/galaxy-central/commits/8093e5f39efb/
Changeset: 8093e5f39efb
User: martenson
Date: 2014-03-06 17:07:40
Summary: Merged in martenson/galaxy-central-marten (pull request #344)
library API improvements - DELETE and PATCH; addition to John's http error codes and exceptions; slight refator; small bugfix
Affected #: 4 files
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/exceptions/__init__.py
--- a/lib/galaxy/exceptions/__init__.py
+++ b/lib/galaxy/exceptions/__init__.py
@@ -31,42 +31,68 @@
pass
-class ItemAccessibilityException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+class ObjectInvalid( Exception ):
+ """ Accessed object store ID is invalid """
+ pass
+# Please keep the exceptions ordered by status code
-class ItemOwnershipException( MessageException ):
- status_code = 403
- err_code = error_codes.USER_DOES_NOT_OWN_ITEM
+class ActionInputError( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+ def __init__( self, err_msg, type="error" ):
+ super( ActionInputError, self ).__init__( err_msg, type )
class DuplicatedSlugException( MessageException ):
status_code = 400
err_code = error_codes.USER_SLUG_DUPLICATE
-
class ObjectAttributeInvalidException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_INVALID
-
class ObjectAttributeMissingException( MessageException ):
status_code = 400
err_code = error_codes.USER_OBJECT_ATTRIBUTE_MISSING
+class MalformedId( MessageException ):
+ status_code = 400
+ err_code = error_codes.MALFORMED_ID
-class ActionInputError( MessageException ):
- def __init__( self, err_msg, type="error" ):
- super( ActionInputError, self ).__init__( err_msg, type )
+class RequestParameterMissingException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_MISSING_PARAMETER
+class RequestParameterInvalidException( MessageException ):
+ status_code = 400
+ err_code = error_codes.USER_REQUEST_INVALID_PARAMETER
+
+class ItemAccessibilityException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_CANNOT_ACCESS_ITEM
+
+class ItemOwnershipException( MessageException ):
+ status_code = 403
+ err_code = error_codes.USER_DOES_NOT_OWN_ITEM
class ObjectNotFound( MessageException ):
""" Accessed object was not found """
status_code = 404
err_code = error_codes.USER_OBJECT_NOT_FOUND
+class Conflict( MessageException ):
+ status_code = 409
+ err_code = error_codes.CONFLICT
-class ObjectInvalid( Exception ):
- """ Accessed object store ID is invalid """
- pass
+class InconsistentDatabase ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INCONSISTENT_DATABASE
+
+class InternalServerError ( MessageException ):
+ status_code = 500
+ err_code = error_codes.INTERNAL_SERVER_ERROR
+
+class NotImplemented ( MessageException ):
+ status_code = 501
+ err_code = error_codes.NOT_IMPLEMENTED
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/exceptions/error_codes.json
--- a/lib/galaxy/exceptions/error_codes.json
+++ b/lib/galaxy/exceptions/error_codes.json
@@ -3,7 +3,7 @@
"name": "UNKNOWN",
"code": 0,
"message": "Unknown error occurred while processing request."
- },
+ },
{
"name": "USER_CANNOT_RUN_AS",
"code": 400001,
@@ -35,6 +35,21 @@
"message": "Slug must be unique per user."
},
{
+ "name": "USER_REQUEST_MISSING_PARAMETER",
+ "code": 400007,
+ "message": "Request is missing parameter required to complete desired action."
+ },
+ {
+ "name": "USER_REQUEST_INVALID_PARAMETER",
+ "code": 400008,
+ "message": "Request contained invalid parameter, action could not be completed."
+ },
+ {
+ "name": "MALFORMED_ID",
+ "code": 400009,
+ "message": "The id of the resource is malformed."
+ },
+ {
"name": "USER_NO_API_KEY",
"code": 403001,
"message": "API Authentication Required for this request"
@@ -53,5 +68,25 @@
"name": "USER_OBJECT_NOT_FOUND",
"code": 404001,
"message": "No such object found."
+ },
+ {
+ "name": "CONFLICT",
+ "code": 409001,
+ "message": "Database conflict prevented fulfilling the request."
+ },
+ {
+ "name": "INTERNAL_SERVER_ERROR",
+ "code": 500001,
+ "message": "Internal server error."
+ },
+ {
+ "name": "INCONSISTENT_DATABASE",
+ "code": 500002,
+ "message": "Inconsistent database prevented fulfilling the request."
+ },
+ {
+ "name": "NOT_IMPLEMENTED",
+ "code": 501001,
+ "message": "Method is not implemented."
}
]
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/webapps/galaxy/api/libraries.py
--- a/lib/galaxy/webapps/galaxy/api/libraries.py
+++ b/lib/galaxy/webapps/galaxy/api/libraries.py
@@ -2,10 +2,12 @@
API operations on a data library.
"""
from galaxy import util
+from galaxy.util import string_as_bool
from galaxy import web
+from galaxy import exceptions
+from galaxy.web import _future_expose_api as expose_api
from galaxy.model.orm import and_, not_, or_
from galaxy.web.base.controller import BaseAPIController, url_for
-from paste.httpexceptions import HTTPBadRequest, HTTPForbidden
import logging
log = logging.getLogger( __name__ )
@@ -13,7 +15,7 @@
class LibrariesController( BaseAPIController ):
- @web.expose_api
+ @expose_api
def index( self, trans, deleted='False', **kwd ):
"""
index( self, trans, deleted='False', **kwd )
@@ -22,11 +24,12 @@
* GET /api/libraries/deleted:
Returns a list of summary data for ``deleted`` libraries.
- :param deleted: if True, show only deleted libraries, if False, ``non-deleted``
+ :param deleted: if True, show only ``deleted`` libraries, if False or nonpresent show only ``non-deleted``
:type deleted: boolean
+ :returns: list of dictionaries containing library information
:rtype: list
- :returns: list of dictionaries containing library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_collection_visible_keys`
"""
query = trans.sa_session.query( trans.app.model.Library )
@@ -50,13 +53,13 @@
libraries = []
for library in query:
item = library.to_dict( view='element' )
- item['url'] = url_for( route, id=trans.security.encode_id( library.id ) )
- item['id'] = trans.security.encode_id( item['id'] )
- item['root_folder_id'] = 'F' + trans.security.encode_id( item['root_folder_id'] )
+ item[ 'url' ] = url_for( route, id=trans.security.encode_id( library.id ) )
+ item[ 'id' ] = trans.security.encode_id( item[ 'id' ] )
+ item[ 'root_folder_id' ] = 'F' + trans.security.encode_id( item[ 'root_folder_id' ] )
libraries.append( item )
return libraries
- @web.expose_api
+ @expose_api
def show( self, trans, id, deleted='False', **kwd ):
"""
show( self, trans, id, deleted='False', **kwd )
@@ -70,50 +73,50 @@
:param deleted: if True, allow information on a ``deleted`` library
:type deleted: boolean
+ :returns: detailed library information
:rtype: dictionary
- :returns: detailed library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
library_id = id
deleted = util.string_as_bool( deleted )
try:
decoded_library_id = trans.security.decode_id( library_id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except Exception:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_library_id )
assert library.deleted == deleted
- except:
+ except Exception:
library = None
if not library or not ( trans.user_is_admin() or trans.app.security_agent.can_access_library( trans.get_current_user_roles(), library ) ):
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- item = library.to_dict( view='element' )
- item['contents_url'] = url_for( 'library_contents', library_id=library_id )
- return item
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- @web.expose_api
+ @expose_api
def create( self, trans, payload, **kwd ):
"""
create( self, trans, payload, **kwd )
* POST /api/libraries:
Creates a new library. Only ``name`` parameter is required.
+
.. note:: Currently, only admin users can create libraries.
- :param payload: (optional) dictionary structure containing::
- 'name': the new library's name
- 'description': the new library's description
- 'synopsis': the new library's synopsis
+ :param payload: dictionary structure containing::
+ 'name': the new library's name (required)
+ 'description': the new library's description (optional)
+ 'synopsis': the new library's synopsis (optional)
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the new library
"""
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to create a new library.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can create libraries.' )
params = util.Params( payload )
name = util.restore_text( params.get( 'name', None ) )
if not name:
- raise HTTPBadRequest( detail="Missing required parameter 'name'." )
+ raise exceptions.RequestParameterMissingException( "Missing required parameter 'name'." )
description = util.restore_text( params.get( 'description', '' ) )
synopsis = util.restore_text( params.get( 'synopsis', '' ) )
if synopsis in [ 'None', None ]:
@@ -123,63 +126,95 @@
library.root_folder = root_folder
trans.sa_session.add_all( ( library, root_folder ) )
trans.sa_session.flush()
- encoded_id = trans.security.encode_id( library.id )
- new_library = {}
- new_library['url'] = url_for( 'library', id=encoded_id )
- new_library['name'] = name
- new_library['description'] = description
- new_library['synopsis'] = synopsis
- new_library['id'] = encoded_id
- new_library['root_folder_id'] = trans.security.encode_id( root_folder.id )
- return new_library
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
- def edit( self, trans, encoded_id, payload, **kwd ):
+ @expose_api
+ def update( self, trans, id, **kwd ):
"""
- * PUT /api/libraries/{encoded_id}
+ * PATCH /api/libraries/{encoded_id}
Updates the library defined by an ``encoded_id`` with the data in the payload.
- .. note:: Currently, only admin users can edit libraries.
+ .. note:: Currently, only admin users can update libraries.
:param payload: (required) dictionary structure containing::
- 'name': new library's name
+ 'name': new library's name, cannot be empty
'description': new library's description
'synopsis': new library's synopsis
:type payload: dict
+ :returns: detailed library information
:rtype: dict
- :returns: a dictionary containing the encoded_id, name, description, synopsis, and 'show' url of the updated library
"""
- return "Not implemented yet"
+ if not trans.user_is_admin():
+ raise exceptions.ItemAccessibilityException( 'Only administrators can update libraries.' )
- @web.expose_api
+ try:
+ decoded_id = trans.security.decode_id( id )
+ except Exception:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
+ library = None
+ try:
+ library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
+ except Exception:
+ library = None
+ if not library:
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ payload = kwd.get( 'payload', None )
+ if payload:
+ name = payload.get( 'name', None )
+ if name == '':
+ raise exceptions.RequestParameterMissingException( "Parameter 'name' of library is required. You cannot remove it." )
+ library.name = name
+ if payload.get( 'description', None ) or payload.get( 'description', None ) == '':
+ library.description = payload.get( 'description', None )
+ if payload.get( 'synopsis', None ) or payload.get( 'synopsis', None ) == '':
+ library.synopsis = payload.get( 'synopsis', None )
+ else:
+ raise exceptions.RequestParameterMissingException( "You did not specify any payload." )
+ trans.sa_session.add( library )
+ trans.sa_session.flush()
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
+
+ @expose_api
def delete( self, trans, id, **kwd ):
"""
delete( self, trans, id, **kwd )
- * DELETE /api/histories/{id}
- mark the library with the given ``id`` as deleted
+ * DELETE /api/libraries/{id}
+ marks the library with the given ``id`` as `deleted` (or removes the `deleted` mark if the `undelete` param is true)
- .. note:: Currently, only admin users can delete libraries.
+ .. note:: Currently, only admin users can un/delete libraries.
- :param id: the encoded id of the library to delete
+ :param id: the encoded id of the library to un/delete
:type id: str
+ :param undelete: flag specifying whether the item should be deleted or undeleted, defaults to false:
+ :type undelete: bool
+
+ :returns: detailed library information
:rtype: dictionary
- :returns: detailed library information
+
.. seealso:: :attr:`galaxy.model.Library.dict_element_visible_keys`
"""
+ undelete = string_as_bool( kwd.get( 'undelete', False ) )
if not trans.user_is_admin():
- raise HTTPForbidden( detail='You are not authorized to delete libraries.' )
+ raise exceptions.ItemAccessibilityException( 'Only administrators can delete and undelete libraries.' )
try:
decoded_id = trans.security.decode_id( id )
- except TypeError:
- raise HTTPBadRequest( detail='Malformed library id ( %s ) specified, unable to decode.' % id )
+ except Exception:
+ raise exceptions.MalformedId( 'Malformed library id ( %s ) specified, unable to decode.' % id )
try:
library = trans.sa_session.query( trans.app.model.Library ).get( decoded_id )
- except:
+ except Exception:
library = None
if not library:
- raise HTTPBadRequest( detail='Invalid library id ( %s ) specified.' % id )
- library.deleted = True
+ raise exceptions.ObjectNotFound( 'Library with the id provided ( %s ) was not found' % id )
+
+ if undelete:
+ library.deleted = False
+ else:
+ library.deleted = True
+
trans.sa_session.add( library )
trans.sa_session.flush()
- return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id } )
+ return library.to_dict( view='element', value_mapper={ 'id' : trans.security.encode_id , 'root_folder_id' : trans.security.encode_id } )
diff -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 -r 8093e5f39efb831da042a20fa2bb850470355d7a lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -135,7 +135,6 @@
path_prefix='/api/histories/:history_id/contents/:history_content_id' )
webapp.mapper.resource( 'dataset', 'datasets', path_prefix='/api' )
- webapp.mapper.resource_with_deleted( 'library', 'libraries', path_prefix='/api' )
webapp.mapper.resource( 'sample', 'samples', path_prefix='/api' )
webapp.mapper.resource( 'request', 'requests', path_prefix='/api' )
webapp.mapper.resource( 'form', 'forms', path_prefix='/api' )
@@ -206,6 +205,12 @@
# ===== LIBRARY API =====
# =======================
+ webapp.mapper.connect( 'update_library',
+ '/api/libraries/:id',
+ controller='libraries',
+ action='update',
+ conditions=dict( method=[ "PATCH" ] ) )
+
webapp.mapper.connect( 'show_lda_item',
'/api/libraries/datasets/:id',
controller='lda_datasets',
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: UI: Attach modal to body instead of #everything
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/52948dd567c8/
Changeset: 52948dd567c8
User: guerler
Date: 2014-03-06 07:41:16
Summary: UI: Attach modal to body instead of #everything
Affected #: 3 files
diff -r 310f5893da982d054b07de669f022dcfba4b1d3d -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,8 +1,8 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
+define(['mvc/ui/ui-modal', 'mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
'plugin/views/charts', 'plugin/views/chart',
'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
- function( Portlet, Ui, Utils, Jobs, Datasets,
+ function( Modal, Portlet, Ui, Utils, Jobs, Datasets,
ChartsView, ChartView,
Config, Chart, Charts, Types
) {
@@ -16,8 +16,12 @@
// link options
this.options = options;
- // link galaxy
- this.modal = Galaxy.modal;
+ // link galaxy modal or create one
+ if (Galaxy && Galaxy.modal) {
+ this.modal = Galaxy.modal;
+ } else {
+ this.modal = new Modal.View();
+ }
// create configuration model
this.config = new Config();
diff -r 310f5893da982d054b07de669f022dcfba4b1d3d -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 static/scripts/mvc/ui/ui-modal.js
--- a/static/scripts/mvc/ui/ui-modal.js
+++ b/static/scripts/mvc/ui/ui-modal.js
@@ -4,7 +4,7 @@
var View = Backbone.View.extend({
// base element
- elMain: '#everything',
+ elMain: 'body',
// defaults options
optionsDefault: {
diff -r 310f5893da982d054b07de669f022dcfba4b1d3d -r 52948dd567c86e5c0ce83ff0c5e80d3fe175c8a1 static/scripts/packed/mvc/ui/ui-modal.js
--- a/static/scripts/packed/mvc/ui/ui-modal.js
+++ b/static/scripts/packed/mvc/ui/ui-modal.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,this.optionsDefault);if(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>')}if(this.$el){this.$el.remove();$(document).off("keyup")}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);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){d.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){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">'+c+'</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:b}});
\ No newline at end of file
+define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,this.optionsDefault);if(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>')}if(this.$el){this.$el.remove();$(document).off("keyup")}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);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){d.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){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">'+c+'</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: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: guerler: UI: Shift modal wrapper into mvc library
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/310f5893da98/
Changeset: 310f5893da98
User: guerler
Date: 2014-03-06 07:28:51
Summary: UI: Shift modal wrapper into mvc library
Affected #: 10 files
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d config/plugins/visualizations/charts/static/library/jobs.js
--- a/config/plugins/visualizations/charts/static/library/jobs.js
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -48,7 +48,9 @@
self.app.log('handle::load()', 'Job submission failed.');
} else {
// update galaxy history
- Galaxy.currHistoryPanel.refreshHdas();
+ if (Galaxy && Galaxy.currHistoryPanel) {
+ Galaxy.currHistoryPanel.refreshHdas();
+ }
// get dataset
var job = response.outputs[0];
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -9,10 +9,9 @@
// dependencies
define([
- "galaxy.modal",
"galaxy.masthead",
"utils/utils",
- "libs/toastr"], function(mod_modal, mod_masthead, mod_utils, mod_toastr) {
+ "libs/toastr"], function(mod_masthead, mod_utils, mod_toastr) {
// MMMMMMMMMMMMMMM
// === Models ====
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/galaxy.modal.js
--- a/static/scripts/galaxy.modal.js
+++ /dev/null
@@ -1,198 +0,0 @@
-// dependencies
-define([], function() {
-
-// modal
-var GalaxyModal = Backbone.View.extend(
-{
- // base element
- elMain: '#everything',
-
- // defaults options
- optionsDefault: {
- title : "galaxy-modal",
- body : "",
- backdrop : true,
- height : null,
- width : null,
- closing_events : false
- },
-
- // button list
- buttonList: {},
-
- // initialize
- initialize : function(options) {
- if (options){
- this._create(options);
- }
- },
-
- // adds and displays a new frame/window
- show: function(options) {
- // create
- this.initialize(options);
-
- // fix height
- if (this.options.height){
- this.$body.css('height', this.options.height);
- this.$body.css('overflow', 'hidden');
- } else{
- this.$body.css('max-height', $(window).height() / 2);
- }
-
- // fix width
- if (this.options.width){
- this.$dialog.css('width', this.options.width);
- }
-
- // show
- if (this.visible) {
- this.$el.show();
- } else {
- this.$el.fadeIn('fast');
- }
-
- // set visible flag
- this.visible = true;
- },
-
- // hide
- hide: function() {
- this.visible = false;
- this.$el.fadeOut('fast');
- },
-
- // enable buttons
- enableButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).prop('disabled', false);
- },
-
- // disable buttons
- disableButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).prop('disabled', true);
- },
-
- // show buttons
- showButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).show();
- },
-
- // hide buttons
- hideButton: function(name) {
- var button_id = this.buttonList[name];
- this.$buttons.find('#' + button_id).hide();
- },
-
- // get button
- getButton: function(name) {
- var button_id = this.buttonList[name];
- return this.$buttons.find('#' + button_id);
- },
-
- // returns scroll top for body element
- scrollTop: function() {
- return this.$body.scrollTop();
- },
-
- // create
- _create: function(options) {
- // link this
- var self = this;
-
- // configure options
- this.options = _.defaults(options, this.optionsDefault);
-
- // check for progress bar request
- if (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>');
- }
-
- // remove former element
- if (this.$el) {
- // remove element
- this.$el.remove();
-
- // remove escape event
- $(document).off('keyup');
- }
-
- // create new element
- this.setElement(this._template(this.options.title));
-
- // link elements
- 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');
-
- // append body
- this.$body.html(this.options.body);
-
- // configure background
- if (!this.options.backdrop){
- this.$backdrop.removeClass('in');
- }
-
- // append buttons
- if (this.options.buttons) {
- // reset button list
- this.buttonList = {};
- var counter = 0;
- $.each(this.options.buttons, function(name, value) {
- var button_id = 'button-' + counter++;
- self.$buttons.append($('<button id="' + button_id + '"></button>').text(name).click(value)).append(" ");
- self.buttonList[name] = button_id;
- });
- } else {
- // hide footer
- this.$footer.hide();
- }
-
- // append to main element
- $(this.elMain).append($(this.el));
-
- // bind additional closing events
- if (this.options.closing_events) {
- // bind the ESC key to hide() function
- if (!this.options.buttons.Pause){ // don't bind for the upload modal because of the side effects with system modal for file choosing
- $(document).on('keyup', function(e) {
- if (e.keyCode == 27) {
- self.hide();
- }
- });
- }
-
- // hide modal if background is clicked
- this.$el.find('.modal-backdrop').on('click', function() { self.hide(); });
- }
- },
-
- // fill regular modal template
- _template: function(title) {
- 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">' + title + '</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 {
- GalaxyModal : GalaxyModal
-}
-
-});
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/mvc/ui/ui-modal.js
--- /dev/null
+++ b/static/scripts/mvc/ui/ui-modal.js
@@ -0,0 +1,197 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+var View = Backbone.View.extend({
+
+ // base element
+ elMain: '#everything',
+
+ // defaults options
+ optionsDefault: {
+ title : 'ui-modal',
+ body : '',
+ backdrop : true,
+ height : null,
+ width : null,
+ closing_events : false
+ },
+
+ // button list
+ buttonList: {},
+
+ // initialize
+ initialize : function(options) {
+ if (options){
+ this._create(options);
+ }
+ },
+
+ // adds and displays a new frame/window
+ show: function(options) {
+ // create
+ this.initialize(options);
+
+ // fix height
+ if (this.options.height){
+ this.$body.css('height', this.options.height);
+ this.$body.css('overflow', 'hidden');
+ } else{
+ this.$body.css('max-height', $(window).height() / 2);
+ }
+
+ // fix width
+ if (this.options.width){
+ this.$dialog.css('width', this.options.width);
+ }
+
+ // show
+ if (this.visible) {
+ this.$el.show();
+ } else {
+ this.$el.fadeIn('fast');
+ }
+
+ // set visible flag
+ this.visible = true;
+ },
+
+ // hide
+ hide: function() {
+ this.visible = false;
+ this.$el.fadeOut('fast');
+ },
+
+ // enable buttons
+ enableButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).prop('disabled', false);
+ },
+
+ // disable buttons
+ disableButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).prop('disabled', true);
+ },
+
+ // show buttons
+ showButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).show();
+ },
+
+ // hide buttons
+ hideButton: function(name) {
+ var button_id = this.buttonList[name];
+ this.$buttons.find('#' + button_id).hide();
+ },
+
+ // get button
+ getButton: function(name) {
+ var button_id = this.buttonList[name];
+ return this.$buttons.find('#' + button_id);
+ },
+
+ // returns scroll top for body element
+ scrollTop: function() {
+ return this.$body.scrollTop();
+ },
+
+ // create
+ _create: function(options) {
+ // link this
+ var self = this;
+
+ // configure options
+ this.options = _.defaults(options, this.optionsDefault);
+
+ // check for progress bar request
+ if (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>');
+ }
+
+ // remove former element
+ if (this.$el) {
+ // remove element
+ this.$el.remove();
+
+ // remove escape event
+ $(document).off('keyup');
+ }
+
+ // create new element
+ this.setElement(this._template(this.options.title));
+
+ // link elements
+ 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');
+
+ // append body
+ this.$body.html(this.options.body);
+
+ // configure background
+ if (!this.options.backdrop){
+ this.$backdrop.removeClass('in');
+ }
+
+ // append buttons
+ if (this.options.buttons) {
+ // reset button list
+ this.buttonList = {};
+ var counter = 0;
+ $.each(this.options.buttons, function(name, value) {
+ var button_id = 'button-' + counter++;
+ self.$buttons.append($('<button id="' + button_id + '"></button>').text(name).click(value)).append(" ");
+ self.buttonList[name] = button_id;
+ });
+ } else {
+ // hide footer
+ this.$footer.hide();
+ }
+
+ // append to main element
+ $(this.elMain).append($(this.el));
+
+ // bind additional closing events
+ if (this.options.closing_events) {
+ // bind the ESC key to hide() function
+ if (!this.options.buttons.Pause){ // don't bind for the upload modal because of the side effects with system modal for file choosing
+ $(document).on('keyup', function(e) {
+ if (e.keyCode == 27) {
+ self.hide();
+ }
+ });
+ }
+
+ // hide modal if background is clicked
+ this.$el.find('.modal-backdrop').on('click', function() { self.hide(); });
+ }
+ },
+
+ // fill regular modal template
+ _template: function(title) {
+ 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">' + title + '</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 : View
+}
+
+});
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/mvc/upload/upload-view.js
--- a/static/scripts/mvc/upload/upload-view.js
+++ b/static/scripts/mvc/upload/upload-view.js
@@ -1,21 +1,21 @@
// dependencies
-define(["galaxy.modal",
- "utils/utils",
+define(["utils/utils",
"mvc/upload/upload-button",
"mvc/upload/upload-model",
"mvc/upload/upload-row",
"mvc/upload/upload-ftp",
"mvc/ui/ui-popover",
+ "mvc/ui/ui-modal",
"mvc/ui",
"utils/uploadbox"],
- function( Modal,
- Utils,
+ function( Utils,
UploadButton,
UploadModel,
UploadItem,
UploadFtp,
- Popover
+ Popover,
+ Modal
) {
// galaxy upload
@@ -177,7 +177,7 @@
if (!this.modal) {
// make modal
var self = this;
- this.modal = new Modal.GalaxyModal({
+ this.modal = new Modal.View({
title : 'Download data directly from web or upload files from your disk',
body : this._template('upload-box', 'upload-info'),
buttons : {
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/galaxy.library.js
--- a/static/scripts/packed/galaxy.library.js
+++ b/static/scripts/packed/galaxy.library.js
@@ -1,1 +1,1 @@
-var view=null;var library_router=null;var responses=[];define(["galaxy.modal","galaxy.masthead","utils/utils","libs/toastr"],function(k,l,h,n){var f=Backbone.Model.extend({urlRoot:"/api/libraries"});var c=Backbone.Model.extend({urlRoot:"/api/folders"});var o=Backbone.Collection.extend({url:"/api/libraries",model:f,sort_key:"name",sort_order:null,});var i=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var d=Backbone.Collection.extend({model:i});var e=Backbone.Model.extend({defaults:{folder:new d(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(r){this.full_path=r[0].full_path;this.get("folder").reset(r[1].folder_contents);return r}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var j=Backbone.Model.extend({url:"/api/histories/"});var p=Backbone.Collection.extend({url:"/api/histories",model:j});var m=Backbone.View.extend({el:"#center",progress:0,progressStep:1,lastSelectedHistory:"",modal:null,folders:null,initialize:function(){this.folders=[];this.queue=jQuery.Deferred();this.queue.resolve()},templateFolder:function(){var r=[];r.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; ">');r.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');r.push('<div id="library_folder_toolbar" >');r.push(' <button title="Create New Folder" id="toolbtn_create_folder" class="btn btn-primary" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder-close"></span> folder</button>');r.push(' <button title="Import selected datasets into history" id="toolbtn_bulk_import" class="btn btn-primary" style="display: none; margin-left: 0.5em;" type="button"><span class="fa fa-external-link"></span> to history</button>');r.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display: none; ">');r.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">');r.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');r.push(" </button>");r.push(' <ul class="dropdown-menu" role="menu">');r.push(' <li><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');r.push(' <li><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');r.push(' <li><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');r.push(" </ul>");r.push(" </div>");r.push("</div>");r.push('<ol class="breadcrumb">');r.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');r.push(" <% _.each(path, function(path_item) { %>");r.push(" <% if (path_item[0] != id) { %>");r.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');r.push("<% } else { %>");r.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');r.push(" <% } %>");r.push(" <% }); %>");r.push("</ol>");r.push('<table id="folder_table" class="library_table table table-condensed">');r.push(" <thead>");r.push(' <th class="button_heading"></th>');r.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');r.push(" <th>name</th>");r.push(" <th>data type</th>");r.push(" <th>size</th>");r.push(" <th>date (UTC)</th>");r.push(" </thead>");r.push(" <tbody>");r.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>');r.push(" <td></td>");r.push(" <td></td>");r.push(" <td></td>");r.push(" <td></td>");r.push(" <td></td>");r.push(" </tr>");r.push(" <% _.each(items, function(content_item) { %>");r.push(' <% if (content_item.get("type") === "folder") { %>');r.push(' <tr class="folder_row light" id="<%- content_item.id %>">');r.push(" <td>");r.push(' <span title="Folder" class="fa fa-folder-o"></span>');r.push(" </td>");r.push(" <td></td>");r.push(" <td>");r.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');r.push(' <% if (content_item.get("item_count") === 0) { %>');r.push(' <span class="muted">(empty folder)</span>');r.push(" <% } %>");r.push(" </td>");r.push(" <td>folder</td>");r.push(' <td><%= _.escape(content_item.get("item_count")) %> item(s)</td>');r.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');r.push(" </tr>");r.push(" <% } else { %>");r.push(' <tr class="dataset_row light" id="<%- content_item.id %>">');r.push(" <td>");r.push(' <span title="Dataset" class="fa fa-file-o"></span>');r.push(" </td>");r.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');r.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');r.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');r.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');r.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');r.push(" </tr>");r.push(" <% } %> ");r.push(" <% }); %>");r.push(" ");r.push(" </tbody>");r.push("</table>");r.push("</div>");return r.join("")},templateDatasetModal:function(){var r=[];r.push('<div class="modal_table">');r.push(' <table class="table table-striped table-condensed">');r.push(" <tr>");r.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');r.push(' <td><%= _.escape(item.get("name")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Data type</th>');r.push(' <td><%= _.escape(item.get("data_type")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Genome build</th>');r.push(' <td><%= _.escape(item.get("genome_build")) %></td>');r.push(" </tr>");r.push(' <th scope="row">Size</th>');r.push(" <td><%= _.escape(size) %></td>");r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Date uploaded (UTC)</th>');r.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Uploaded by</th>');r.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');r.push(" </tr>");r.push(' <tr scope="row">');r.push(' <th scope="row">Data Lines</th>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');r.push(" </tr>");r.push(' <th scope="row">Comment Lines</th>');r.push(' <% if (item.get("metadata_comment_lines") === "") { %>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');r.push(" <% } else { %>");r.push(' <td scope="row">unknown</td>');r.push(" <% } %>");r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Number of Columns</th>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Column Types</th>');r.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');r.push(" </tr>");r.push(" <tr>");r.push(' <th scope="row">Miscellaneous information</th>');r.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');r.push(" </tr>");r.push(" </table>");r.push(' <pre class="peek">');r.push(" </pre>");r.push("</div>");return r.join("")},templateHistorySelectInModal:function(){var r=[];r.push('<span id="history_modal_combo" style="width:90%; margin-left: 1em; margin-right: 1em; ">');r.push("Select history: ");r.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');r.push(" <% _.each(histories, function(history) { %>");r.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');r.push(" <% }); %>");r.push("</select>");r.push("</span>");return r.join("")},templateBulkImportInModal:function(){var r=[];r.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');r.push("Select history: ");r.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');r.push(" <% _.each(histories, function(history) { %>");r.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');r.push(" <% }); %>");r.push("</select>");r.push("</span>");return r.join("")},templateProgressBar:function(){var r=[];r.push('<div class="import_text">');r.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");r.push("</div>");r.push('<div class="progress">');r.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');r.push(' <span class="completion_span">0% Complete</span>');r.push(" </div>");r.push("</div>");r.push("");return r.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 tmpl_array.join("")},events:{"click #select-all-checkboxes":"selectAll","click #toolbtn_bulk_import":"modalBulkImport","click #toolbtn_dl":"bulkDownload","click #toolbtn_create_folder":"createFolderFromModal","click .library-dataset":"showDatasetDetails","click .dataset_row":"selectClickedRow"},render:function(r){$("#center").css("overflow","auto");view=this;var t=this;var s=new e({id:r.id});s.url=s.attributes.urlRoot+r.id+"/contents";s.fetch({success:function(u){for(var w=0;w<s.attributes.folder.models.length;w++){var v=s.attributes.folder.models[w];if(v.get("type")==="file"){v.set("readable_size",t.size_to_string(v.get("file_size")))}}var y=s.full_path;var z;if(y.length===1){z=0}else{z=y[y.length-2][0]}var x=_.template(t.templateFolder(),{path:s.full_path,items:s.attributes.folder.models,id:r.id,upper_folder_id:z});t.$el.html(x)},error:function(){n.error("An error occured :(")}})},size_to_string:function(r){var s="";if(r>=100000000000){r=r/100000000000;s="TB"}else{if(r>=100000000){r=r/100000000;s="GB"}else{if(r>=100000){r=r/100000;s="MB"}else{if(r>=100){r=r/100;s="KB"}else{r=r*10;s="b"}}}}return(Math.round(r)/10)+s},showDatasetDetails:function(u){u.preventDefault();var v=$(u.target).parent().parent().parent().attr("id");if(typeof v==="undefined"){v=$(u.target).parent().attr("id")}if(typeof v==="undefined"){v=$(u.target).parent().parent().attr("id")}var t=new i();var s=new p();t.id=v;var r=this;t.fetch({success:function(w){s.fetch({success:function(x){r.renderModalAfterFetch(w,x)},error:function(){n.error("An error occured during fetching histories:(");r.renderModalAfterFetch(w)}})},error:function(){n.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(w,t){var u=this.size_to_string(w.get("file_size"));var v=_.template(this.templateDatasetModal(),{item:w,size:u});var s=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:v,buttons:{Import:function(){s.importCurrentIntoHistory()},Download:function(){s.downloadCurrent()},Close:function(){s.modal.hide()}}});$(".peek").html(w.get("peek"));if(typeof history.models!==undefined){var r=_.template(this.templateHistorySelectInModal(),{histories:t.models});$(this.modal.elMain).find(".buttons").prepend(r);if(s.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(s.lastSelectedHistory)}}},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var r=[];r.push($("#id_row").attr("data-id"));var s="/api/libraries/datasets/download/uncompressed";var t={ldda_ids:r};folderContentView.processDownload(s,t);this.modal.enableButton("Import");this.modal.enableButton("Download")},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var t=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=t;var r=$("#id_row").attr("data-id");var u=new b();var s=this;u.url=u.urlRoot+t+"/contents";u.save({content:r,source:"library"},{success:function(){n.success("Dataset imported");s.modal.enableButton("Import");s.modal.enableButton("Download")},error:function(){n.error("An error occured! Dataset not imported. Please try again.");s.modal.enableButton("Import");s.modal.enableButton("Download")}})},selectAll:function(s){var r=s.target.checked;that=this;$(":checkbox").each(function(){this.checked=r;$row=$(this.parentElement.parentElement);(r)?that.makeDarkRow($row):that.makeWhiteRow($row)});this.checkTools()},selectClickedRow:function(s){var u="";var r;var t;if(s.target.localName==="input"){u=s.target;r=$(s.target.parentElement.parentElement);t="input"}else{if(s.target.localName==="td"){u=$("#"+s.target.parentElement.id).find(":checkbox")[0];r=$(s.target.parentElement);t="td"}}if(u.checked){if(t==="td"){u.checked="";this.makeWhiteRow(r)}else{if(t==="input"){this.makeDarkRow(r)}}}else{if(t==="td"){u.checked="selected";this.makeDarkRow(r)}else{if(t==="input"){this.makeWhiteRow(r)}}}this.checkTools()},makeDarkRow:function(r){r.removeClass("light");r.find("a").removeClass("light");r.addClass("dark");r.find("a").addClass("dark");r.find("span").removeClass("fa-file-o");r.find("span").addClass("fa-file")},makeWhiteRow:function(r){r.removeClass("dark");r.find("a").removeClass("dark");r.addClass("light");r.find("a").addClass("light");r.find("span").addClass("fa-file-o");r.find("span").removeClass("fa-file")},checkTools:function(){var r=$("#folder_table").find(":checked");if(r.length>0){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}else{$("#toolbtn_bulk_import").hide();$("#toolbtn_dl").hide()}},modalBulkImport:function(){var s=this;var r=new p();r.fetch({success:function(t){var u=_.template(s.templateBulkImportInModal(),{histories:t.models});s.modal=Galaxy.modal;s.modal.show({closing_events:true,title:"Import into History",body:u,buttons:{Import:function(){s.importAllIntoHistory()},Close:function(){s.modal.hide()}}})},error:function(){n.error("An error occured :(")}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var t=$("select[name=dataset_import_bulk] option:selected").val();var x=$("select[name=dataset_import_bulk] option:selected").text();var z=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){z.push(this.parentElement.parentElement.id)}});var y=_.template(this.templateProgressBar(),{history_name:x});$(this.modal.elMain).find(".modal-body").html(y);var u=100/z.length;this.initProgress(u);var r=[];for(var s=z.length-1;s>=0;s--){library_dataset_id=z[s];var v=new b();var w=this;v.url=v.urlRoot+t+"/contents";v.content=library_dataset_id;v.source="library";r.push(v)}this.chainCall(r)},chainCall:function(s){var r=this;var t=s.pop();if(typeof t==="undefined"){n.success("All datasets imported");this.modal.hide();return}var u=$.when(t.save({content:t.content,source:t.source})).done(function(v){r.updateProgress();responses.push(v);r.chainCall(s)})},initProgress:function(r){this.progress=0;this.progressStep=r},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(r,v){var t=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){t.push(this.parentElement.parentElement.id)}});var s="/api/libraries/datasets/download/"+v;var u={ldda_ids:t};this.processDownload(s,u,"get")},processDownload:function(s,t,u){if(s&&t){t=typeof t=="string"?t:$.param(t);var r="";$.each(t.split("&"),function(){var v=this.split("=");r+='<input type="hidden" name="'+v[0]+'" value="'+v[1]+'" />'});$('<form action="'+s+'" method="'+(u||"post")+'">'+r+"</form>").appendTo("body").submit().remove();n.info("Your download will begin soon")}},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var r=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:this.templateNewFolderInModal(),buttons:{Create:function(){r.create_new_folder_event()},Close:function(){r.modal.hide();r.modal=null}}})},create_new_folder_event:function(){var r=this.serialize_new_folder();if(this.validate_new_folder(r)){var t=new c();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];t.url=t.urlRoot+"/"+current_folder_id;var s=this;t.save(r,{success:function(u){s.modal.hide();n.success("Folder created");s.render({id:current_folder_id})},error:function(){n.error("An error occured :(")}})}else{n.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(r){return r.name!==""}});var a=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal"},modal:null,collection:null,initialize:function(){var r=this;this.collection=new o();this.collection.fetch({success:function(s){r.render()},error:function(t,s){if(s.statusCode().status===403){n.info("Please log in first. Redirecting to login page in 3s.");setTimeout(that.redirectToLogin,3000)}else{n.error("An error occured. Please try again.")}}});$("#center").css("overflow","auto")},render:function(t){var r=this.templateLibraryList();var s=null;if(this.collection!==null&&typeof t==="undefined"){s=this.collection.models}else{if(t!==null){s=t}else{s=[]}}this.$el.html(r({libraries:s,order:this.collection.sort_order}))},sortLibraries:function(s,r){if(s==="name"){if(r==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(u,t){if(u.get("name").toLowerCase()>t.get("name").toLowerCase()){return 1}if(t.get("name").toLowerCase()>u.get("name").toLowerCase()){return -1}return 0}}else{if(r==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(u,t){if(u.get("name").toLowerCase()>t.get("name").toLowerCase()){return -1}if(t.get("name").toLowerCase()>u.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; overflow: auto !important; ">');tmpl_array.push("");tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push('<a href="" id="create_new_library_btn" class="btn btn-primary file ">New Library</a>');tmpl_array.push('<table class="library_table table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th><a title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(" <th>description</th>");tmpl_array.push(" <th>synopsis</th> ");tmpl_array.push(" </thead>");tmpl_array.push(" <tbody>");tmpl_array.push(" <% _.each(libraries, function(library) { %>");tmpl_array.push(" <tr>");tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(" </tr>");tmpl_array.push(" <% }); %>");tmpl_array.push(" </tbody>");tmpl_array.push("</table>");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("")},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(s){s.preventDefault();s.stopPropagation();var r=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){r.create_new_library_event()},Close:function(){r.modal.hide()}}})},create_new_library_event:function(){var t=this.serialize_new_library();if(this.validate_new_library(t)){var s=new f();var r=this;s.save(t,{success:function(u){r.collection.add(u);r.modal.hide();r.clear_library_modal();r.render();n.success("Library created")},error:function(){n.error("An error occured :(")}})}else{n.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(r){return r.name!==""}});var q=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var g=Backbone.View.extend({initialize:function(){galaxyLibraryview=new a();library_router=new q();folderContentView=new m();library_router.on("route:libraries",function(){galaxyLibraryview.render()});library_router.on("route:sort_libraries",function(s,r){galaxyLibraryview.sortLibraries(s,r);galaxyLibraryview.render()});library_router.on("route:folder_content",function(r){folderContentView.render({id:r})});library_router.on("route:download",function(r,s){if($("#center").find(":checked").length===0){library_router.navigate("folders/"+r,{trigger:true,replace:true})}else{folderContentView.download(r,s);library_router.navigate("folders/"+r,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:g}});
\ No newline at end of file
+var view=null;var library_router=null;var responses=[];define(["galaxy.masthead","utils/utils","libs/toastr"],function(k,h,m){var f=Backbone.Model.extend({urlRoot:"/api/libraries"});var c=Backbone.Model.extend({urlRoot:"/api/folders"});var n=Backbone.Collection.extend({url:"/api/libraries",model:f,sort_key:"name",sort_order:null,});var i=Backbone.Model.extend({urlRoot:"/api/libraries/datasets"});var d=Backbone.Collection.extend({model:i});var e=Backbone.Model.extend({defaults:{folder:new d(),full_path:"unknown",urlRoot:"/api/folders/",id:"unknown"},parse:function(q){this.full_path=q[0].full_path;this.get("folder").reset(q[1].folder_contents);return q}});var b=Backbone.Model.extend({urlRoot:"/api/histories/"});var j=Backbone.Model.extend({url:"/api/histories/"});var o=Backbone.Collection.extend({url:"/api/histories",model:j});var l=Backbone.View.extend({el:"#center",progress:0,progressStep:1,lastSelectedHistory:"",modal:null,folders:null,initialize:function(){this.folders=[];this.queue=jQuery.Deferred();this.queue.resolve()},templateFolder:function(){var q=[];q.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; ">');q.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');q.push('<div id="library_folder_toolbar" >');q.push(' <button title="Create New Folder" id="toolbtn_create_folder" class="btn btn-primary" type="button"><span class="fa fa-plus"></span><span class="fa fa-folder-close"></span> folder</button>');q.push(' <button title="Import selected datasets into history" id="toolbtn_bulk_import" class="btn btn-primary" style="display: none; margin-left: 0.5em;" type="button"><span class="fa fa-external-link"></span> to history</button>');q.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display: none; ">');q.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="btn btn-primary dropdown-toggle" data-toggle="dropdown">');q.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');q.push(" </button>");q.push(' <ul class="dropdown-menu" role="menu">');q.push(' <li><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');q.push(' <li><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');q.push(' <li><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');q.push(" </ul>");q.push(" </div>");q.push("</div>");q.push('<ol class="breadcrumb">');q.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');q.push(" <% _.each(path, function(path_item) { %>");q.push(" <% if (path_item[0] != id) { %>");q.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');q.push("<% } else { %>");q.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');q.push(" <% } %>");q.push(" <% }); %>");q.push("</ol>");q.push('<table id="folder_table" class="library_table table table-condensed">');q.push(" <thead>");q.push(' <th class="button_heading"></th>');q.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');q.push(" <th>name</th>");q.push(" <th>data type</th>");q.push(" <th>size</th>");q.push(" <th>date (UTC)</th>");q.push(" </thead>");q.push(" <tbody>");q.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>');q.push(" <td></td>");q.push(" <td></td>");q.push(" <td></td>");q.push(" <td></td>");q.push(" <td></td>");q.push(" </tr>");q.push(" <% _.each(items, function(content_item) { %>");q.push(' <% if (content_item.get("type") === "folder") { %>');q.push(' <tr class="folder_row light" id="<%- content_item.id %>">');q.push(" <td>");q.push(' <span title="Folder" class="fa fa-folder-o"></span>');q.push(" </td>");q.push(" <td></td>");q.push(" <td>");q.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');q.push(' <% if (content_item.get("item_count") === 0) { %>');q.push(' <span class="muted">(empty folder)</span>');q.push(" <% } %>");q.push(" </td>");q.push(" <td>folder</td>");q.push(' <td><%= _.escape(content_item.get("item_count")) %> item(s)</td>');q.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');q.push(" </tr>");q.push(" <% } else { %>");q.push(' <tr class="dataset_row light" id="<%- content_item.id %>">');q.push(" <td>");q.push(' <span title="Dataset" class="fa fa-file-o"></span>');q.push(" </td>");q.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');q.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');q.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');q.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');q.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');q.push(" </tr>");q.push(" <% } %> ");q.push(" <% }); %>");q.push(" ");q.push(" </tbody>");q.push("</table>");q.push("</div>");return q.join("")},templateDatasetModal:function(){var q=[];q.push('<div class="modal_table">');q.push(' <table class="table table-striped table-condensed">');q.push(" <tr>");q.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');q.push(' <td><%= _.escape(item.get("name")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Data type</th>');q.push(' <td><%= _.escape(item.get("data_type")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Genome build</th>');q.push(' <td><%= _.escape(item.get("genome_build")) %></td>');q.push(" </tr>");q.push(' <th scope="row">Size</th>');q.push(" <td><%= _.escape(size) %></td>");q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Date uploaded (UTC)</th>');q.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Uploaded by</th>');q.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');q.push(" </tr>");q.push(' <tr scope="row">');q.push(' <th scope="row">Data Lines</th>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');q.push(" </tr>");q.push(' <th scope="row">Comment Lines</th>');q.push(' <% if (item.get("metadata_comment_lines") === "") { %>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');q.push(" <% } else { %>");q.push(' <td scope="row">unknown</td>');q.push(" <% } %>");q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Number of Columns</th>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Column Types</th>');q.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');q.push(" </tr>");q.push(" <tr>");q.push(' <th scope="row">Miscellaneous information</th>');q.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');q.push(" </tr>");q.push(" </table>");q.push(' <pre class="peek">');q.push(" </pre>");q.push("</div>");return q.join("")},templateHistorySelectInModal:function(){var q=[];q.push('<span id="history_modal_combo" style="width:90%; margin-left: 1em; margin-right: 1em; ">');q.push("Select history: ");q.push('<select id="dataset_import_single" name="dataset_import_single" style="width:50%; margin-bottom: 1em; "> ');q.push(" <% _.each(histories, function(history) { %>");q.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');q.push(" <% }); %>");q.push("</select>");q.push("</span>");return q.join("")},templateBulkImportInModal:function(){var q=[];q.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');q.push("Select history: ");q.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');q.push(" <% _.each(histories, function(history) { %>");q.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');q.push(" <% }); %>");q.push("</select>");q.push("</span>");return q.join("")},templateProgressBar:function(){var q=[];q.push('<div class="import_text">');q.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");q.push("</div>");q.push('<div class="progress">');q.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');q.push(' <span class="completion_span">0% Complete</span>');q.push(" </div>");q.push("</div>");q.push("");return q.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 tmpl_array.join("")},events:{"click #select-all-checkboxes":"selectAll","click #toolbtn_bulk_import":"modalBulkImport","click #toolbtn_dl":"bulkDownload","click #toolbtn_create_folder":"createFolderFromModal","click .library-dataset":"showDatasetDetails","click .dataset_row":"selectClickedRow"},render:function(q){$("#center").css("overflow","auto");view=this;var s=this;var r=new e({id:q.id});r.url=r.attributes.urlRoot+q.id+"/contents";r.fetch({success:function(t){for(var v=0;v<r.attributes.folder.models.length;v++){var u=r.attributes.folder.models[v];if(u.get("type")==="file"){u.set("readable_size",s.size_to_string(u.get("file_size")))}}var x=r.full_path;var y;if(x.length===1){y=0}else{y=x[x.length-2][0]}var w=_.template(s.templateFolder(),{path:r.full_path,items:r.attributes.folder.models,id:q.id,upper_folder_id:y});s.$el.html(w)},error:function(){m.error("An error occured :(")}})},size_to_string:function(q){var r="";if(q>=100000000000){q=q/100000000000;r="TB"}else{if(q>=100000000){q=q/100000000;r="GB"}else{if(q>=100000){q=q/100000;r="MB"}else{if(q>=100){q=q/100;r="KB"}else{q=q*10;r="b"}}}}return(Math.round(q)/10)+r},showDatasetDetails:function(t){t.preventDefault();var u=$(t.target).parent().parent().parent().attr("id");if(typeof u==="undefined"){u=$(t.target).parent().attr("id")}if(typeof u==="undefined"){u=$(t.target).parent().parent().attr("id")}var s=new i();var r=new o();s.id=u;var q=this;s.fetch({success:function(v){r.fetch({success:function(w){q.renderModalAfterFetch(v,w)},error:function(){m.error("An error occured during fetching histories:(");q.renderModalAfterFetch(v)}})},error:function(){m.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(v,s){var t=this.size_to_string(v.get("file_size"));var u=_.template(this.templateDatasetModal(),{item:v,size:t});var r=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:u,buttons:{Import:function(){r.importCurrentIntoHistory()},Download:function(){r.downloadCurrent()},Close:function(){r.modal.hide()}}});$(".peek").html(v.get("peek"));if(typeof history.models!==undefined){var q=_.template(this.templateHistorySelectInModal(),{histories:s.models});$(this.modal.elMain).find(".buttons").prepend(q);if(r.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(r.lastSelectedHistory)}}},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var q=[];q.push($("#id_row").attr("data-id"));var r="/api/libraries/datasets/download/uncompressed";var s={ldda_ids:q};folderContentView.processDownload(r,s);this.modal.enableButton("Import");this.modal.enableButton("Download")},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var s=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=s;var q=$("#id_row").attr("data-id");var t=new b();var r=this;t.url=t.urlRoot+s+"/contents";t.save({content:q,source:"library"},{success:function(){m.success("Dataset imported");r.modal.enableButton("Import");r.modal.enableButton("Download")},error:function(){m.error("An error occured! Dataset not imported. Please try again.");r.modal.enableButton("Import");r.modal.enableButton("Download")}})},selectAll:function(r){var q=r.target.checked;that=this;$(":checkbox").each(function(){this.checked=q;$row=$(this.parentElement.parentElement);(q)?that.makeDarkRow($row):that.makeWhiteRow($row)});this.checkTools()},selectClickedRow:function(r){var t="";var q;var s;if(r.target.localName==="input"){t=r.target;q=$(r.target.parentElement.parentElement);s="input"}else{if(r.target.localName==="td"){t=$("#"+r.target.parentElement.id).find(":checkbox")[0];q=$(r.target.parentElement);s="td"}}if(t.checked){if(s==="td"){t.checked="";this.makeWhiteRow(q)}else{if(s==="input"){this.makeDarkRow(q)}}}else{if(s==="td"){t.checked="selected";this.makeDarkRow(q)}else{if(s==="input"){this.makeWhiteRow(q)}}}this.checkTools()},makeDarkRow:function(q){q.removeClass("light");q.find("a").removeClass("light");q.addClass("dark");q.find("a").addClass("dark");q.find("span").removeClass("fa-file-o");q.find("span").addClass("fa-file")},makeWhiteRow:function(q){q.removeClass("dark");q.find("a").removeClass("dark");q.addClass("light");q.find("a").addClass("light");q.find("span").addClass("fa-file-o");q.find("span").removeClass("fa-file")},checkTools:function(){var q=$("#folder_table").find(":checked");if(q.length>0){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}else{$("#toolbtn_bulk_import").hide();$("#toolbtn_dl").hide()}},modalBulkImport:function(){var r=this;var q=new o();q.fetch({success:function(s){var t=_.template(r.templateBulkImportInModal(),{histories:s.models});r.modal=Galaxy.modal;r.modal.show({closing_events:true,title:"Import into History",body:t,buttons:{Import:function(){r.importAllIntoHistory()},Close:function(){r.modal.hide()}}})},error:function(){m.error("An error occured :(")}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var s=$("select[name=dataset_import_bulk] option:selected").val();var w=$("select[name=dataset_import_bulk] option:selected").text();var y=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){y.push(this.parentElement.parentElement.id)}});var x=_.template(this.templateProgressBar(),{history_name:w});$(this.modal.elMain).find(".modal-body").html(x);var t=100/y.length;this.initProgress(t);var q=[];for(var r=y.length-1;r>=0;r--){library_dataset_id=y[r];var u=new b();var v=this;u.url=u.urlRoot+s+"/contents";u.content=library_dataset_id;u.source="library";q.push(u)}this.chainCall(q)},chainCall:function(r){var q=this;var s=r.pop();if(typeof s==="undefined"){m.success("All datasets imported");this.modal.hide();return}var t=$.when(s.save({content:s.content,source:s.source})).done(function(u){q.updateProgress();responses.push(u);q.chainCall(r)})},initProgress:function(q){this.progress=0;this.progressStep=q},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(q,u){var s=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!=""){s.push(this.parentElement.parentElement.id)}});var r="/api/libraries/datasets/download/"+u;var t={ldda_ids:s};this.processDownload(r,t,"get")},processDownload:function(r,s,t){if(r&&s){s=typeof s=="string"?s:$.param(s);var q="";$.each(s.split("&"),function(){var u=this.split("=");q+='<input type="hidden" name="'+u[0]+'" value="'+u[1]+'" />'});$('<form action="'+r+'" method="'+(t||"post")+'">'+q+"</form>").appendTo("body").submit().remove();m.info("Your download will begin soon")}},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var q=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:this.templateNewFolderInModal(),buttons:{Create:function(){q.create_new_folder_event()},Close:function(){q.modal.hide();q.modal=null}}})},create_new_folder_event:function(){var q=this.serialize_new_folder();if(this.validate_new_folder(q)){var s=new c();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];s.url=s.urlRoot+"/"+current_folder_id;var r=this;s.save(q,{success:function(t){r.modal.hide();m.success("Folder created");r.render({id:current_folder_id})},error:function(){m.error("An error occured :(")}})}else{m.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(q){return q.name!==""}});var a=Backbone.View.extend({el:"#center",events:{"click #create_new_library_btn":"show_library_modal"},modal:null,collection:null,initialize:function(){var q=this;this.collection=new n();this.collection.fetch({success:function(r){q.render()},error:function(s,r){if(r.statusCode().status===403){m.info("Please log in first. Redirecting to login page in 3s.");setTimeout(that.redirectToLogin,3000)}else{m.error("An error occured. Please try again.")}}});$("#center").css("overflow","auto")},render:function(s){var q=this.templateLibraryList();var r=null;if(this.collection!==null&&typeof s==="undefined"){r=this.collection.models}else{if(s!==null){r=s}else{r=[]}}this.$el.html(q({libraries:r,order:this.collection.sort_order}))},sortLibraries:function(r,q){if(r==="name"){if(q==="asc"){this.collection.sort_order="asc";this.collection.comparator=function(t,s){if(t.get("name").toLowerCase()>s.get("name").toLowerCase()){return 1}if(s.get("name").toLowerCase()>t.get("name").toLowerCase()){return -1}return 0}}else{if(q==="desc"){this.collection.sort_order="desc";this.collection.comparator=function(t,s){if(t.get("name").toLowerCase()>s.get("name").toLowerCase()){return -1}if(s.get("name").toLowerCase()>t.get("name").toLowerCase()){return 1}return 0}}}this.collection.sort()}},templateLibraryList:function(){tmpl_array=[];tmpl_array.push('<div class="library_container" style="width: 90%; margin: auto; margin-top: 2em; overflow: auto !important; ">');tmpl_array.push("");tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push('<a href="" id="create_new_library_btn" class="btn btn-primary file ">New Library</a>');tmpl_array.push('<table class="library_table table table-condensed">');tmpl_array.push(" <thead>");tmpl_array.push(' <th><a title="Click to reverse order" href="#sort/name/<% if(order==="desc"||order===null){print("asc")}else{print("desc")} %>">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');tmpl_array.push(" <th>description</th>");tmpl_array.push(" <th>synopsis</th> ");tmpl_array.push(" </thead>");tmpl_array.push(" <tbody>");tmpl_array.push(" <% _.each(libraries, function(library) { %>");tmpl_array.push(" <tr>");tmpl_array.push(' <td><a href="#folders/<%- library.get("root_folder_id") %>"><%- library.get("name") %></a></td>');tmpl_array.push(' <td><%= _.escape(library.get("description")) %></td>');tmpl_array.push(' <td><%= _.escape(library.get("synopsis")) %></td>');tmpl_array.push(" </tr>");tmpl_array.push(" <% }); %>");tmpl_array.push(" </tbody>");tmpl_array.push("</table>");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("")},redirectToHome:function(){window.location="../"},redirectToLogin:function(){window.location="/user/login"},show_library_modal:function(r){r.preventDefault();r.stopPropagation();var q=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Library",body:this.templateNewLibraryInModal(),buttons:{Create:function(){q.create_new_library_event()},Close:function(){q.modal.hide()}}})},create_new_library_event:function(){var s=this.serialize_new_library();if(this.validate_new_library(s)){var r=new f();var q=this;r.save(s,{success:function(t){q.collection.add(t);q.modal.hide();q.clear_library_modal();q.render();m.success("Library created")},error:function(){m.error("An error occured :(")}})}else{m.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(q){return q.name!==""}});var p=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var g=Backbone.View.extend({initialize:function(){galaxyLibraryview=new a();library_router=new p();folderContentView=new l();library_router.on("route:libraries",function(){galaxyLibraryview.render()});library_router.on("route:sort_libraries",function(r,q){galaxyLibraryview.sortLibraries(r,q);galaxyLibraryview.render()});library_router.on("route:folder_content",function(q){folderContentView.render({id:q})});library_router.on("route:download",function(q,r){if($("#center").find(":checked").length===0){library_router.navigate("folders/"+q,{trigger:true,replace:true})}else{folderContentView.download(q,r);library_router.navigate("folders/"+q,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:g}});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/galaxy.modal.js
--- a/static/scripts/packed/galaxy.modal.js
+++ /dev/null
@@ -1,1 +0,0 @@
-define([],function(){var a=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"galaxy-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(b){if(b){this._create(b)}},show:function(b){this.initialize(b);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",false)},disableButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).prop("disabled",true)},showButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).show()},hideButton:function(b){var c=this.buttonList[b];this.$buttons.find("#"+c).hide()},getButton:function(b){var c=this.buttonList[b];return this.$buttons.find("#"+c)},scrollTop:function(){return this.$body.scrollTop()},_create:function(d){var c=this;this.options=_.defaults(d,this.optionsDefault);if(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>')}if(this.$el){this.$el.remove();$(document).off("keyup")}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);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var b=0;$.each(this.options.buttons,function(e,g){var f="button-"+b++;c.$buttons.append($('<button id="'+f+'"></button>').text(e).click(g)).append(" ");c.buttonList[e]=f})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){c.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){c.hide()})}},_template:function(b){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">'+b+'</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{GalaxyModal:a}});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/mvc/ui/ui-modal.js
--- /dev/null
+++ b/static/scripts/packed/mvc/ui/ui-modal.js
@@ -0,0 +1,1 @@
+define(["utils/utils"],function(a){var b=Backbone.View.extend({elMain:"#everything",optionsDefault:{title:"ui-modal",body:"",backdrop:true,height:null,width:null,closing_events:false},buttonList:{},initialize:function(c){if(c){this._create(c)}},show:function(c){this.initialize(c);if(this.options.height){this.$body.css("height",this.options.height);this.$body.css("overflow","hidden")}else{this.$body.css("max-height",$(window).height()/2)}if(this.options.width){this.$dialog.css("width",this.options.width)}if(this.visible){this.$el.show()}else{this.$el.fadeIn("fast")}this.visible=true},hide:function(){this.visible=false;this.$el.fadeOut("fast")},enableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",false)},disableButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).prop("disabled",true)},showButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).show()},hideButton:function(c){var d=this.buttonList[c];this.$buttons.find("#"+d).hide()},getButton:function(c){var d=this.buttonList[c];return this.$buttons.find("#"+d)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var d=this;this.options=_.defaults(e,this.optionsDefault);if(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>')}if(this.$el){this.$el.remove();$(document).off("keyup")}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);if(!this.options.backdrop){this.$backdrop.removeClass("in")}if(this.options.buttons){this.buttonList={};var c=0;$.each(this.options.buttons,function(f,h){var g="button-"+c++;d.$buttons.append($('<button id="'+g+'"></button>').text(f).click(h)).append(" ");d.buttonList[f]=g})}else{this.$footer.hide()}$(this.elMain).append($(this.el));if(this.options.closing_events){if(!this.options.buttons.Pause){$(document).on("keyup",function(f){if(f.keyCode==27){d.hide()}})}this.$el.find(".modal-backdrop").on("click",function(){d.hide()})}},_template:function(c){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">'+c+'</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:b}});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d static/scripts/packed/mvc/upload/upload-view.js
--- a/static/scripts/packed/mvc/upload/upload-view.js
+++ b/static/scripts/packed/mvc/upload/upload-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.modal","utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui/ui-popover","mvc/ui","utils/uploadbox"],function(a,f,e,c,b,g,d){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,list_extensions:[],list_genomes:[],auto:{id:"auto",text:"Auto-detect",description:"This system will try to detect the file type automatically. If your file is not detected properly as one of the known formats, it most likely means that it has some format problems (e.g., different number of columns on different rows). You can still coerce the system to set your data to the format you think it should be. You can also upload compressed files, which will automatically be decompressed."},collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(i){this.options=_.defaults(i,this.options)}if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.get(galaxy_config.root+"api/datatypes?extension_only=False",function(j){for(key in j){h.list_extensions.push({id:j[key].extension,text:j[key].extension,description:j[key].description,description_url:j[key].description_url})}h.list_extensions.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0});if(!h.options.datatypes_disable_auto){h.list_extensions.unshift(h.auto)}});f.get(galaxy_config.root+"api/genomes",function(j){for(key in j){h.list_genomes.push({id:j[key][1],text:j[key][0]})}h.list_genomes.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0})});this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.GalaxyModal({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Paste/Fetch data":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}this.modal.show();this._updateUser();this._updateScreen()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}tool_input={};if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateUser:function(){this.current_user=Galaxy.currUser.get("id");this.current_history=null;if(this.current_user){this.current_history=Galaxy.currHistoryPanel.model.get("id")}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Paste/Fetch data")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Paste/Fetch data")}if(this.current_user&&this.options.ftp_upload_dir&&this.options.ftp_upload_site){this.modal.showButton("Choose FTP file")}else{this.modal.hideButton("Choose FTP file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
+define(["utils/utils","mvc/upload/upload-button","mvc/upload/upload-model","mvc/upload/upload-row","mvc/upload/upload-ftp","mvc/ui/ui-popover","mvc/ui/ui-modal","mvc/ui","utils/uploadbox"],function(f,e,c,b,g,d,a){return Backbone.View.extend({options:{nginx_upload_path:""},modal:null,ui_button:null,uploadbox:null,current_history:null,upload_size:0,list_extensions:[],list_genomes:[],auto:{id:"auto",text:"Auto-detect",description:"This system will try to detect the file type automatically. If your file is not detected properly as one of the known formats, it most likely means that it has some format problems (e.g., different number of columns on different rows). You can still coerce the system to set your data to the format you think it should be. You can also upload compressed files, which will automatically be decompressed."},collection:new c.Collection(),ftp:null,counter:{announce:0,success:0,error:0,running:0,reset:function(){this.announce=this.success=this.error=this.running=0}},initialize:function(i){var h=this;if(i){this.options=_.defaults(i,this.options)}if(!Galaxy.currHistoryPanel||!Galaxy.currHistoryPanel.model){window.setTimeout(function(){h.initialize()},500);return}this.ui_button=new e.Model({icon:"fa-upload",tooltip:"Download from URL or upload files from disk",label:"Load Data",onclick:function(j){if(j){h._eventShow(j)}},onunload:function(){if(h.counter.running>0){return"Several uploads are still processing."}}});$("#left .unified-panel-header-inner").append((new e.View(this.ui_button)).$el);var h=this;f.get(galaxy_config.root+"api/datatypes?extension_only=False",function(j){for(key in j){h.list_extensions.push({id:j[key].extension,text:j[key].extension,description:j[key].description,description_url:j[key].description_url})}h.list_extensions.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0});if(!h.options.datatypes_disable_auto){h.list_extensions.unshift(h.auto)}});f.get(galaxy_config.root+"api/genomes",function(j){for(key in j){h.list_genomes.push({id:j[key][1],text:j[key][0]})}h.list_genomes.sort(function(l,k){return l.id>k.id?1:l.id<k.id?-1:0})});this.collection.on("remove",function(j){h._eventRemove(j)});this.collection.on("change:genome",function(k){var j=k.get("genome");h.collection.each(function(l){if(l.get("status")=="init"&&l.get("genome")=="?"){l.set("genome",j)}})})},_eventShow:function(j){j.preventDefault();if(!this.modal){var h=this;this.modal=new a.View({title:"Download data directly from web or upload files from your disk",body:this._template("upload-box","upload-info"),buttons:{"Choose local file":function(){h.uploadbox.select()},"Choose FTP file":function(){h._eventFtp()},"Paste/Fetch data":function(){h._eventCreate()},Start:function(){h._eventStart()},Pause:function(){h._eventStop()},Reset:function(){h._eventReset()},Close:function(){h.modal.hide()},},height:"400",width:"900",closing_events:true});this.setElement("#upload-box");var h=this;this.uploadbox=this.$el.uploadbox({announce:function(k,l,m){h._eventAnnounce(k,l,m)},initialize:function(k,l,m){return h._eventInitialize(k,l,m)},progress:function(k,l,m){h._eventProgress(k,l,m)},success:function(k,l,m){h._eventSuccess(k,l,m)},error:function(k,l,m){h._eventError(k,l,m)},complete:function(){h._eventComplete()}});var i=this.modal.getButton("Choose FTP file");this.ftp=new d.View({title:"FTP files",container:i})}this.modal.show();this._updateUser();this._updateScreen()},_eventRemove:function(i){var h=i.get("status");if(h=="success"){this.counter.success--}else{if(h=="error"){this.counter.error--}else{this.counter.announce--}}this._updateScreen();this.uploadbox.remove(i.id)},_eventAnnounce:function(h,i,k){this.counter.announce++;this._updateScreen();var j=new b(this,{id:h,file_name:i.name,file_size:i.size,file_mode:i.mode,file_path:i.path});this.collection.add(j.model);$(this.el).find("tbody:first").append(j.$el);j.render()},_eventInitialize:function(m,j,s){var k=this.collection.get(m);k.set("status","running");var o=k.get("file_name");var n=k.get("file_path");var h=k.get("file_mode");var p=k.get("extension");var r=k.get("genome");var q=k.get("url_paste");var l=k.get("space_to_tabs");var i=k.get("to_posix_lines");if(!q&&!(j.size>0)){return null}this.uploadbox.configure({url:this.options.nginx_upload_path});if(h=="local"){this.uploadbox.configure({paramname:"files_0|file_data"})}else{this.uploadbox.configure({paramname:null})}tool_input={};if(h=="new"){tool_input["files_0|url_paste"]=q}if(h=="ftp"){tool_input["files_0|ftp_files"]=n}tool_input.dbkey=r;tool_input.file_type=p;tool_input["files_0|type"]="upload_dataset";tool_input.space_to_tabs=l;tool_input.to_posix_lines=i;data={};data.history_id=this.current_history;data.tool_id="upload1";data.inputs=JSON.stringify(tool_input);return data},_eventProgress:function(i,j,h){var k=this.collection.get(i);k.set("percentage",h);this.ui_button.set("percentage",this._upload_percentage(h,j.size))},_eventSuccess:function(i,j,l){var k=this.collection.get(i);k.set("percentage",100);k.set("status","success");var h=k.get("file_size");this.ui_button.set("percentage",this._upload_percentage(100,h));this.upload_completed+=h*100;this.counter.announce--;this.counter.success++;this._updateScreen();Galaxy.currHistoryPanel.refreshHdas()},_eventError:function(h,i,k){var j=this.collection.get(h);j.set("percentage",100);j.set("status","error");j.set("info",k);this.ui_button.set("percentage",this._upload_percentage(100,i.size));this.ui_button.set("status","danger");this.upload_completed+=i.size*100;this.counter.announce--;this.counter.error++;this._updateScreen()},_eventComplete:function(){this.collection.each(function(h){if(h.get("status")=="queued"){h.set("status","init")}});this.counter.running=0;this._updateScreen()},_eventFtp:function(){if(!this.ftp.visible){this.ftp.empty();this.ftp.append((new g(this)).$el);this.ftp.show()}else{this.ftp.hide()}},_eventCreate:function(){this.uploadbox.add([{name:"New File",size:0,mode:"new"}])},_eventStart:function(){if(this.counter.announce==0||this.counter.running>0){return}var h=this;this.upload_size=0;this.upload_completed=0;this.collection.each(function(i){if(i.get("status")=="init"){i.set("status","queued");h.upload_size+=i.get("file_size")}});this.ui_button.set("percentage",0);this.ui_button.set("status","success");this.counter.running=this.counter.announce;this._updateScreen();this.uploadbox.start()},_eventStop:function(){if(this.counter.running==0){return}this.ui_button.set("status","info");this.uploadbox.stop();$("#upload-info").html("Queue will pause after completing the current file...")},_eventReset:function(){if(this.counter.running==0){this.collection.reset();this.counter.reset();this._updateScreen();this.uploadbox.reset();this.ui_button.set("percentage",0)}},_updateUser:function(){this.current_user=Galaxy.currUser.get("id");this.current_history=null;if(this.current_user){this.current_history=Galaxy.currHistoryPanel.model.get("id")}},_updateScreen:function(){if(this.counter.announce==0){if(this.uploadbox.compatible()){message="You can Drag & Drop files into this box."}else{message="Unfortunately, your browser does not support multiple file uploads or drag&drop.<br>Some supported browsers are: Firefox 4+, Chrome 7+, IE 10+, Opera 12+ or Safari 6+."}}else{if(this.counter.running==0){message="You added "+this.counter.announce+" file(s) to the queue. Add more files or click 'Start' to proceed."}else{message="Please wait..."+this.counter.announce+" out of "+this.counter.running+" remaining."}}$("#upload-info").html(message);if(this.counter.running==0&&this.counter.announce+this.counter.success+this.counter.error>0){this.modal.enableButton("Reset")}else{this.modal.disableButton("Reset")}if(this.counter.running==0&&this.counter.announce>0){this.modal.enableButton("Start")}else{this.modal.disableButton("Start")}if(this.counter.running>0){this.modal.enableButton("Pause")}else{this.modal.disableButton("Pause")}if(this.counter.running==0){this.modal.enableButton("Choose local file");this.modal.enableButton("Choose FTP file");this.modal.enableButton("Paste/Fetch data")}else{this.modal.disableButton("Choose local file");this.modal.disableButton("Choose FTP file");this.modal.disableButton("Paste/Fetch data")}if(this.current_user&&this.options.ftp_upload_dir&&this.options.ftp_upload_site){this.modal.showButton("Choose FTP file")}else{this.modal.hideButton("Choose FTP file")}if(this.counter.announce+this.counter.success+this.counter.error>0){$(this.el).find("#upload-table").show()}else{$(this.el).find("#upload-table").hide()}},_upload_percentage:function(h,i){return(this.upload_completed+(h*i))/this.upload_size},_template:function(i,h){return'<div id="'+i+'" class="upload-box"><table id="upload-table" class="table table-striped" style="display: none;"><thead><tr><th>Name</th><th>Size</th><th>Type</th><th>Genome</th><th>Settings</th><th>Status</th><th></th></tr></thead><tbody></tbody></table></div><h6 id="'+h+'" class="upload-info"></h6>'}})});
\ No newline at end of file
diff -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd -r 310f5893da982d054b07de669f022dcfba4b1d3d templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -83,7 +83,7 @@
## load galaxy js-modules
$(function() {
- require(['galaxy.masthead', 'galaxy.menu', 'galaxy.modal', 'galaxy.frame', 'mvc/upload/upload-view'],
+ require(['galaxy.masthead', 'galaxy.menu', 'mvc/ui/ui-modal', 'galaxy.frame', 'mvc/upload/upload-view'],
function(mod_masthead, mod_menu, mod_modal, mod_frame, GalaxyUpload)
{
## check if masthead is available
@@ -95,7 +95,7 @@
## load global galaxy objects
Galaxy.masthead = new mod_masthead.GalaxyMasthead(masthead_config);
- Galaxy.modal = new mod_modal.GalaxyModal();
+ Galaxy.modal = new mod_modal.View();
Galaxy.frame = new mod_frame.GalaxyFrame();
## construct default menu options
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: Ui/Charts: Enable job submission, revise data access, generalize framework, update elements
by commits-noreply@bitbucket.org 06 Mar '14
by commits-noreply@bitbucket.org 06 Mar '14
06 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4ec6ff7c4165/
Changeset: 4ec6ff7c4165
User: guerler
Date: 2014-03-06 06:48:58
Summary: Ui/Charts: Enable job submission, revise data access, generalize framework, update elements
Affected #: 25 files
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/app.js
--- a/config/plugins/visualizations/charts/static/app.js
+++ b/config/plugins/visualizations/charts/static/app.js
@@ -1,10 +1,10 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils',
- 'plugin/views/charts', 'plugin/views/viewport', 'plugin/views/chart',
- 'plugin/models/config', 'plugin/models/datasets', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
- function( Portlet, Ui, Utils,
- ChartsView, ViewportView, ChartView,
- Config, Datasets, Chart, Charts, Types
+define(['mvc/ui/ui-portlet', 'plugin/library/ui', 'utils/utils', 'plugin/library/jobs', 'plugin/library/datasets',
+ 'plugin/views/charts', 'plugin/views/chart',
+ 'plugin/models/config', 'plugin/models/chart', 'plugin/models/charts', 'plugin/models/types'],
+ function( Portlet, Ui, Utils, Jobs, Datasets,
+ ChartsView, ChartView,
+ Config, Chart, Charts, Types
) {
// widget
@@ -17,11 +17,14 @@
this.options = options;
// link galaxy
- this.modal = parent.Galaxy.modal;
+ this.modal = Galaxy.modal;
// create configuration model
this.config = new Config();
+ // job/data /processor
+ this.jobs = new Jobs(this);
+
// create chart models
this.types = new Types();
this.chart = new Chart();
@@ -33,11 +36,7 @@
// create views
this.charts_view = new ChartsView(this);
this.chart_view = new ChartView(this);
- this.viewport_view = new ViewportView(this);
- // append view port to charts viewer
- this.charts_view.append(this.viewport_view.$el);
-
// create portlet
if (!this.options.config.widget) {
this.portlet = new Portlet.View({icon : 'fa-bar-chart-o'});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/bardiagram.js
--- a/config/plugins/visualizations/charts/static/charts/bardiagram.js
+++ b/config/plugins/visualizations/charts/static/charts/bardiagram.js
@@ -11,21 +11,25 @@
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarChart();
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarChart();
- self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/histogram.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/charts/histogram.js
@@ -0,0 +1,49 @@
+// dependencies
+define([], function() {
+
+// widget
+return Backbone.View.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ this.app = app;
+ this.options = options;
+ },
+
+ // plot
+ plot: function(chart, request_dictionary) {
+
+ // update request dataset id
+ request_dictionary.id = chart.get('dataset_id_job');
+
+ // configure request
+ var index = 0;
+ for (var i in request_dictionary.groups) {
+ var group = request_dictionary.groups[i];
+ group.columns = {
+ x: index++,
+ y: index++
+ }
+ }
+
+ // send request
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarChart();
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.2f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.1f'))
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ chart.set('state', 'ok');
+ });
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/horizontal.js
--- a/config/plugins/visualizations/charts/static/charts/horizontal.js
+++ b/config/plugins/visualizations/charts/static/charts/horizontal.js
@@ -8,24 +8,28 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.d3_chart = nv.models.multiBarHorizontalChart();
-
- self.d3_chart.xAxis.tickFormat(function() { return ''; });
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ this.app.datasets.request(request_dictionary, function(data) {
+ // add graph to screen
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.multiBarHorizontalChart();
+
+ self.d3_chart.xAxis.tickFormat(function() { return ''; });
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/line.js
--- a/config/plugins/visualizations/charts/static/charts/line.js
+++ b/config/plugins/visualizations/charts/static/charts/line.js
@@ -8,30 +8,31 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.chart_3d = nv.models.lineChart();
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.lineChart();
- self.chart_3d.xAxis
- .tickFormat(d3.format(',f'));
+ self.chart_3d.xAxis
+ .tickFormat(d3.format(',f'));
- self.chart_3d.yAxis
- .tickFormat(d3.format(',.2f'));
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.chart_3d);
+ self.chart_3d.yAxis
+ .tickFormat(d3.format(',.2f'));
+
+ self.options.svg.datum(data)
+ .call(self.chart_3d);
- nv.utils.windowResize(self.chart_3d.update);
-
- return self.chart_3d;
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/linewithfocus.js
--- a/config/plugins/visualizations/charts/static/charts/linewithfocus.js
+++ b/config/plugins/visualizations/charts/static/charts/linewithfocus.js
@@ -8,28 +8,31 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.chart_3d = nv.models.lineWithFocusChart();
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.lineWithFocusChart();
- self.chart_3d.xAxis
- .tickFormat(d3.format(',f'));
+ self.chart_3d.xAxis
+ .tickFormat(d3.format(',f'));
- self.chart_3d.yAxis
- .tickFormat(d3.format(',.2f'));
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.chart_3d);
+ self.chart_3d.yAxis
+ .tickFormat(d3.format(',.2f'));
+
+ self.options.svg.datum(data)
+ .call(self.chart_3d);
- nv.utils.windowResize(self.chart_3d.update);
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/piechart.js
--- a/config/plugins/visualizations/charts/static/charts/piechart.js
+++ b/config/plugins/visualizations/charts/static/charts/piechart.js
@@ -8,43 +8,46 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // loop through data groups
- for (var key in data) {
- // get group
- var group = data[key];
+ // request data
+ var self = this;
+ this.app.datasets.request(request_dictionary, function(data) {
- // format chart data
- var pie_data = [];
- for (var key in group.values) {
- var value = group.values[key];
- pie_data.push ({
- key : value.x,
- y : value.y
+ // loop through data groups
+ for (var key in request_dictionary.groups) {
+ // get group
+ var group = request_dictionary.groups[key];
+
+ // format chart data
+ var pie_data = [];
+ for (var key in group.values) {
+ var value = group.values[key];
+ pie_data.push ({
+ key : value.x,
+ y : value.y
+ });
+ }
+
+ // add graph to screen
+ nv.addGraph(function() {
+ self.chart_3d = nv.models.pieChart()
+ .donut(true)
+ .showLegend(false);
+
+ self.options.svg.datum(pie_data)
+ .call(self.chart_3d);
+
+ nv.utils.windowResize(self.chart_3d.update);
+
+ // set chart state
+ chart.set('state', 'ok');
});
}
-
- // add graph to screen
- var self = this;
- nv.addGraph(function() {
- self.chart_3d = nv.models.pieChart()
- .donut(true)
- .showLegend(false);
-
- d3.select(self.options.svg_id)
- .datum(pie_data)
- .call(self.chart_3d);
-
- nv.utils.windowResize(self.chart_3d.update);
-
- return self.chart_3d;
- });
- }
+ });
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/scatterplot.js
--- a/config/plugins/visualizations/charts/static/charts/scatterplot.js
+++ b/config/plugins/visualizations/charts/static/charts/scatterplot.js
@@ -8,28 +8,31 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- self.d3_chart = nv.models.scatterChart()
- .showDistX(true)
- .showDistY(true)
- .color(d3.scale.category10().range());
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ self.d3_chart = nv.models.scatterChart()
+ .showDistX(true)
+ .showDistY(true)
+ .color(d3.scale.category10().range());
+
+ self.d3_chart.xAxis.tickFormat(d3.format('.02f'))
+ self.d3_chart.yAxis.tickFormat(d3.format('.02f'))
- self.d3_chart.xAxis.tickFormat(d3.format('.02f'))
- self.d3_chart.yAxis.tickFormat(d3.format('.02f'))
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/charts/stackedarea.js
--- a/config/plugins/visualizations/charts/static/charts/stackedarea.js
+++ b/config/plugins/visualizations/charts/static/charts/stackedarea.js
@@ -8,50 +8,35 @@
initialize: function(app, options) {
this.app = app;
this.options = options;
- this.chart = options.chart;
},
// render
- refresh : function(data)
+ plot : function(chart, request_dictionary)
{
- // add graph to screen
+ // request data
var self = this;
- nv.addGraph(function() {
- // check data
- var valid = true;
- var length = 0;
- for (var key in data) {
- // evalute length
- if (length == 0) {
- length = data[key].values.length;
- } else {
- if (length != data[key].values.length) {
- valid = false;
- break;
- }
- }
- }
- if (!valid) {
- return;
- }
-
- // make plot
- self.d3_chart = nv.models.stackedAreaChart()
- .x(function(d) {
- return d.x
- })
- .y(function(d) {
- return d.y
- })
- .clipEdge(true);
-
- self.d3_chart.xAxis.tickFormat(function() { return ''; });
-
- d3.select(self.options.svg_id)
- .datum(data)
- .call(self.d3_chart);
-
- nv.utils.windowResize(self.d3_chart.update);
+ this.app.datasets.request(request_dictionary, function(data) {
+ nv.addGraph(function() {
+ // make plot
+ self.d3_chart = nv.models.stackedAreaChart()
+ .x(function(d) {
+ return d.x
+ })
+ .y(function(d) {
+ return d.y
+ })
+ .clipEdge(true);
+
+ self.d3_chart.xAxis.tickFormat(function() { return ''; });
+
+ self.options.svg.datum(data)
+ .call(self.d3_chart);
+
+ nv.utils.windowResize(self.d3_chart.update);
+
+ // set chart state
+ chart.set('state', 'ok');
+ });
});
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/datasets.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/datasets.js
@@ -0,0 +1,137 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// widget
+return Backbone.Collection.extend(
+{
+ // initialize
+ initialize: function(app, options)
+ {
+ // link app
+ this.app = app;
+
+ // configure options
+ this.options = Utils.merge(options, this.optionsDefault);
+ },
+
+ // wait
+ request: function(options, success, error) {
+ // link this
+ var self = this;
+
+ // wait for dataset
+ Utils.request('GET', config.root + 'api/datasets/' + options.id, {}, function(dataset) {
+ switch (dataset.state) {
+ case 'error':
+ if (error) {
+ error(dataset);
+ }
+ break;
+ default:
+ if (options.groups) {
+ self._fetch(options, success);
+ } else {
+ success(dataset);
+ }
+ }
+ });
+ },
+
+ // fetch data columns into dataset object
+ _fetch: function(options, callback) {
+ // set offset
+ var offset = options.start ? options.start : 0;
+
+ // set limit
+ var limit = Math.abs(options.end - options.start);
+ var query_limit = this.app.config.get('query_limit');
+ if (!limit || limit > query_limit) {
+ limit = query_limit;
+ }
+
+ // get column indices
+ var index_string = '';
+ var index_map = {};
+ var index_count = 0;
+ for (var i in options.groups) {
+ var group = options.groups[i];
+ for (var key in group.columns) {
+ var column = group.columns[key];
+
+ // add to index string
+ index_string += column + ',';
+
+ // add to dictionary
+ index_map[column] = index_count;
+
+ // increase counter
+ index_count++;
+ }
+ }
+ if (index_count == 0) {
+ callback({});
+ return;
+ }
+ index_string = index_string.substring(0, index_string.length - 1);
+
+ // initialize result dictionary
+ var result = options.groups.slice(0);
+ for (var i in result) {
+ result[i].values = [];
+ }
+
+ // make request
+ var self = this;
+ Utils.request('GET', config.root + 'api/datasets/' + options.id, {
+ data_type : 'raw_data',
+ provider : 'dataset-column',
+ limit : limit,
+ offset : offset,
+ indeces : index_string
+ }, function(response) {
+
+ // loop through rows
+ for (var i in response.data) {
+ // get row
+ var row = response.data[i];
+
+ // collect all data into the defined groups
+ for (var j in options.groups) {
+ // get group
+ var group = options.groups[j];
+
+ // initialize value
+ var value = {
+ x : parseInt(i) + offset
+ };
+
+ // fill value
+ for (var key in group.columns) {
+ // get column
+ var column = group.columns[key];
+
+ // identify column
+ var index = index_map[column];
+
+ // read value from row
+ var v = row[index];
+ if(isNaN(v)) {
+ v = 0;
+ }
+
+ // add value to dictionary
+ value[key] = v;
+ }
+
+ // add to result
+ result[j].values.push(value);
+ }
+ }
+
+ // callback
+ callback(result);
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/jobs.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/jobs.js
@@ -0,0 +1,98 @@
+// dependencies
+define(['utils/utils'], function(Utils) {
+
+// widget
+return Backbone.Model.extend(
+{
+ // initialize
+ initialize: function(app, options) {
+ // link app
+ this.app = app;
+
+ // link options
+ this.options = Utils.merge(options, this.optionsDefault);
+ },
+
+ // create job
+ submit: function(chart, request_string, callback) {
+ // link this
+ var self = this;
+
+ // backup chart details
+ var chart_id = chart.id;
+ var chart_type = chart.get('type');
+
+ // get chart settings
+ var chart_settings = this.app.types.get(chart_type);
+
+ // configure tool
+ data = {
+ 'tool_id' : 'rkit',
+ 'history_id' : chart.history_id,
+ 'inputs' : {
+ 'input' : chart.dataset_hid,
+ 'module' : chart_type,
+ 'options' : request_string
+ }
+ }
+
+ // set chart state
+ chart.state('submit', 'Sending job request...');
+
+ // post job
+ Utils.request('POST', config.root + 'api/tools', data,
+ // success handler
+ function(response) {
+ if (!response.outputs || response.outputs.length == 0) {
+ chart.state('failed', 'Job submission failed. No response.');
+ self.app.log('handle::load()', 'Job submission failed.');
+ } else {
+ // update galaxy history
+ Galaxy.currHistoryPanel.refreshHdas();
+
+ // get dataset
+ var job = response.outputs[0];
+
+ // check dataset
+ chart.state('queued', 'Job has been queued...');
+
+ // backup resulting dataset id
+ chart.set('dataset_id_job', job.id);
+
+ // wait for job completion
+ self._loop(job.id, function(job) {
+ switch (job.state) {
+ case 'ok':
+ chart.state('ok', 'Job completed successfully...');
+ callback(job);
+ return true;
+ case 'error':
+ chart.state('failed', 'Job has failed. Please check the history for details.');
+ return true;
+ case 'running':
+ chart.state('running', 'Job is running...');
+ return false;
+ }
+ });
+ }
+ },
+ // error handler
+ function(response) {
+ chart.state('failed', 'Job submission failed.');
+ self.app.log('handle::load()', 'Job submission failed.');
+ }
+ );
+ },
+
+ // request job details
+ _loop: function(id, callback) {
+ var self = this;
+ Utils.request('GET', config.root + 'api/jobs/' + id, {}, function(job) {
+ if (!callback(job)) {
+ setTimeout(function() { self._loop(id, callback); }, self.app.config.get('query_timeout'));
+ }
+ });
+ }
+});
+
+});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/table.js
--- a/config/plugins/visualizations/charts/static/library/table.js
+++ b/config/plugins/visualizations/charts/static/library/table.js
@@ -82,9 +82,12 @@
// remove
remove: function(id) {
- this.$tbody.find('#' + id).remove();
- this.row_count--;
- this._refresh();
+ var item = this.$tbody.find('#' + id);
+ if (item.length > 0) {
+ item.remove();
+ this.row_count--;
+ this._refresh();
+ }
},
// remove
@@ -129,6 +132,9 @@
// commit
_commit: function(id, prepend) {
+ // remove previous item with same id
+ this.remove(id);
+
// add
this.row.attr('id', id);
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/ui.select.js
--- a/config/plugins/visualizations/charts/static/library/ui.select.js
+++ b/config/plugins/visualizations/charts/static/library/ui.select.js
@@ -8,9 +8,14 @@
optionsDefault: {
id : '',
cls : '',
- empty : 'No data available'
+ empty : 'No data available',
+ visible : true,
+ wait : false
},
+ // value
+ selected : null,
+
// initialize
initialize : function(options) {
// configure options
@@ -19,70 +24,102 @@
// create new element
this.setElement(this._template(this.options));
+ // link elements
+ this.$select = this.$el.find('#select');
+ this.$wait = this.$el.find('#wait');
+
// initial value
- if (this.options.value) {
- this.$el.val(this.options.value);
- }
+ this.selected = this.options.value;
// add change event
var self = this;
if (this.options.onchange) {
- this.$el.on('change', function() { self.options.onchange(self.value()); });
+ this.$select.on('change', function() {
+ self.value(self.$select.val());
+ });
}
// refresh
this._refresh();
+
+ // show/hide
+ if (!this.options.visible) {
+ this.hide();
+ }
+
+ // wait
+ if (this.options.wait) {
+ this.wait();
+ }
},
// value
value : function (new_value) {
+
// get current id/value
- var before = this.$el.val();
+ var before = this.selected;
// check if new_value is defined
if (new_value !== undefined) {
- this.$el.val(new_value);
+ this.selected = new_value;
+ this.$select.val(new_value);
}
// get current id/value
- var after = this.$el.val();
- if(after === undefined) {
- return null;
- } else {
+ var after = this.selected;
+ if(after) {
// fire onchange
- if ((after != before && this.options.onchange) || this.$el.find('option').length == 1) {
+ if ((after != before && this.options.onchange)) {
this.options.onchange(after);
}
-
- // return current value
- return after;
}
+
+ // return
+ return after;
},
// label
text : function () {
- return this.$el.find('option:selected').text();
+ return this.$select.find('option:selected').text();
+ },
+
+ // show
+ show: function() {
+ this.$wait.hide();
+ this.$select.show();
+ this.$el.show();
+ },
+
+ // hide
+ hide: function() {
+ this.$el.hide();
+ },
+
+ // wait
+ wait: function() {
+ this.$select.hide();
+ this.$wait.css('display','inline-block');
},
// disabled
disabled: function() {
- return this.$el.is(':disabled');
+ return this.$select.is(':disabled');
},
// enable
enable: function() {
- this.$el.prop('disabled', false);
+ this.$select.prop('disabled', false);
},
// disable
disable: function() {
- this.$el.prop('disabled', true);
+ this.$select.prop('disabled', true);
},
// add
add: function(options) {
// add options
- $(this.el).append(this._templateOption(options));
+ this.$select.append(this._templateOption(options));
// refresh
this._refresh();
@@ -91,8 +128,8 @@
// remove
del: function(value) {
// remove option
- $(this.el).find('option[value=' + value + ']').remove();
- $(this.el).trigger('change');
+ this.$select.find('option[value=' + value + ']').remove();
+ this.$select.trigger('change');
// refresh
this._refresh();
@@ -100,20 +137,18 @@
// render
update: function(options) {
- // selected
- var selected = this.$el.val();
-
// remove all options
- $(this.el).find('option').remove();
+ this.$select.find('option').remove();
// add new options
- for (var key in options.data) {
- $(this.el).append(this._templateOption(options.data[key]));
+ for (var key in options) {
+ this.$select.append(this._templateOption(options[key]));
}
- // add selected value
- if (this._exists(selected))
- $(this.el).val(selected);
+ // select first option if nothing else is selected
+ if (!this.selected && options.length > 0) {
+ this.value(options[0].value);
+ }
// refresh
this._refresh();
@@ -122,23 +157,31 @@
// refresh
_refresh: function() {
// remove placeholder
- $(this.el).find('option[value=null]').remove();
+ this.$select.find('option[value=null]').remove();
// count remaining entries
- var remaining = $(this.el).find('option').length;
+ var remaining = this.$select.find('option').length;
if (remaining == 0) {
// append placeholder
- $(this.el).append(this._templateOption({value : 'null', label : this.options.empty}));
+ this.$select.append(this._templateOption({value : 'null', label : this.options.empty}));
this.disable();
} else {
+ // enable select field
this.enable();
+
+ // update selected value
+ if (this.selected) {
+ //if (this._exists(selected)) {
+ this.$select.val(this.selected);
+ //}
+ }
}
},
// exists
_exists: function(value) {
// check if selected value exists
- return 0 != $(this.el).find('option[value=' + value + ']').length;
+ return 0 != this.$select.find('option[value=' + value + ']').length;
},
// option
@@ -148,21 +191,24 @@
// element
_template: function(options) {
- var tmpl = '<select id="' + options.id + '" class="select ' + options.cls + ' ' + options.id + '">';
+ var tmpl = '<div id="' + options.id + '">' +
+ '<i id="wait" class="fa fa-spinner fa-spin" style="font-size: 1.2em; display: none;"/>' +
+ '<select id="select" class="select ' + options.cls + ' ' + options.id + '">';
for (key in options.data) {
// options
var item = options.data[key];
// identify selected value
var tag = '';
- if (item.value == options.selected || item.value == '') {
+ if (item.value == options.value || item.value == '') {
tag = 'selected';
}
// add template string
- tmpl += '<option value="' + item.value + '" ' + tag + '>' + item.label + '</option>';
+ tmpl += '<option value="' + item.value + '" ' + tag + '>' + item.label + '</option>';
}
- tmpl += '</select>';
+ tmpl += '</select>' +
+ '</div>';
return tmpl;
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/library/utils.js
--- /dev/null
+++ b/config/plugins/visualizations/charts/static/library/utils.js
@@ -0,0 +1,152 @@
+/**
+ * Galaxy utilities comprises small functions, which at this point
+ * do not require their own classes/files
+*/
+
+// dependencies
+define(["libs/underscore"], function(_) {
+
+// generic function to recieve json from url
+function get (url, success, error) {
+ request('GET', url, {}, success, error);
+};
+
+// generic function to send json to url
+function request (method, url, data, success, error) {
+
+ // encode data into url
+ if (method == 'GET' || method == 'DELETE') {
+ if (url.indexOf('?') == -1) {
+ url += '?';
+ } else {
+ url += '&';
+ }
+ url += $.param(data)
+ }
+
+ // prepare request
+ var xhr = new XMLHttpRequest();
+ xhr.open(method, url, true);
+ xhr.setRequestHeader('Accept', 'application/json');
+ xhr.setRequestHeader('Cache-Control', 'no-cache');
+ xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
+ xhr.setRequestHeader('Content-Type', 'application/json');
+ xhr.onloadend = function() {
+ var status = xhr.status;
+ if (status == 200) {
+ try {
+ response = jQuery.parseJSON(xhr.responseText);
+ } catch (e) {
+ response = xhr.responseText;
+ }
+ success && success(response);
+ } else {
+ error && error(status);
+ }
+ };
+
+ // make request
+ if (method == 'GET' || method == 'DELETE') {
+ xhr.send();
+ } else {
+ xhr.send(JSON.stringify(data));
+ }
+};
+
+// get css value
+function cssGetAttribute (classname, name) {
+ // place dummy element
+ var el = $('<div class="' + classname + '"></div>');
+
+ // required append
+ el.appendTo(':eq(0)');
+
+ // get value
+ var value = el.css(name);
+
+ // remove element
+ el.remove();
+
+ // return css value
+ return value;
+};
+
+// load css
+function cssLoadFile (url) {
+ // check if css is already available
+ if (!$('link[href^="' + url + '"]').length)
+ $('<link href="' + galaxy_config.root + url + '" rel="stylesheet">').appendTo('head');
+};
+
+// merge
+function merge (options, optionsDefault) {
+ if (options)
+ return _.defaults(options, optionsDefault);
+ else
+ return optionsDefault;
+};
+
+// to string
+function bytesToString (size, normal_font) {
+ // 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
+ if (size > 0) { size = size * 10; unit = 'b'; } else
+ return '<strong>-</strong>';
+
+ // return formatted string
+ var rounded = (Math.round(size) / 10);
+ if (normal_font) {
+ return rounded + ' ' + unit;
+ } else {
+ return '<strong>' + rounded + '</strong> ' + unit;
+ }
+};
+
+// unique ide
+function uuid(){
+ return (new Date().getTime()).toString(36);
+};
+
+// wrap
+function wrap($el) {
+ var wrapper = $('<p></p>');
+ wrapper.append($el);
+ return wrapper;
+};
+
+// time
+function time() {
+ // get date object
+ var d = new Date();
+
+ // format items
+ var hours = (d.getHours() < 10 ? "0" : "") + d.getHours();
+ var minutes = (d.getMinutes() < 10 ? "0" : "") + d.getMinutes()
+
+ // format final stamp
+ var datetime = d.getDate() + "/"
+ + (d.getMonth() + 1) + "/"
+ + d.getFullYear() + ", "
+ + hours + ":"
+ + minutes;
+ return datetime;
+};
+
+// return
+return {
+ cssLoadFile : cssLoadFile,
+ cssGetAttribute : cssGetAttribute,
+ get : get,
+ merge : merge,
+ bytesToString: bytesToString,
+ uuid: uuid,
+ time: time,
+ wrap: wrap,
+ request: request
+};
+
+});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/chart.js
--- a/config/plugins/visualizations/charts/static/models/chart.js
+++ b/config/plugins/visualizations/charts/static/models/chart.js
@@ -7,10 +7,12 @@
{
// defaults
defaults : {
- id : null,
- title : '',
- type : '',
- date : null
+ id : null,
+ title : '',
+ type : '',
+ date : null,
+ state : '',
+ state_info : ''
},
// initialize
@@ -37,6 +39,11 @@
current.groups.add(group.clone());
});
current.trigger('change', current);
+ },
+
+ state: function(value, info) {
+ this.set('state_info', info);
+ this.set('state', value);
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/config.js
--- a/config/plugins/visualizations/charts/static/models/config.js
+++ b/config/plugins/visualizations/charts/static/models/config.js
@@ -1,15 +1,13 @@
// dependencies
define([], function() {
-
// model
return Backbone.Model.extend(
{
// options
defaults : {
- query_limit : 20,
- query_pace : 1000,
- query_max : 5,
+ query_limit : 1000,
+ query_timeout : 500,
title : 'Create a new chart'
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/datasets.js
--- a/config/plugins/visualizations/charts/static/models/datasets.js
+++ /dev/null
@@ -1,125 +0,0 @@
-// dependencies
-define(['utils/utils'], function(Utils) {
-
-// widget
-return Backbone.Model.extend(
-{
- // options
- optionsDefault : {
- limit : 500,
- pace : 1000,
- max : 2
- },
-
- // list
- list: {},
-
- // initialize
- initialize: function(app, options)
- {
- // link app
- this.app = app;
-
- // configure options
- this.options = Utils.merge(options, this.optionsDefault);
- },
-
- // get
- get: function(options, callback) {
- // check if dataset already exists
- var dataset = this.list[options.id];
- if (dataset) {
- if (dataset.values) {
- if (dataset.values[options.column]) {
- if (callback) {
- callback(dataset);
- }
- return dataset;
- }
- }
- } else {
- this.list[options.id] = dataset = this.app.options.dataset;
- }
-
- // initiate fetch cycle
- if (options.column !== undefined) {
- this._fetch(options, callback);
- } else {
- if (callback) {
- callback(dataset);
- }
- return dataset;
- }
-
- // return
- return dataset;
- },
-
- // size
- length: function() {
- return this.list.length;
- },
-
- // request data
- _fetch : function(options, callback) {
- // get dataset
- var dataset = this.list[options.id];
-
- // initialize values for datasets
- if (!dataset.values) {
- dataset.values = {};
- }
- if (!dataset.values[options.column]) {
- dataset.values[options.column] = [];
- }
-
- // initialize page number
- if (options.page === undefined) {
- options.page = 0;
- } else {
- options.page++;
- }
-
- // check max page
- if (options.page > this.options.max) {
- return;
- }
-
- // config limits
- var limit = this.options.limit;
- var offset = this.options.limit * options.page;
-
- // make request
- var self = this;
- Utils.request('GET', config.root + 'api/datasets/' + options.id, {
- data_type : 'raw_data',
- provider : 'dataset-column',
- limit : limit,
- offset : offset,
- indeces : options.column
- }, function(response) {
- // verify if all data has been fetched
- if (response.data.length > 0) {
- // add values to dataset
- for (var key in response.data){
- var value = response.data[key][0];
- if (value !== undefined) {
- dataset.values[options.column].push(value);
- } else {
- return dataset;
- }
- }
-
- // update charts
- if (callback) {
- callback(dataset);
- }
-
- // next call
- setTimeout(function() { self._fetch(options, callback); }, self.options.pace);
- }
- });
- }
-});
-
-});
\ No newline at end of file
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/group.js
--- a/config/plugins/visualizations/charts/static/models/group.js
+++ b/config/plugins/visualizations/charts/static/models/group.js
@@ -6,8 +6,8 @@
{
// options
defaults : {
- label : 'Data label',
- date : ''
+ key : 'Data label',
+ date : ''
},
// reset
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/models/types.js
--- a/config/plugins/visualizations/charts/static/models/types.js
+++ b/config/plugins/visualizations/charts/static/models/types.js
@@ -7,48 +7,57 @@
// types
defaults: {
'bardiagram' : {
- title : 'Bar diagram',
- data : {
+ title : 'Bar diagram',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
+ 'histogram' : {
+ title : 'Histogram',
+ mode : 'execute',
+ columns : {
+ y : {
+ title : 'Derive frequencies'
+ }
+ }
+ },
'horizontal' : {
- title : 'Bar diagram (horizontal)',
- data : {
+ title : 'Bar diagram (horizontal)',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'line' : {
- title : 'Line chart',
- data : {
+ title : 'Line chart',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'linewithfocus' : {
- title : 'Line chart (with focus)',
- data : {
+ title : 'Line chart (with focus)',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'piechart' : {
- title : 'Pie chart',
- data : {
+ title : 'Pie chart',
+ columns : {
y : {
title : 'Values for y-axis'
}
}
},
'scatterplot' : {
- title : 'Scatter plot',
- data : {
+ title : 'Scatter plot',
+ columns : {
x : {
title : 'Values for x-axis'
},
@@ -58,8 +67,8 @@
}
},
'stackedarea' : {
- title : 'Stacked area',
- data : {
+ title : 'Stacked area',
+ columns : {
y : {
title : 'Values for y-axis'
}
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/views/chart.js
--- a/config/plugins/visualizations/charts/static/views/chart.js
+++ b/config/plugins/visualizations/charts/static/views/chart.js
@@ -97,7 +97,7 @@
// save chart
self._saveChart();
- // show viewport
+ // show charts
self.hide();
self.app.charts_view.$el.show();
}
@@ -125,7 +125,6 @@
self.app.config.set('title', self.title.value());
}
});
- this.dataset = new Ui.Input({value : app.options.dataset.id, disabled: true, visible: false});
// append element
var $settings = $('<div/>');
@@ -183,8 +182,8 @@
this.app.chart.groups.on('reset', function(group) {
self._removeAllGroups();
});
- this.app.chart.groups.on('change:label', function(group) {
- self._refreshLabels();
+ this.app.chart.groups.on('change:key', function(group) {
+ self._refreshGroupKey();
});
// reset
@@ -198,11 +197,11 @@
},
// update
- _refreshLabels: function() {
+ _refreshGroupKey: function() {
var self = this;
var counter = 0;
this.chart.groups.each(function(group) {
- var title = group.get('label', '');
+ var title = group.get('key', '');
if (title == '') {
title = 'Chart data';
}
@@ -213,8 +212,7 @@
// new group
_addGroupModel: function() {
var group = new Group({
- id : Utils.uuid(),
- dataset_id : this.chart.get('dataset_id')
+ id : Utils.uuid()
});
this.chart.groups.add(group);
return group;
@@ -241,7 +239,7 @@
});
// update titles
- this._refreshLabels()
+ this._refreshGroupKey();
},
// remove group
@@ -249,7 +247,7 @@
this.tabs.del(group.id);
// update titles
- this._refreshLabels()
+ this._refreshGroupKey();
},
// remove group
@@ -261,8 +259,10 @@
_resetChart: function() {
// reset chart details
this.chart.set('id', Utils.uuid());
+ this.chart.set('type', 'bardiagram');
this.chart.set('dataset_id', this.app.options.dataset.id);
- this.chart.set('type', 'bardiagram');
+ this.chart.set('dataset_hid', this.app.options.dataset.hid);
+ this.chart.set('history_id', this.app.options.dataset.history_id);
this.chart.set('title', 'New Chart');
},
@@ -272,7 +272,6 @@
this.chart.set({
type : this.table.value(),
title : this.title.value(),
- dataset_id : this.dataset.value(),
date : Utils.time()
});
@@ -280,11 +279,14 @@
var current = this.app.charts.get(this.chart.id);
if (!current) {
current = this.chart.clone();
+ current.copy(this.chart);
this.app.charts.add(current);
+ } else {
+ current.copy(this.chart);
}
-
- // update chart model
- current.copy(this.chart);
+
+ // trigger redraw
+ current.set('state', 'redraw');
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/views/charts.js
--- a/config/plugins/visualizations/charts/static/views/charts.js
+++ b/config/plugins/visualizations/charts/static/views/charts.js
@@ -1,5 +1,5 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/group'], function(Portlet, Table, Ui, Utils, Group) {
+define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils', 'plugin/models/group', 'plugin/views/viewport',], function(Portlet, Table, Ui, Utils, Group, ViewportView) {
// widget
return Backbone.View.extend(
@@ -10,6 +10,9 @@
// link app
this.app = app;
+ // create viewport
+ this.viewport_view = new ViewportView(app);
+
// table
this.table = new Table({
content : 'Add charts to this table.',
@@ -32,7 +35,7 @@
self.app.config.set('title', chart.get('title'));
// show viewport
- self.app.viewport_view.show(chart_id);
+ self.viewport_view.showChart(chart_id);
}
});
@@ -89,11 +92,15 @@
});
this.portlet.append(this.table.$el);
- // append to main
+ // append portlet with table
if (!this.app.options.config.widget) {
this.$el.append(this.portlet.$el);
}
+ // append view port
+ this.$el.append(Utils.wrap(''));
+ this.$el.append(this.viewport_view.$el);
+
// events
var self = this;
this.app.charts.on('add', function(chart) {
@@ -106,8 +113,7 @@
});
this.app.charts.on('change', function(chart) {
// replace
- self._removeChart(chart);
- self._addChart(chart);
+ self._changeChart(chart);
});
},
@@ -117,12 +123,6 @@
this.$el.hide();
},
- // append
- append : function($el) {
- this.$el.append(Utils.wrap(''));
- this.$el.append($el);
- },
-
// add
_addChart: function(chart) {
// add title to table
@@ -146,11 +146,21 @@
// check if table is empty
if (this.table.size() == 0) {
this.hide();
+ this.app.chart.reset();
this.app.chart_view.$el.show();
} else {
// select available chart
this.table.value(this.app.charts.last().id);
}
+ },
+
+ // change
+ _changeChart: function(chart) {
+ // add chart
+ this._addChart(chart);
+
+ // select available chart
+ this.table.value(chart.id);
}
});
diff -r ff303b254f5a2ae3dfa213d5cde5ed65070b1961 -r 4ec6ff7c4165fff75f0e52735bb189ee2f29cecd config/plugins/visualizations/charts/static/views/group.js
--- a/config/plugins/visualizations/charts/static/views/group.js
+++ b/config/plugins/visualizations/charts/static/views/group.js
@@ -1,6 +1,6 @@
// dependencies
-define(['mvc/ui/ui-portlet', 'plugin/library/table', 'plugin/library/ui', 'utils/utils'],
- function(Portlet, Table, Ui, Utils) {
+define(['plugin/library/table', 'plugin/library/ui', 'utils/utils'],
+ function(Table, Ui, Utils) {
// chart config
return Backbone.View.extend(
@@ -23,18 +23,18 @@
this.group = options.group;
// ui elements
- this.label = new Ui.Input({
+ this.group_key = new Ui.Input({
placeholder: 'Data label',
onchange: function() {
- self.group.set('label', self.label.value());
+ self.group.set('key', self.group_key.value());
}
});
this.table = new Table({content: 'No data column.'});
- // add table to portlet
+ // create element
var $view = $('<div/>');
$view.append(Utils.wrap((new Ui.Label({title: 'Provide a label:'})).$el));
- $view.append(Utils.wrap(this.label.$el));
+ $view.append(Utils.wrap(this.group_key.$el));
$view.append(Utils.wrap((new Ui.Label({title: 'Select columns:'})).$el));
$view.append(Utils.wrap(this.table.$el));
@@ -44,101 +44,92 @@
// change
var self = this;
this.chart.on('change:dataset_id', function() {
- self._refreshDataset();
+ self._refreshTable();
});
this.chart.on('change:type', function() {
- self._refreshType();
+ self._refreshTable();
});
- this.group.on('change:label', function() {
- self._refreshLabel();
+ this.group.on('change:key', function() {
+ self._refreshGroupKey();
});
this.group.on('change', function() {
self._refreshGroup();
});
// refresh
- this._refresh();
- },
-
- // render
- _refresh: function() {
- this._refreshDataset();
- this._refreshType();
- this._refreshLabel();
+ this._refreshTable();
+ this._refreshGroupKey();
this._refreshGroup();
},
// update dataset
- _refreshDataset: function() {
+ _refreshTable: function() {
// identify datasets
var dataset_id = this.chart.get('dataset_id');
+ var chart_type = this.chart.get('type');
// check if dataset is available
- if (!dataset_id) {
+ if (!dataset_id || !chart_type) {
return;
}
+ // link this
+ var self = this;
+
+ // configure chart type
+ var chart_settings = this.app.types.get(chart_type);
+
+ // reset table
+ this.table.removeAll();
+
+ // load list
+ var list = {};
+ for (var id in chart_settings.columns) {
+ // initialize
+ var value = this.group.get(id);
+ if (!value) {
+ this.group.set(id, 0);
+ }
+
+ // create select field
+ var data_def = chart_settings.columns[id];
+ var select = new Ui.Select({
+ id : 'select_' + id,
+ gid : id,
+ onchange : function(value) {
+ self.group.set(this.gid, value);
+ },
+ value : value,
+ wait : true
+ });
+
+ // add row to table
+ this.table.add(data_def.title);
+ this.table.add(select.$el);
+ this.table.append(id);
+
+ // add select field to list
+ list[id] = select;
+ }
+
// get dataset
- var dataset = this.app.datasets.get({id : dataset_id});
-
- // check
- if (!dataset) {
- this.app.log('Group::_refreshDataset()', 'Failed to retrieve dataset.');
- return;
- }
-
- // configure columns
- this.columns = [];
- var meta = dataset.metadata_column_types;
- for (var key in meta){
- this.columns.push({
- 'label' : key + ' [' + meta[key] + ']',
- 'value' : key
- });
- }
-
- // update select fields
- for (var key in this.list) {
- this.list[key].update(this.columns);
- }
- },
-
- // update
- _refreshType: function() {
- // configure chart type
- var self = this;
- var chart_type = this.chart.get('type');
- if (chart_type) {
- var chart_settings = this.app.types.get(chart_type);
-
- // table
- this.table.removeAll();
- this.list = {};
- for (var id in chart_settings.data) {
- // create select field
- var data_def = chart_settings.data[id];
- var select = new Ui.Select({
- id : 'select_' + id,
- gid : id,
- data : this.columns,
- onchange : function(value) {
- self.group.set(this.gid, value);
- },
- value : this.group.get(id)
+ this.app.datasets.request({id : dataset_id}, function(dataset) {
+ // configure columns
+ self.columns = [];
+ var meta = dataset.metadata_column_types;
+ for (var key in meta){
+ self.columns.push({
+ 'label' : key + ' [' + meta[key] + ']',
+ 'value' : key
});
-
- // set model value
- this.group.set(id, select.value());
-
- // add row to table
- this.table.add(data_def.title);
- this.table.add(select.$el);
- this.table.append(id);
-
- // add select field to list
- this.list[id] = select;
}
- }
+
+ // update select fields
+ for (var key in list) {
+ list[key].update(self.columns);
+ list[key].show();
+ }
+ });
},
// update
@@ -146,13 +137,13 @@
this.group.set('date', Utils.time());
},
- // update label
- _refreshLabel: function() {
- var label_text = this.group.get('label');
- if (label_text === undefined) {
- label_text = '';
+ // update group key
+ _refreshGroupKey: function() {
+ var key_text = this.group.get('key');
+ if (key_text === undefined) {
+ key_text = '';
}
- this.label.value(label_text);
+ this.group_key.value(key_text);
}
});
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/ccfb1805efd0/
Changeset: ccfb1805efd0
Branch: stable
User: natefoo
Date: 2014-03-05 19:59:41
Summary: Correctly handle Slurm jobs that are not caught by the job monitor until after MinJobAge (and thus appear to be "invalid jobs").
Affected #: 1 file
diff -r f1a13b9f2c3eb89dd28a8bbcc20fd929d39dcb65 -r ccfb1805efd075ebb2ab56f4b75509e7d6d99ebb lib/galaxy/jobs/runners/slurm.py
--- a/lib/galaxy/jobs/runners/slurm.py
+++ b/lib/galaxy/jobs/runners/slurm.py
@@ -19,8 +19,14 @@
def _complete_terminal_job( self, ajs, drmaa_state, **kwargs ):
def __get_jobinfo():
- scontrol_out = subprocess.check_output( ( 'scontrol', '-o', 'show', 'job', ajs.job_id ) )
- return dict( [ out_param.split( '=', 1 ) for out_param in scontrol_out.split() ] )
+ p = subprocess.Popen( ( 'scontrol', '-o', 'show', 'job', ajs.job_id ), stdout=subprocess.PIPE, stderr=subprocess.PIPE )
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ # Will need to be more clever here if this message is not consistent
+ if stderr == 'slurm_load_jobs error: Invalid job id specified\n':
+ return dict( JobState='NOT_FOUND' )
+ raise Exception( '`scontrol -o show job %s` returned %s, stderr: %s' % ( ajs.job_id, p.returncode, stderr ) )
+ return dict( [ out_param.split( '=', 1 ) for out_param in stdout.split() ] )
if drmaa_state == self.drmaa_job_states.FAILED:
try:
job_info = __get_jobinfo()
@@ -33,7 +39,10 @@
ajs.fail_message = "This job failed and the system timed out while trying to determine the cause of the failure."
break
job_info = __get_jobinfo()
- if job_info['JobState'] == 'TIMEOUT':
+ if job_info['JobState'] == 'NOT_FOUND':
+ log.warning( '(%s/%s) Job not found, assuming job check exceeded MinJobAge and completing as successful', ajs.job_wrapper.get_id_tag(), ajs.job_id )
+ drmaa_state = self.drmaa_job_states.DONE
+ elif job_info['JobState'] == 'TIMEOUT':
ajs.fail_message = "This job was terminated because it ran longer than the maximum allowed job run time."
elif job_info['JobState'] == 'NODE_FAIL':
log.warning( '(%s/%s) Job failed due to node failure, attempting resubmission', ajs.job_wrapper.get_id_tag(), ajs.job_id )
@@ -47,11 +56,12 @@
ajs.fail_message = "This job failed because it was cancelled by an administrator."
else:
ajs.fail_message = "This job failed for reasons that could not be determined."
- ajs.fail_message += '\nPlease click the bug icon to report this problem if you need help.'
- ajs.stop_job = False
- self.work_queue.put( ( self.fail_job, ajs ) )
+ if drmaa_state == self.drmaa_job_states.FAILED:
+ ajs.fail_message += '\nPlease click the bug icon to report this problem if you need help.'
+ ajs.stop_job = False
+ self.work_queue.put( ( self.fail_job, ajs ) )
except Exception, e:
log.exception( '(%s/%s) Unable to inspect failed slurm job using scontrol, job will be unconditionally failed: %s', ajs.job_wrapper.get_id_tag(), ajs.job_id, e )
super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state = drmaa_state )
- elif drmaa_state == self.drmaa_job_states.DONE:
- super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state = drmaa_state )
+ # by default, finish as if the job was successful.
+ super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state = drmaa_state )
https://bitbucket.org/galaxy/galaxy-central/commits/4cad859d0325/
Changeset: 4cad859d0325
User: natefoo
Date: 2014-03-05 20:00:27
Summary: merge stable.
Affected #: 1 file
diff -r 8bb60a2538f6d2c4525ea50e3c37e3e78063814b -r 4cad859d032560a123f57eac78a81f852dc7531e lib/galaxy/jobs/runners/slurm.py
--- a/lib/galaxy/jobs/runners/slurm.py
+++ b/lib/galaxy/jobs/runners/slurm.py
@@ -19,8 +19,14 @@
def _complete_terminal_job( self, ajs, drmaa_state, **kwargs ):
def __get_jobinfo():
- scontrol_out = subprocess.check_output( ( 'scontrol', '-o', 'show', 'job', ajs.job_id ) )
- return dict( [ out_param.split( '=', 1 ) for out_param in scontrol_out.split() ] )
+ p = subprocess.Popen( ( 'scontrol', '-o', 'show', 'job', ajs.job_id ), stdout=subprocess.PIPE, stderr=subprocess.PIPE )
+ stdout, stderr = p.communicate()
+ if p.returncode != 0:
+ # Will need to be more clever here if this message is not consistent
+ if stderr == 'slurm_load_jobs error: Invalid job id specified\n':
+ return dict( JobState='NOT_FOUND' )
+ raise Exception( '`scontrol -o show job %s` returned %s, stderr: %s' % ( ajs.job_id, p.returncode, stderr ) )
+ return dict( [ out_param.split( '=', 1 ) for out_param in stdout.split() ] )
if drmaa_state == self.drmaa_job_states.FAILED:
try:
job_info = __get_jobinfo()
@@ -33,7 +39,10 @@
ajs.fail_message = "This job failed and the system timed out while trying to determine the cause of the failure."
break
job_info = __get_jobinfo()
- if job_info['JobState'] == 'TIMEOUT':
+ if job_info['JobState'] == 'NOT_FOUND':
+ log.warning( '(%s/%s) Job not found, assuming job check exceeded MinJobAge and completing as successful', ajs.job_wrapper.get_id_tag(), ajs.job_id )
+ drmaa_state = self.drmaa_job_states.DONE
+ elif job_info['JobState'] == 'TIMEOUT':
ajs.fail_message = "This job was terminated because it ran longer than the maximum allowed job run time."
elif job_info['JobState'] == 'NODE_FAIL':
log.warning( '(%s/%s) Job failed due to node failure, attempting resubmission', ajs.job_wrapper.get_id_tag(), ajs.job_id )
@@ -47,11 +56,12 @@
ajs.fail_message = "This job failed because it was cancelled by an administrator."
else:
ajs.fail_message = "This job failed for reasons that could not be determined."
- ajs.fail_message += '\nPlease click the bug icon to report this problem if you need help.'
- ajs.stop_job = False
- self.work_queue.put( ( self.fail_job, ajs ) )
+ if drmaa_state == self.drmaa_job_states.FAILED:
+ ajs.fail_message += '\nPlease click the bug icon to report this problem if you need help.'
+ ajs.stop_job = False
+ self.work_queue.put( ( self.fail_job, ajs ) )
except Exception, e:
log.exception( '(%s/%s) Unable to inspect failed slurm job using scontrol, job will be unconditionally failed: %s', ajs.job_wrapper.get_id_tag(), ajs.job_id, e )
super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state = drmaa_state )
- elif drmaa_state == self.drmaa_job_states.DONE:
- super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state = drmaa_state )
+ # by default, finish as if the job was successful.
+ super( SlurmJobRunner, self )._complete_terminal_job( ajs, drmaa_state = drmaa_state )
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
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/07508592cb65/
Changeset: 07508592cb65
User: jeremy goecks
Date: 2014-03-05 18:00:16
Summary: Enable workflow display_by_username_and_slug to support different 'display' formats: html, json, and json download. This makes it possible to generate human-readable URLs for all workflow display/download/export actions. Update download and export links to use display_by_username_and_slug.
Affected #: 3 files
diff -r 27f8a2d9c7115418b263b2ff2d705b96ed9e412b -r 07508592cb65845474b9f3e0f781260c0fd861bc lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -66,6 +66,7 @@
webapp.add_route( '/u/:username/p/:slug', controller='page', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/h/:slug', controller='history', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/w/:slug', controller='workflow', action='display_by_username_and_slug' )
+ webapp.add_route( '/u/:username/w/:slug/:format', controller='workflow', action='display_by_username_and_slug' )
webapp.add_route( '/u/:username/v/:slug', controller='visualization', action='display_by_username_and_slug' )
webapp.add_route( '/search', controller='search', action='index' )
diff -r 27f8a2d9c7115418b263b2ff2d705b96ed9e412b -r 07508592cb65845474b9f3e0f781260c0fd861bc lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -219,24 +219,35 @@
return trans.fill_template( "workflow/list_published.mako", grid=grid )
@web.expose
- def display_by_username_and_slug( self, trans, username, slug ):
- """ Display workflow based on a username and slug. """
+ def display_by_username_and_slug( self, trans, username, slug, format='html' ):
+ """
+ Display workflow based on a username and slug. Format can be html, json, or json-download.
+ """
- # Get workflow.
+ # Get workflow by username and slug. Security is handled by the display methods below.
session = trans.sa_session
user = session.query( model.User ).filter_by( username=username ).first()
stored_workflow = trans.sa_session.query( model.StoredWorkflow ).filter_by( user=user, slug=slug, deleted=False ).first()
- return self.display(trans, stored_workflow)
+ encoded_id = trans.security.encode_id( stored_workflow.id )
+
+ # Display workflow in requested format.
+ if format == 'html':
+ return self._display( trans, stored_workflow )
+ elif format == 'json':
+ return self.for_direct_import( trans, encoded_id )
+ elif format == 'json-download':
+ return self.export_to_file( trans, encoded_id )
@web.expose
def display_by_id( self, trans, id ):
""" Display workflow based on id. """
# Get workflow.
stored_workflow = self.get_stored_workflow( trans, id )
- return self.display(trans, stored_workflow)
+ return self._display(trans, stored_workflow)
- def display(self, trans, stored_workflow):
- """ Base workflow display """
+ def _display( self, trans, stored_workflow ):
+ """ Diplay workflow as HTML page. """
+
if stored_workflow is None:
raise web.httpexceptions.HTTPNotFound()
# Security check raises error if user cannot access workflow.
@@ -552,6 +563,7 @@
stored_workflow = model.StoredWorkflow()
stored_workflow.name = workflow_name
stored_workflow.user = user
+ self.create_item_slug( trans.sa_session, stored_workflow )
# And the first (empty) workflow revision
workflow = model.Workflow()
workflow.name = workflow_name
@@ -882,6 +894,12 @@
Handles download/export workflow command.
"""
stored = self.get_stored_workflow( trans, id, check_ownership=False, check_accessible=True )
+
+ # Export requires workflow to have a slug, so set slug if necessary.
+ if not stored.slug:
+ self.create_item_slug( trans.sa_session, stored )
+ trans.sa_session.flush()
+
return trans.fill_template( "/workflow/export.mako", item=stored, use_panels=True )
@web.expose
diff -r 27f8a2d9c7115418b263b2ff2d705b96ed9e412b -r 07508592cb65845474b9f3e0f781260c0fd861bc templates/export_base.mako
--- a/templates/export_base.mako
+++ b/templates/export_base.mako
@@ -78,7 +78,8 @@
%if item.importable:
Use this URL to import the ${get_class_display_name( item.__class__ ).lower()} directly into another Galaxy server:
<div class="display-url">
- ${h.url_for(controller=self.controller, action='for_direct_import', id=trans.security.encode_id( item.id ), qualified=True )}
+ ${h.url_for(controller=self.controller, action='display_by_username_and_slug', username=trans.user.username,
+ slug=item.slug, format='json', qualified=True )}
</div>
(Copy this URL into the box titled 'Workflow URL' in the Import Workflow page.)
%else:
@@ -89,7 +90,8 @@
<%def name="render_download_to_file(item)"><h3>Download to File</h3>
- <a href="${h.url_for(controller=self.controller, action='export_to_file', id=trans.security.encode_id( item.id ) )}">
+ <a href="${h.url_for( controller=self.controller, action='display_by_username_and_slug', username=trans.user.username,
+ slug=item.slug, format='json-download' )}">
Download ${get_class_display_name( item.__class__ ).lower()} to file so that it can be saved or imported into another Galaxy server.</a></%def>
https://bitbucket.org/galaxy/galaxy-central/commits/63dd3cfc0abe/
Changeset: 63dd3cfc0abe
User: jeremy goecks
Date: 2014-03-05 18:23:27
Summary: Fix 07508592cb65 bug to correctly set username for workflow download/link.
Affected #: 1 file
diff -r 07508592cb65845474b9f3e0f781260c0fd861bc -r 63dd3cfc0abe162d6825a8ac8cbee027678d1793 templates/export_base.mako
--- a/templates/export_base.mako
+++ b/templates/export_base.mako
@@ -78,7 +78,7 @@
%if item.importable:
Use this URL to import the ${get_class_display_name( item.__class__ ).lower()} directly into another Galaxy server:
<div class="display-url">
- ${h.url_for(controller=self.controller, action='display_by_username_and_slug', username=trans.user.username,
+ ${h.url_for(controller=self.controller, action='display_by_username_and_slug', username=item.user.username,
slug=item.slug, format='json', qualified=True )}
</div>
(Copy this URL into the box titled 'Workflow URL' in the Import Workflow page.)
@@ -90,7 +90,7 @@
<%def name="render_download_to_file(item)"><h3>Download to File</h3>
- <a href="${h.url_for( controller=self.controller, action='display_by_username_and_slug', username=trans.user.username,
+ <a href="${h.url_for( controller=self.controller, action='display_by_username_and_slug', username=item.user.username,
slug=item.slug, format='json-download' )}">
Download ${get_class_display_name( item.__class__ ).lower()} to file so that it can be saved or imported into another Galaxy server.</a></%def>
https://bitbucket.org/galaxy/galaxy-central/commits/920332bc082c/
Changeset: 920332bc082c
User: jeremy goecks
Date: 2014-03-05 18:25:33
Summary: Add save and link options for embedded workflows.
Affected #: 1 file
diff -r 63dd3cfc0abe162d6825a8ac8cbee027678d1793 -r 920332bc082cbd40452ccd0ac10f29192e094dad templates/webapps/galaxy/workflow/embed.mako
--- a/templates/webapps/galaxy/workflow/embed.mako
+++ b/templates/webapps/galaxy/workflow/embed.mako
@@ -3,6 +3,17 @@
from galaxy.web.framework.helpers import iff
%>
+<%def name="render_item_links( workflow )">
+ <a href="${h.url_for( controller='workflow', action='display_by_username_and_slug', username=workflow.user.username,
+ slug=item.slug, format='json-download' )}" title="Save Worflow" class="icon-button disk">
+ ## FIXME: find and set appropriate icon for linking to workflow.
+ <!--
+ <a href="${h.url_for( controller='workflow', action='display_by_username_and_slug', username=workflow.user.username,
+ slug=item.slug, format='json' )}" title="Worflow Link for Import" class="icon-button TODO ">
+ -->
+ ${parent.render_item_links( workflow )}
+</%def>
+
<%def name="render_summary_content( workflow, steps )">
## <ul>
https://bitbucket.org/galaxy/galaxy-central/commits/8bb60a2538f6/
Changeset: 8bb60a2538f6
User: jeremy goecks
Date: 2014-03-05 18:34:44
Summary: To ensure that workflow has a slug, create slug when retrieving workflow from database. Remove slug creation code from user controller actions.
Affected #: 2 files
diff -r 920332bc082cbd40452ccd0ac10f29192e094dad -r 8bb60a2538f6d2c4525ea50e3c37e3e78063814b lib/galaxy/web/base/controller.py
--- a/lib/galaxy/web/base/controller.py
+++ b/lib/galaxy/web/base/controller.py
@@ -1562,10 +1562,18 @@
workflow = trans.sa_session.query( trans.model.StoredWorkflow ).get( trans.security.decode_id( id ) )
except TypeError:
workflow = None
+
if not workflow:
error( "Workflow not found" )
else:
- return self.security_check( trans, workflow, check_ownership, check_accessible )
+ self.security_check( trans, workflow, check_ownership, check_accessible )
+
+ # Older workflows may be missing slugs, so set them here.
+ if not workflow.slug:
+ self.create_item_slug( trans.sa_session, workflow )
+ trans.sa_session.flush()
+
+ return workflow
def get_stored_workflow_steps( self, trans, stored_workflow ):
""" Restores states for a stored workflow's steps. """
diff -r 920332bc082cbd40452ccd0ac10f29192e094dad -r 8bb60a2538f6d2c4525ea50e3c37e3e78063814b lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -313,7 +313,6 @@
share.user = other
session = trans.sa_session
session.add( share )
- self.create_item_slug( session, stored )
session.flush()
trans.set_message( "Workflow '%s' shared with user '%s'" % ( stored.name, other.email ) )
return trans.response.send_redirect( url_for( controller='workflow', action='sharing', id=id ) )
@@ -505,8 +504,6 @@
""" Returns workflow's name and link. """
stored = self.get_stored_workflow( trans, id )
- if self.create_item_slug( trans.sa_session, stored ):
- trans.sa_session.flush()
return_dict = { "name" : stored.name, "link" : url_for(controller='workflow', action="display_by_username_and_slug", username=stored.user.username, slug=stored.slug ) }
return return_dict
@@ -895,11 +892,6 @@
"""
stored = self.get_stored_workflow( trans, id, check_ownership=False, check_accessible=True )
- # Export requires workflow to have a slug, so set slug if necessary.
- if not stored.slug:
- self.create_item_slug( trans.sa_session, stored )
- trans.sa_session.flush()
-
return trans.fill_template( "/workflow/export.mako", item=stored, use_panels=True )
@web.expose
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/f1a13b9f2c3e/
Changeset: f1a13b9f2c3e
Branch: stable
User: greg
Date: 2014-03-04 23:01:51
Summary: Fix for white ghost scenario discovery.
Affected #: 2 files
diff -r b1b8acdf8c7268dfded0a358acfe31308196381a -r f1a13b9f2c3eb89dd28a8bbcc20fd929d39dcb65 lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -1,3 +1,4 @@
+import copy
import logging
import os
import urllib
@@ -71,8 +72,8 @@
def get_dependencies_for_repository( trans, tool_shed_url, repo_info_dict, includes_tool_dependencies ):
"""
- Return dictionaries containing the sets of installed and missing tool dependencies and repository dependencies associated
- with the repository defined by the received repo_info_dict.
+ Return dictionaries containing the sets of installed and missing tool dependencies and repository
+ dependencies associated with the repository defined by the received repo_info_dict.
"""
repository = None
installed_rd = {}
@@ -86,15 +87,20 @@
if tool_dependencies:
if not includes_tool_dependencies:
includes_tool_dependencies = True
- # Inspect the tool_dependencies dictionary to separate the installed and missing tool dependencies. We don't add to installed_td
- # and missing_td here because at this point they are empty.
- installed_td, missing_td = get_installed_and_missing_tool_dependencies_for_installing_repository( trans, tool_shed_url, tool_dependencies )
- # In cases where a repository dependency is required only for compiling a dependent repository's tool dependency, the value of
- # repository_dependencies will be an empty dictionary here.
+ # Inspect the tool_dependencies dictionary to separate the installed and missing tool dependencies.
+ # We don't add to installed_td and missing_td here because at this point they are empty.
+ installed_td, missing_td = \
+ get_installed_and_missing_tool_dependencies_for_installing_repository( trans, tool_shed_url, tool_dependencies )
+ # In cases where a repository dependency is required only for compiling a dependent repository's
+ # tool dependency, the value of repository_dependencies will be an empty dictionary here.
if repository_dependencies:
# We have a repository with one or more defined repository dependencies.
if not repository:
- repository = suc.get_repository_for_dependency_relationship( trans.app, tool_shed_url, name, repository_owner, changeset_revision )
+ repository = suc.get_repository_for_dependency_relationship( trans.app,
+ tool_shed_url,
+ name,
+ repository_owner,
+ changeset_revision )
if repository and repository.metadata:
installed_rd, missing_rd = get_installed_and_missing_repository_dependencies( trans, repository )
else:
@@ -309,18 +315,26 @@
installed_tool_dependencies = {}
missing_tool_dependencies = {}
if tool_dependencies_dict:
- for td_key, val in tool_dependencies_dict.items():
+ # Make sure not to change anything in the received tool_dependencies_dict as that would be a bad side-effect!
+ tmp_tool_dependencies_dict = copy.deepcopy( tool_dependencies_dict )
+ for td_key, val in tmp_tool_dependencies_dict.items():
# Default the status to NEVER_INSTALLED.
tool_dependency_status = trans.install_model.ToolDependency.installation_status.NEVER_INSTALLED
# Set environment tool dependencies are a list.
if td_key == 'set_environment':
new_val = []
for requirement_dict in val:
- # {'repository_name': 'xx', 'name': 'bwa', 'version': '0.5.9', 'repository_owner': 'yy', 'changeset_revision': 'zz', 'type': 'package'}
- tool_dependency = tool_dependency_util.get_tool_dependency_by_name_version_type( trans.app,
- requirement_dict.get( 'name', None ),
- requirement_dict.get( 'version', None ),
- requirement_dict.get( 'type', 'package' ) )
+ # {'repository_name': 'xx',
+ # 'name': 'bwa',
+ # 'version': '0.5.9',
+ # 'repository_owner': 'yy',
+ # 'changeset_revision': 'zz',
+ # 'type': 'package'}
+ tool_dependency = \
+ tool_dependency_util.get_tool_dependency_by_name_version_type( trans.app,
+ requirement_dict.get( 'name', None ),
+ requirement_dict.get( 'version', None ),
+ requirement_dict.get( 'type', 'package' ) )
if tool_dependency:
tool_dependency_status = tool_dependency.status
requirement_dict[ 'status' ] = tool_dependency_status
@@ -331,7 +345,12 @@
missing_tool_dependencies[ td_key ] = new_val
else:
# The val dictionary looks something like this:
- # {'repository_name': 'xx', 'name': 'bwa', 'version': '0.5.9', 'repository_owner': 'yy', 'changeset_revision': 'zz', 'type': 'package'}
+ # {'repository_name': 'xx',
+ # 'name': 'bwa',
+ # 'version': '0.5.9',
+ # 'repository_owner': 'yy',
+ # 'changeset_revision': 'zz',
+ # 'type': 'package'}
tool_dependency = tool_dependency_util.get_tool_dependency_by_name_version_type( trans.app,
val.get( 'name', None ),
val.get( 'version', None ),
@@ -347,14 +366,16 @@
def get_required_repo_info_dicts( trans, tool_shed_url, repo_info_dicts ):
"""
- Inspect the list of repo_info_dicts for repository dependencies and append a repo_info_dict for each of them to the list. All
- repository_dependencies entries in each of the received repo_info_dicts includes all required repositories, so only one pass through
- this method is required to retrieve all repository dependencies.
+ Inspect the list of repo_info_dicts for repository dependencies and append a repo_info_dict for each of
+ them to the list. All repository_dependencies entries in each of the received repo_info_dicts includes
+ all required repositories, so only one pass through this method is required to retrieve all repository
+ dependencies.
"""
all_required_repo_info_dict = {}
all_repo_info_dicts = []
if repo_info_dicts:
- # We'll send tuples of ( tool_shed, repository_name, repository_owner, changeset_revision ) to the tool shed to discover repository ids.
+ # We'll send tuples of ( tool_shed, repository_name, repository_owner, changeset_revision ) to the tool
+ # shed to discover repository ids.
required_repository_tups = []
for repo_info_dict in repo_info_dicts:
if repo_info_dict not in all_repo_info_dicts:
@@ -368,9 +389,10 @@
continue
repository_components_tuple = container_util.get_components_from_key( key )
components_list = suc.extract_components_from_tuple( repository_components_tuple )
- # Skip listing a repository dependency if it is required only to compile a tool dependency defined for the dependent repository since
- # in this case, the repository dependency is really a dependency of the dependent repository's contained tool dependency, and only if
- # that tool dependency requires compilation.
+ # Skip listing a repository dependency if it is required only to compile a tool dependency
+ # defined for the dependent repository since in this case, the repository dependency is really
+ # a dependency of the dependent repository's contained tool dependency, and only if that
+ # tool dependency requires compilation.
# For backward compatibility to the 12/20/12 Galaxy release.
prior_installation_required = 'False'
only_if_compiling_contained_td = 'False'
@@ -388,8 +410,8 @@
only_if_compiling_contained_td = components_list[ 5 ]
except:
only_if_compiling_contained_td = 'False'
- # Skip listing a repository dependency if it is required only to compile a tool dependency defined for the dependent repository
- # (see above comment).
+ # Skip listing a repository dependency if it is required only to compile a tool dependency
+ # defined for the dependent repository (see above comment).
if not util.asbool( only_if_compiling_contained_td ):
if components_list not in required_repository_tups:
required_repository_tups.append( components_list )
diff -r b1b8acdf8c7268dfded0a358acfe31308196381a -r f1a13b9f2c3eb89dd28a8bbcc20fd929d39dcb65 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -99,34 +99,37 @@
def create_repository_dependency_objects( trans, tool_path, tool_shed_url, repo_info_dicts, install_repository_dependencies=False,
no_changes_checked=False, tool_panel_section_id=None, new_tool_panel_section_label=None ):
"""
- Discover all repository dependencies and make sure all tool_shed_repository and associated repository_dependency records exist as well as
- the dependency relationships between installed repositories. This method is called when uninstalled repositories are being reinstalled.
- If the user elected to install repository dependencies, all items in the all_repo_info_dicts list will be processed. However, if repository
- dependencies are not to be installed, only those items contained in the received repo_info_dicts list will be processed.
+ Discover all repository dependencies and make sure all tool_shed_repository and associated repository_dependency
+ records exist as well as the dependency relationships between installed repositories. This method is called when
+ uninstalled repositories are being reinstalled. If the user elected to install repository dependencies, all items
+ in the all_repo_info_dicts list will be processed. However, if repository dependencies are not to be installed,
+ only those items contained in the received repo_info_dicts list will be processed.
"""
log.debug( "Creating repository dependency objects..." )
- # The following list will be maintained within this method to contain all created or updated tool shed repositories, including repository
- # dependencies that may not be installed.
+ # The following list will be maintained within this method to contain all created or updated tool shed repositories,
+ # including repository dependencies that may not be installed.
all_created_or_updated_tool_shed_repositories = []
- # There will be a one-to-one mapping between items in 3 lists: created_or_updated_tool_shed_repositories, tool_panel_section_keys and
- # filtered_repo_info_dicts. The 3 lists will filter out repository dependencies that are not to be installed.
+ # There will be a one-to-one mapping between items in 3 lists: created_or_updated_tool_shed_repositories,
+ # tool_panel_section_keys and filtered_repo_info_dicts. The 3 lists will filter out repository dependencies
+ # that are not to be installed.
created_or_updated_tool_shed_repositories = []
tool_panel_section_keys = []
- # Repositories will be filtered (e.g., if already installed, if elected to not be installed, etc), so filter the associated repo_info_dicts
- # accordingly.
+ # Repositories will be filtered (e.g., if already installed, if elected to not be installed, etc), so filter
+ # the associated repo_info_dicts accordingly.
filtered_repo_info_dicts = []
- # Discover all repository dependencies and retrieve information for installing them. Even if the user elected to not install repository
- # dependencies we have to make sure all repository dependency objects exist so that the appropriate repository dependency relationships can
- # be built.
+ # Discover all repository dependencies and retrieve information for installing them. Even if the user elected
+ # to not install repository dependencies we have to make sure all repository dependency objects exist so that
+ # the appropriate repository dependency relationships can be built.
all_required_repo_info_dict = common_install_util.get_required_repo_info_dicts( trans, tool_shed_url, repo_info_dicts )
all_repo_info_dicts = all_required_repo_info_dict.get( 'all_repo_info_dicts', [] )
if not all_repo_info_dicts:
# No repository dependencies were discovered so process the received repositories.
all_repo_info_dicts = [ rid for rid in repo_info_dicts ]
for repo_info_dict in all_repo_info_dicts:
- # If the user elected to install repository dependencies, all items in the all_repo_info_dicts list will be processed. However, if
- # repository dependencies are not to be installed, only those items contained in the received repo_info_dicts list will be processed
- # but the the all_repo_info_dicts list will be used to create all defined repository dependency relationships.
+ # If the user elected to install repository dependencies, all items in the all_repo_info_dicts list will
+ # be processed. However, if repository dependencies are not to be installed, only those items contained
+ # in the received repo_info_dicts list will be processed but the the all_repo_info_dicts list will be used
+ # to create all defined repository dependency relationships.
if is_in_repo_info_dicts( repo_info_dict, repo_info_dicts ) or install_repository_dependencies:
for name, repo_info_tuple in repo_info_dict.items():
can_update_db_record = False
@@ -196,7 +199,7 @@
suc.create_or_update_tool_shed_repository( app=trans.app,
name=name,
description=description,
- installed_changeset_revision=changeset_revision,
+ installed_changeset_revision=installed_changeset_revision,
ctx_rev=ctx_rev,
repository_clone_url=repository_clone_url,
metadata_dict={},
https://bitbucket.org/galaxy/galaxy-central/commits/27f8a2d9c711/
Changeset: 27f8a2d9c711
User: davebgx
Date: 2014-03-04 23:03:11
Summary: Merge stable.
Affected #: 0 files
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 white ghost scenario discovery.
by commits-noreply@bitbucket.org 04 Mar '14
by commits-noreply@bitbucket.org 04 Mar '14
04 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/88778c84ab7b/
Changeset: 88778c84ab7b
User: greg
Date: 2014-03-04 23:01:51
Summary: Fix for white ghost scenario discovery.
Affected #: 2 files
diff -r 36fa1ad1fc17939b68d10339a7cead7d21803a11 -r 88778c84ab7b91e0ed9a78812dafb8bb0958a3e4 lib/tool_shed/util/common_install_util.py
--- a/lib/tool_shed/util/common_install_util.py
+++ b/lib/tool_shed/util/common_install_util.py
@@ -1,3 +1,4 @@
+import copy
import logging
import os
import urllib
@@ -71,8 +72,8 @@
def get_dependencies_for_repository( trans, tool_shed_url, repo_info_dict, includes_tool_dependencies ):
"""
- Return dictionaries containing the sets of installed and missing tool dependencies and repository dependencies associated
- with the repository defined by the received repo_info_dict.
+ Return dictionaries containing the sets of installed and missing tool dependencies and repository
+ dependencies associated with the repository defined by the received repo_info_dict.
"""
repository = None
installed_rd = {}
@@ -86,15 +87,20 @@
if tool_dependencies:
if not includes_tool_dependencies:
includes_tool_dependencies = True
- # Inspect the tool_dependencies dictionary to separate the installed and missing tool dependencies. We don't add to installed_td
- # and missing_td here because at this point they are empty.
- installed_td, missing_td = get_installed_and_missing_tool_dependencies_for_installing_repository( trans, tool_shed_url, tool_dependencies )
- # In cases where a repository dependency is required only for compiling a dependent repository's tool dependency, the value of
- # repository_dependencies will be an empty dictionary here.
+ # Inspect the tool_dependencies dictionary to separate the installed and missing tool dependencies.
+ # We don't add to installed_td and missing_td here because at this point they are empty.
+ installed_td, missing_td = \
+ get_installed_and_missing_tool_dependencies_for_installing_repository( trans, tool_shed_url, tool_dependencies )
+ # In cases where a repository dependency is required only for compiling a dependent repository's
+ # tool dependency, the value of repository_dependencies will be an empty dictionary here.
if repository_dependencies:
# We have a repository with one or more defined repository dependencies.
if not repository:
- repository = suc.get_repository_for_dependency_relationship( trans.app, tool_shed_url, name, repository_owner, changeset_revision )
+ repository = suc.get_repository_for_dependency_relationship( trans.app,
+ tool_shed_url,
+ name,
+ repository_owner,
+ changeset_revision )
if repository and repository.metadata:
installed_rd, missing_rd = get_installed_and_missing_repository_dependencies( trans, repository )
else:
@@ -309,18 +315,26 @@
installed_tool_dependencies = {}
missing_tool_dependencies = {}
if tool_dependencies_dict:
- for td_key, val in tool_dependencies_dict.items():
+ # Make sure not to change anything in the received tool_dependencies_dict as that would be a bad side-effect!
+ tmp_tool_dependencies_dict = copy.deepcopy( tool_dependencies_dict )
+ for td_key, val in tmp_tool_dependencies_dict.items():
# Default the status to NEVER_INSTALLED.
tool_dependency_status = trans.install_model.ToolDependency.installation_status.NEVER_INSTALLED
# Set environment tool dependencies are a list.
if td_key == 'set_environment':
new_val = []
for requirement_dict in val:
- # {'repository_name': 'xx', 'name': 'bwa', 'version': '0.5.9', 'repository_owner': 'yy', 'changeset_revision': 'zz', 'type': 'package'}
- tool_dependency = tool_dependency_util.get_tool_dependency_by_name_version_type( trans.app,
- requirement_dict.get( 'name', None ),
- requirement_dict.get( 'version', None ),
- requirement_dict.get( 'type', 'package' ) )
+ # {'repository_name': 'xx',
+ # 'name': 'bwa',
+ # 'version': '0.5.9',
+ # 'repository_owner': 'yy',
+ # 'changeset_revision': 'zz',
+ # 'type': 'package'}
+ tool_dependency = \
+ tool_dependency_util.get_tool_dependency_by_name_version_type( trans.app,
+ requirement_dict.get( 'name', None ),
+ requirement_dict.get( 'version', None ),
+ requirement_dict.get( 'type', 'package' ) )
if tool_dependency:
tool_dependency_status = tool_dependency.status
requirement_dict[ 'status' ] = tool_dependency_status
@@ -331,7 +345,12 @@
missing_tool_dependencies[ td_key ] = new_val
else:
# The val dictionary looks something like this:
- # {'repository_name': 'xx', 'name': 'bwa', 'version': '0.5.9', 'repository_owner': 'yy', 'changeset_revision': 'zz', 'type': 'package'}
+ # {'repository_name': 'xx',
+ # 'name': 'bwa',
+ # 'version': '0.5.9',
+ # 'repository_owner': 'yy',
+ # 'changeset_revision': 'zz',
+ # 'type': 'package'}
tool_dependency = tool_dependency_util.get_tool_dependency_by_name_version_type( trans.app,
val.get( 'name', None ),
val.get( 'version', None ),
@@ -347,14 +366,16 @@
def get_required_repo_info_dicts( trans, tool_shed_url, repo_info_dicts ):
"""
- Inspect the list of repo_info_dicts for repository dependencies and append a repo_info_dict for each of them to the list. All
- repository_dependencies entries in each of the received repo_info_dicts includes all required repositories, so only one pass through
- this method is required to retrieve all repository dependencies.
+ Inspect the list of repo_info_dicts for repository dependencies and append a repo_info_dict for each of
+ them to the list. All repository_dependencies entries in each of the received repo_info_dicts includes
+ all required repositories, so only one pass through this method is required to retrieve all repository
+ dependencies.
"""
all_required_repo_info_dict = {}
all_repo_info_dicts = []
if repo_info_dicts:
- # We'll send tuples of ( tool_shed, repository_name, repository_owner, changeset_revision ) to the tool shed to discover repository ids.
+ # We'll send tuples of ( tool_shed, repository_name, repository_owner, changeset_revision ) to the tool
+ # shed to discover repository ids.
required_repository_tups = []
for repo_info_dict in repo_info_dicts:
if repo_info_dict not in all_repo_info_dicts:
@@ -368,9 +389,10 @@
continue
repository_components_tuple = container_util.get_components_from_key( key )
components_list = suc.extract_components_from_tuple( repository_components_tuple )
- # Skip listing a repository dependency if it is required only to compile a tool dependency defined for the dependent repository since
- # in this case, the repository dependency is really a dependency of the dependent repository's contained tool dependency, and only if
- # that tool dependency requires compilation.
+ # Skip listing a repository dependency if it is required only to compile a tool dependency
+ # defined for the dependent repository since in this case, the repository dependency is really
+ # a dependency of the dependent repository's contained tool dependency, and only if that
+ # tool dependency requires compilation.
# For backward compatibility to the 12/20/12 Galaxy release.
prior_installation_required = 'False'
only_if_compiling_contained_td = 'False'
@@ -388,8 +410,8 @@
only_if_compiling_contained_td = components_list[ 5 ]
except:
only_if_compiling_contained_td = 'False'
- # Skip listing a repository dependency if it is required only to compile a tool dependency defined for the dependent repository
- # (see above comment).
+ # Skip listing a repository dependency if it is required only to compile a tool dependency
+ # defined for the dependent repository (see above comment).
if not util.asbool( only_if_compiling_contained_td ):
if components_list not in required_repository_tups:
required_repository_tups.append( components_list )
diff -r 36fa1ad1fc17939b68d10339a7cead7d21803a11 -r 88778c84ab7b91e0ed9a78812dafb8bb0958a3e4 lib/tool_shed/util/repository_dependency_util.py
--- a/lib/tool_shed/util/repository_dependency_util.py
+++ b/lib/tool_shed/util/repository_dependency_util.py
@@ -99,34 +99,37 @@
def create_repository_dependency_objects( trans, tool_path, tool_shed_url, repo_info_dicts, install_repository_dependencies=False,
no_changes_checked=False, tool_panel_section_id=None, new_tool_panel_section_label=None ):
"""
- Discover all repository dependencies and make sure all tool_shed_repository and associated repository_dependency records exist as well as
- the dependency relationships between installed repositories. This method is called when uninstalled repositories are being reinstalled.
- If the user elected to install repository dependencies, all items in the all_repo_info_dicts list will be processed. However, if repository
- dependencies are not to be installed, only those items contained in the received repo_info_dicts list will be processed.
+ Discover all repository dependencies and make sure all tool_shed_repository and associated repository_dependency
+ records exist as well as the dependency relationships between installed repositories. This method is called when
+ uninstalled repositories are being reinstalled. If the user elected to install repository dependencies, all items
+ in the all_repo_info_dicts list will be processed. However, if repository dependencies are not to be installed,
+ only those items contained in the received repo_info_dicts list will be processed.
"""
log.debug( "Creating repository dependency objects..." )
- # The following list will be maintained within this method to contain all created or updated tool shed repositories, including repository
- # dependencies that may not be installed.
+ # The following list will be maintained within this method to contain all created or updated tool shed repositories,
+ # including repository dependencies that may not be installed.
all_created_or_updated_tool_shed_repositories = []
- # There will be a one-to-one mapping between items in 3 lists: created_or_updated_tool_shed_repositories, tool_panel_section_keys and
- # filtered_repo_info_dicts. The 3 lists will filter out repository dependencies that are not to be installed.
+ # There will be a one-to-one mapping between items in 3 lists: created_or_updated_tool_shed_repositories,
+ # tool_panel_section_keys and filtered_repo_info_dicts. The 3 lists will filter out repository dependencies
+ # that are not to be installed.
created_or_updated_tool_shed_repositories = []
tool_panel_section_keys = []
- # Repositories will be filtered (e.g., if already installed, if elected to not be installed, etc), so filter the associated repo_info_dicts
- # accordingly.
+ # Repositories will be filtered (e.g., if already installed, if elected to not be installed, etc), so filter
+ # the associated repo_info_dicts accordingly.
filtered_repo_info_dicts = []
- # Discover all repository dependencies and retrieve information for installing them. Even if the user elected to not install repository
- # dependencies we have to make sure all repository dependency objects exist so that the appropriate repository dependency relationships can
- # be built.
+ # Discover all repository dependencies and retrieve information for installing them. Even if the user elected
+ # to not install repository dependencies we have to make sure all repository dependency objects exist so that
+ # the appropriate repository dependency relationships can be built.
all_required_repo_info_dict = common_install_util.get_required_repo_info_dicts( trans, tool_shed_url, repo_info_dicts )
all_repo_info_dicts = all_required_repo_info_dict.get( 'all_repo_info_dicts', [] )
if not all_repo_info_dicts:
# No repository dependencies were discovered so process the received repositories.
all_repo_info_dicts = [ rid for rid in repo_info_dicts ]
for repo_info_dict in all_repo_info_dicts:
- # If the user elected to install repository dependencies, all items in the all_repo_info_dicts list will be processed. However, if
- # repository dependencies are not to be installed, only those items contained in the received repo_info_dicts list will be processed
- # but the the all_repo_info_dicts list will be used to create all defined repository dependency relationships.
+ # If the user elected to install repository dependencies, all items in the all_repo_info_dicts list will
+ # be processed. However, if repository dependencies are not to be installed, only those items contained
+ # in the received repo_info_dicts list will be processed but the the all_repo_info_dicts list will be used
+ # to create all defined repository dependency relationships.
if is_in_repo_info_dicts( repo_info_dict, repo_info_dicts ) or install_repository_dependencies:
for name, repo_info_tuple in repo_info_dict.items():
can_update_db_record = False
@@ -196,7 +199,7 @@
suc.create_or_update_tool_shed_repository( app=trans.app,
name=name,
description=description,
- installed_changeset_revision=changeset_revision,
+ installed_changeset_revision=installed_changeset_revision,
ctx_rev=ctx_rev,
repository_clone_url=repository_clone_url,
metadata_dict={},
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
4 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/489a1fac832e/
Changeset: 489a1fac832e
User: jmchilton
Date: 2014-03-04 18:49:35
Summary: Fix node type being sent to prebuild_node in galaxy.workflow_editor.js.
Affected #: 1 file
diff -r bd2561df7d11308bd717cadd0158d26fbcf7e4dc -r 489a1fac832e0a10cdf77e9afa64b0a71b8f7774 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -605,7 +605,7 @@
// First pass, nodes
var using_workflow_outputs = false;
$.each( data.steps, function( id, step ) {
- var node = prebuild_node( "tool", step.name, step.tool_id );
+ var node = prebuild_node( step.type, step.name, step.tool_id );
node.init_field_data( step );
if ( step.position ) {
node.element.css( { top: step.position.top, left: step.position.left } );
https://bitbucket.org/galaxy/galaxy-central/commits/ef7be9474145/
Changeset: ef7be9474145
User: jmchilton
Date: 2014-03-04 18:49:35
Summary: Eliminate code dup. in workflow editor for building connectors.
Affected #: 1 file
diff -r 489a1fac832e0a10cdf77e9afa64b0a71b8f7774 -r ef7be94741451e43dca891603b3c06ebf06311a5 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -634,21 +634,16 @@
var node = wf.nodes[id];
$.each( step.input_connections, function( k, v ) {
if ( v ) {
- if ($.isArray(v)) {
- $.each( v, function (l,x ) {
- var other_node = wf.nodes[ x.id ];
- var c = new Connector();
- c.connect( other_node.output_terminals[ x.output_name ],
- node.input_terminals[ k ] );
- c.redraw();
- });
- } else {
- var other_node = wf.nodes[ v.id ];
+ if ( ! $.isArray( v ) ) {
+ v = [ v ];
+ }
+ $.each( v, function( l, x ) {
+ var other_node = wf.nodes[ x.id ];
var c = new Connector();
- c.connect( other_node.output_terminals[ v.output_name ],
+ c.connect( other_node.output_terminals[ x.output_name ],
node.input_terminals[ k ] );
c.redraw();
- }
+ });
}
});
if(using_workflow_outputs && node.type === 'tool'){
https://bitbucket.org/galaxy/galaxy-central/commits/69ee2351526c/
Changeset: 69ee2351526c
User: jmchilton
Date: 2014-03-04 18:49:35
Summary: Eliminate code dup. in workflow editor for building input terminals.
Affected #: 1 file
diff -r ef7be94741451e43dca891603b3c06ebf06311a5 -r 69ee2351526c97d6a0d4016bfbb76cc8051a12f3 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -171,6 +171,11 @@
this.tool_errors = {};
}
$.extend( Node.prototype, {
+ new_input_terminal : function( input ) {
+ var t = $("<div class='terminal input-terminal'></div>");
+ this.enable_input_terminal( t, input.name, input.extensions, input.multiple );
+ return t;
+ },
enable_input_terminal : function( elements, name, types, multiple ) {
var node = this;
$(elements).each( function() {
@@ -317,8 +322,7 @@
b.find( "div" ).remove();
var ibox = $("<div class='inputs'></div>").appendTo( b );
$.each( data.data_inputs, function( i, input ) {
- var t = $("<div class='terminal input-terminal'></div>");
- node.enable_input_terminal( t, input.name, input.extensions, input.multiple );
+ var t = node.new_input_terminal( input );
var ib = $("<div class='form-row dataRow input-data-row' name='" + input.name + "'>" + input.label + "</div>" );
ib.css({ position:'absolute',
left: -1000,
@@ -420,8 +424,7 @@
var new_body = $("<div class='inputs'></div>");
var old = old_body.find( "div.input-data-row");
$.each( data.data_inputs, function( i, input ) {
- var t = $("<div class='terminal input-terminal'></div>");
- node.enable_input_terminal( t, input.name, input.extensions, input.multiple );
+ var t = node.new_input_terminal( input );
// If already connected save old connection
old_body.find( "div[name='" + input.name + "']" ).each( function() {
$(this).find( ".input-terminal" ).each( function() {
https://bitbucket.org/galaxy/galaxy-central/commits/36fa1ad1fc17/
Changeset: 36fa1ad1fc17
User: jmchilton
Date: 2014-03-04 18:49:35
Summary: Refactor out optional data selection handling.
Reused a few times downstream for dataset collections.
Affected #: 1 file
diff -r 69ee2351526c97d6a0d4016bfbb76cc8051a12f3 -r 36fa1ad1fc17939b68d10339a7cead7d21803a11 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -1644,18 +1644,7 @@
# Also collect children via association object
dataset_collector( hda.children, hid )
dataset_collector( history.active_datasets_children_and_roles, None )
-
- set_selected = field.get_selected( return_label=True, return_value=True, multi=False ) is not None
- # Ensure than an item is always selected
- if self.optional:
- if set_selected:
- field.add_option( "Selection is Optional", 'None', False )
- else:
- field.add_option( "Selection is Optional", 'None', True )
- elif not set_selected and bool( field.options ):
- # Select the last item
- a, b, c = field.options[-1]
- field.options[-1] = a, b, True
+ self._ensure_selection( field )
return field
def get_initial_value( self, trans, context, history=None ):
@@ -1835,6 +1824,19 @@
assert history is not None, "%s requires a history" % class_name
return history
+ def _ensure_selection( self, field ):
+ set_selected = field.get_selected( return_label=True, return_value=True, multi=False ) is not None
+ # Ensure than an item is always selected
+ if self.optional:
+ if set_selected:
+ field.add_option( "Selection is Optional", 'None', False )
+ else:
+ field.add_option( "Selection is Optional", 'None', True )
+ elif not set_selected and bool( field.options ):
+ # Select the last item
+ a, b, c = field.options[-1]
+ field.options[-1] = a, b, True
+
class HiddenDataToolParameter( HiddenToolParameter, DataToolParameter ):
"""
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: JS utils: add ajax queue and named ajax queue to allow processing async calls in order and/or prevent duplicate async calls
by commits-noreply@bitbucket.org 04 Mar '14
by commits-noreply@bitbucket.org 04 Mar '14
04 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bd2561df7d11/
Changeset: bd2561df7d11
User: carlfeberhard
Date: 2014-03-04 18:33:51
Summary: JS utils: add ajax queue and named ajax queue to allow processing async calls in order and/or prevent duplicate async calls
Affected #: 2 files
diff -r afac236cffd149aaa68dcf08f73903e109d14e33 -r bd2561df7d11308bd717cadd0158d26fbcf7e4dc static/scripts/packed/utils/ajax-queue.js
--- /dev/null
+++ b/static/scripts/packed/utils/ajax-queue.js
@@ -0,0 +1,1 @@
+define([],function(){function k(m){var l=this;l.deferred=jQuery.Deferred();l.queue=[];l.responses=[];l.numToProcess=0;l.running=false;l.init(m||[]);l.start();return l}k.prototype.init=function i(m){var l=this;m.forEach(function(n){l.add(n)})};k.prototype.add=function j(n){var l=this,m=this.queue.length;this.numToProcess+=1;this.queue.push(function(){var o=n();o.done(function(p){l.deferred.notify({curr:m,total:l.numToProcess,response:p})});o.always(function(p){l.responses.push(p);if(l.queue.length){l.queue.shift()()}else{l.stop()}})})};k.prototype.start=function b(){if(this.queue.length){this.running=true;this.queue.shift()()}};k.prototype.stop=function h(l,m){this.running=false;this.queue=[];if(l){this.deferred.reject(m)}else{this.deferred.resolve(this.responses)}return this};k.prototype.done=function f(l){return this.deferred.done(l)};k.prototype.fail=function d(l){return this.deferred.fail(l)};k.prototype.always=function e(l){return this.deferred.always(l)};k.prototype.progress=function a(l){return this.deferred.progress(l)};k.create=function g(l){return new AjaxQeueue(l).deferred};function c(m){var l=this;l.names={};k.call(this,m);return l}c.prototype=new k();c.prototype.constructor=c;c.prototype.add=function j(l){if(!(l.hasOwnProperty("name")&&l.hasOwnProperty("fn"))){throw new Error('NamedAjaxQueue.add requires an object with both "name" and "fn": '+JSON.stringify(l))}if(this.names.hasOwnProperty(l.name)){return}this.names[l.name]=true;k.prototype.add.call(this,l.fn)};c.create=function g(l){return new c(l).deferred};return{AjaxQueue:k,NamedAjaxQueue:c}});
\ No newline at end of file
diff -r afac236cffd149aaa68dcf08f73903e109d14e33 -r bd2561df7d11308bd717cadd0158d26fbcf7e4dc static/scripts/utils/ajax-queue.js
--- /dev/null
+++ b/static/scripts/utils/ajax-queue.js
@@ -0,0 +1,165 @@
+define([
+], function(){
+//ASSUMES: jquery
+//=============================================================================
+/** @class AjaxQueue
+ * Class that allows queueing functions that return jQuery promises (such
+ * as ajax calls). Each function waits for the previous to complete before
+ * being called
+ *
+ * @constructor accepts a list of functions and automatically begins
+ * processing them
+ */
+function AjaxQueue( initialFunctions ){
+ //TODO: possibly rename to DeferredQueue
+ var self = this;
+ /** the main deferred for the entire queue - note: also sends notifications of progress */
+ self.deferred = jQuery.Deferred();
+ /** the queue array of functions */
+ self.queue = [];
+ /** cache the response from each deferred call - error or success */
+ self.responses = [];
+ /** total number of fn's to process */
+ self.numToProcess = 0;
+ /** is the queue processing/waiting for any calls to return? */
+ self.running = false;
+
+ self.init( initialFunctions || [] );
+ self.start();
+
+ return self;
+}
+
+/** add all fns in initialFunctions (if any) to the queue */
+AjaxQueue.prototype.init = function init( initialFunctions ){
+ var self = this;
+ initialFunctions.forEach( function( fn ){
+ self.add( fn );
+ });
+};
+
+/** add a fn to the queue */
+AjaxQueue.prototype.add = function add( fn ){
+ //console.debug( 'AjaxQueue.prototype.add:', fn );
+ var self = this,
+ index = this.queue.length;
+ this.numToProcess += 1;
+
+ this.queue.push( function(){
+ var xhr = fn();
+ // if successful, notify using the deferred to allow tracking progress
+ xhr.done( function( response ){
+ self.deferred.notify({ curr: index, total: self.numToProcess, response: response });
+ });
+ // (regardless of previous error or success) if not last ajax call, shift and call the next
+ // if last fn, resolve deferred
+ xhr.always( function( response ){
+ self.responses.push( response );
+ if( self.queue.length ){
+ self.queue.shift()();
+ } else {
+ self.stop();
+ }
+ });
+ });
+};
+
+/** start processing the queue */
+AjaxQueue.prototype.start = function start(){
+ if( this.queue.length ){
+ this.running = true;
+ this.queue.shift()();
+ }
+};
+
+/** stop the queue
+ * @param {boolean} causeFail cause an error/fail on the main deferred
+ * @param {String} msg message to send when rejecting the main deferred
+ */
+AjaxQueue.prototype.stop = function stop( causeFail, msg ){
+ //TODO: doesn't abort current call
+ this.running = false;
+ this.queue = [];
+ if( causeFail ){
+ //TODO: spliced args instead
+ this.deferred.reject( msg );
+ } else {
+ this.deferred.resolve( this.responses );
+ }
+ return this;
+};
+
+// only a handful of the deferred interface for now - possible YAGNI
+/** implement done from the jq deferred interface */
+AjaxQueue.prototype.done = function done( fn ){
+ return this.deferred.done( fn );
+};
+/** implement fail from the jq deferred interface */
+AjaxQueue.prototype.fail = function fail( fn ){
+ return this.deferred.fail( fn );
+};
+/** implement always from the jq deferred interface */
+AjaxQueue.prototype.always = function always( fn ){
+ return this.deferred.always( fn );
+};
+/** implement progress from the jq deferred interface */
+AjaxQueue.prototype.progress = function progress( fn ){
+ return this.deferred.progress( fn );
+};
+
+/** shortcut constructor / fire and forget
+ * @returns {Deferred} the queue's main deferred
+ */
+AjaxQueue.create = function create( initialFunctions ){
+ return new AjaxQeueue( initialFunctions ).deferred;
+};
+
+
+//=============================================================================
+/** @class NamedAjaxQueue
+ * @augments AjaxQueue
+ * Allows associating a name with a deferring fn and prevents adding deferring
+ * fns if the name has already been used. Useful to prevent build up of duplicate
+ * async calls.
+ * Both the array initialFunctions sent to constructor and any added later with
+ * add() should be objects (NOT functions) of the form:
+ * { name: some unique id,
+ * fn: the deferring fn or ajax call }
+ */
+function NamedAjaxQueue( initialFunctions ){
+ var self = this;
+ self.names = {};
+ AjaxQueue.call( this, initialFunctions );
+ return self;
+}
+NamedAjaxQueue.prototype = new AjaxQueue();
+NamedAjaxQueue.prototype.constructor = NamedAjaxQueue;
+
+/** add the obj.fn to the queue if obj.name hasn't been used before */
+NamedAjaxQueue.prototype.add = function add( obj ){
+ //console.debug( 'NamedAjaxQueue.prototype.add:', obj );
+ if( !( obj.hasOwnProperty( 'name' ) && obj.hasOwnProperty( 'fn' ) ) ){
+ throw new Error( 'NamedAjaxQueue.add requires an object with both "name" and "fn": ' + JSON.stringify( obj ) );
+ }
+ if( this.names.hasOwnProperty( obj.name ) ){
+ //console.warn( 'name has been used:', obj.name );
+ return;
+ }
+ this.names[ obj.name ] = true;
+ AjaxQueue.prototype.add.call( this, obj.fn );
+};
+
+/** shortcut constructor / fire and forget
+ * @returns {Deferred} the queue's main deferred
+ */
+NamedAjaxQueue.create = function create( initialFunctions ){
+ return new NamedAjaxQueue( initialFunctions ).deferred;
+};
+
+
+//=============================================================================
+ return {
+ AjaxQueue : AjaxQueue,
+ NamedAjaxQueue : NamedAjaxQueue
+ };
+});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: History panel: allow override of toggle in toggle deleted/hidden, extract methods searchHdas and clearHdaSearch to allow js searching
by commits-noreply@bitbucket.org 04 Mar '14
by commits-noreply@bitbucket.org 04 Mar '14
04 Mar '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/afac236cffd1/
Changeset: afac236cffd1
User: carlfeberhard
Date: 2014-03-04 17:44:28
Summary: History panel: allow override of toggle in toggle deleted/hidden, extract methods searchHdas and clearHdaSearch to allow js searching
Affected #: 4 files
diff -r c8b0a7759ef65205df26a8b685cbb64d32ce3cc4 -r afac236cffd149aaa68dcf08f73903e109d14e33 static/scripts/mvc/history/readonly-history-panel.js
--- a/static/scripts/mvc/history/readonly-history-panel.js
+++ b/static/scripts/mvc/history/readonly-history-panel.js
@@ -635,8 +635,9 @@
* (2) re-rendering the history
* @returns {Boolean} new show_deleted setting
*/
- toggleShowDeleted : function(){
- this.storage.set( 'show_deleted', !this.storage.get( 'show_deleted' ) );
+ toggleShowDeleted : function( show ){
+ show = ( show !== undefined )?( show ):( !this.storage.get( 'show_deleted' ) );
+ this.storage.set( 'show_deleted', show );
this.renderHdas();
return this.storage.get( 'show_deleted' );
},
@@ -646,8 +647,9 @@
* (2) re-rendering the history
* @returns {Boolean} new show_hidden setting
*/
- toggleShowHidden : function(){
- this.storage.set( 'show_hidden', !this.storage.get( 'show_hidden' ) );
+ toggleShowHidden : function( show ){
+ show = ( show !== undefined )?( show ):( !this.storage.get( 'show_hidden' ) );
+ this.storage.set( 'show_hidden', show );
this.renderHdas();
return this.storage.get( 'show_hidden' );
},
@@ -664,17 +666,10 @@
var panel = this,
inputSelector = '.history-search-input';
- function onSearch( searchFor ){
- //console.debug( 'onSearch', searchFor, panel );
- panel.searchFor = searchFor;
- panel.filters = [ function( hda ){ return hda.matchesAll( panel.searchFor ); } ];
- panel.trigger( 'search:searching', searchFor, panel );
- panel.renderHdas();
- }
function onFirstSearch( searchFor ){
- //console.debug( 'onSearch', searchFor, panel );
+ //console.debug( 'onFirstSearch', searchFor, panel );
if( panel.model.hdas.haveDetails() ){
- onSearch( searchFor );
+ panel.searchHdas( searchFor );
return;
}
panel.$el.find( inputSelector ).searchInput( 'toggle-loading' );
@@ -683,24 +678,17 @@
panel.$el.find( inputSelector ).searchInput( 'toggle-loading' );
})
.done( function(){
- onSearch( searchFor );
+ panel.searchHdas( searchFor );
});
}
- function onSearchClear(){
- //console.debug( 'onSearchClear', panel );
- panel.searchFor = '';
- panel.filters = [];
- panel.trigger( 'search:clear', panel );
- panel.renderHdas();
- }
$where.searchInput({
initialVal : panel.searchFor,
name : 'history-search',
placeholder : 'search datasets',
classes : 'history-search',
onfirstsearch : onFirstSearch,
- onsearch : onSearch,
- onclear : onSearchClear
+ onsearch : _.bind( this.searchHdas, this ),
+ onclear : _.bind( this.clearHdaSearch, this )
});
return $where;
},
@@ -733,6 +721,28 @@
}
},
+ /** filter hda view list to those that contain the searchFor terms
+ * (see the search section in the HDA model for implementation of the actual searching)
+ */
+ searchHdas : function( searchFor ){
+ //note: assumes hda details are loaded
+ //console.debug( 'onSearch', searchFor, this );
+ var panel = this;
+ this.searchFor = searchFor;
+ this.filters = [ function( hda ){ return hda.matchesAll( panel.searchFor ); } ];
+ this.trigger( 'search:searching', searchFor, this );
+ this.renderHdas();
+ },
+
+ /** clear the search filters and show all views that are normally shown */
+ clearHdaSearch : function( searchFor ){
+ //console.debug( 'onSearchClear', this );
+ this.searchFor = '';
+ this.filters = [];
+ this.trigger( 'search:clear', this );
+ this.renderHdas();
+ },
+
// ........................................................................ loading indicator
/** hide the panel and display a loading indicator (in the panel's parent) when history model's are switched */
showLoadingIndicator : function( msg, speed, callback ){
diff -r c8b0a7759ef65205df26a8b685cbb64d32ce3cc4 -r afac236cffd149aaa68dcf08f73903e109d14e33 static/scripts/mvc/ui.js
--- a/static/scripts/mvc/ui.js
+++ b/static/scripts/mvc/ui.js
@@ -906,7 +906,6 @@
var $first = $( this[0] ),
button = $first.data( 'mode-button' );
- console.debug( 'first, button', $first, button );
if( !button ){
throw new Error( 'modeButton needs an options object or string name of a function' );
diff -r c8b0a7759ef65205df26a8b685cbb64d32ce3cc4 -r afac236cffd149aaa68dcf08f73903e109d14e33 static/scripts/packed/mvc/history/readonly-history-panel.js
--- a/static/scripts/packed/mvc/history/readonly-history-panel.js
+++ b/static/scripts/packed/mvc/history/readonly-history-panel.js
@@ -1,1 +1,1 @@
-define(["mvc/history/history-model","mvc/dataset/hda-base"],function(e,a){var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(f){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([f],[true])))},removeExpandedHda:function(f){this.save("expandedHdas",_.omit(this.get("expandedHdas"),f))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function c(f){if(!f){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+f)}return("history:"+f)};var b=Backbone.View.extend(LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",msgsSelector:".message-container",emptyMsgSelector:".empty-history-message",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(f){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.linkTarget=f.linkTarget||"_blank";this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searchFor="";this._setUpListeners();if(this.model){if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers()}if(f.onready){f.onready.call(this)}},_setUpListeners:function(){this.on("error",function(g,j,f,i,h){this.errorHandler(g,j,f,i,h)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}},errorHandler:function(h,k,g,j,i){var f=this._parseErrorMessage(h,k,g,j,i);if(k&&k.status===0&&k.readyState===0){}else{if(k&&k.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",f.message,f.details)})}else{this.displayMessage("error",f.message,f.details)}}}},_parseErrorMessage:function(i,m,h,l,k){var g=Galaxy.currUser,f={message:this._bePolite(l),details:{user:(g instanceof User)?(g.toJSON()):(g+""),source:(i instanceof Backbone.Model)?(i.toJSON()):(i+""),xhr:m,options:(m)?(_.omit(h,"xhr")):(h)}};_.extend(f.details,k||{});if(m&&_.isFunction(m.getAllResponseHeaders)){var j=m.getAllResponseHeaders();j=_.compact(j.split("\n"));j=_.map(j,function(n){return n.split(": ")});f.details.xhr.responseHeaders=_.object(j)}return f},_bePolite:function(f){f=f||_l("An error occurred while getting updates from the server");return f+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(i,h,g,k){var f=this,j=function(l){return f.getExpandedHdaIds(l.id)};return this.loadHistory(i,h,g,k,j)},loadHistory:function(i,h,g,l,j){this.trigger("loading-history",this);h=h||{};var f=this;var k=e.History.getHistoryData(i,{historyFn:g,hdaFn:l,hdaDetailIds:h.initiallyExpanded||j});return this._loadHistoryFromXHR(k,h).fail(function(o,m,n){f.trigger("error",f,o,h,_l("An error was encountered while "+m),{historyId:i,history:n||{}})}).always(function(){f.trigger("loading-done",f)})},_loadHistoryFromXHR:function(h,g){var f=this;h.then(function(i,j){f.setModel(i,j,g)});h.fail(function(j,i){f.render()});return h},setModel:function(h,f,g){g=g||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){h.user=Galaxy.currUser.toJSON()}this.model=new e.History(h,f,g);if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(g,f,h){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(g)){this.storage.set("exandedHdas",g)}if(_.isBoolean(f)){this.storage.set("show_deleted",f)}if(_.isBoolean(h)){this.storage.set("show_hidden",h)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var f in sessionStorage){if(f.indexOf("history:")===0){sessionStorage.removeItem(f)}}},getStoredOptions:function(g){if(!g||g==="current"){return(this.storage)?(this.storage.get()):({})}var f=sessionStorage.getItem(d.historyStorageKey(g));return(f===null)?({}):(JSON.parse(f))},getExpandedHdaIds:function(f){var g=this.getStoredOptions(f).expandedHdas;return((_.isEmpty(g))?([]):(_.keys(g)))},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(g,i,f,h){this.errorHandler(g,i,f,h)},this)},render:function(h,i){h=(h===undefined)?(this.fxSpeed):(h);var f=this,g;if(this.model){g=this.renderModel()}else{g=this.renderWithoutModel()}$(f).queue("fx",[function(j){if(h&&f.$el.is(":visible")){f.$el.fadeOut(h,j)}else{j()}},function(j){f.$el.empty();if(g){f.$el.append(g.children())}j()},function(j){if(h&&!f.$el.is(":visible")){f.$el.fadeIn(h,j)}else{j()}},function(j){if(i){i.call(this)}f.trigger("rendered",this);j()}]);return this},renderWithoutModel:function(){var f=$("<div/>"),g=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return f.append(g)},renderModel:function(){var f=$("<div/>");f.append(b.templates.historyPanel(this.model.toJSON()));f.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(f);this.renderHdas(f);return f},_renderSearchButton:function(f){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},createHdaView:function(g){var f=g.get("id"),h=new this.HDAViewClass({model:g,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[f],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(h);return h},_setUpHdaListeners:function(g){var f=this;g.on("body-expanded",function(h){f.storage.addExpandedHda(h)});g.on("body-collapsed",function(h){f.storage.removeExpandedHda(h)});g.on("error",function(i,k,h,j){f.errorHandler(i,k,h,j)})},renderHdas:function(g){g=g||this.$el;var f=this,i={},h=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);g.find(this.datasetsSelector).empty();if(h.length){h.each(function(k){var j=k.get("id"),l=f.createHdaView(k);i[j]=l;if(_.contains(f.selectedHdaIds,j)){l.selected=true}f.attachHdaView(l.render(),g)});g.find(this.emptyMsgSelector).hide()}else{g.find(this.emptyMsgSelector).text((this.model.hdas.length&&this.searchFor)?(this.noneFoundMsg):(this.emptyMsg)).show()}this.hdaViews=i;return this.hdaViews},attachHdaView:function(h,g){g=g||this.$el;var f=g.find(this.datasetsSelector);f.prepend(h.$el)},addHdaView:function(i){this.log("add."+this,i);var g=this;if(!i.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function h(k){var j=g.$el.find(g.emptyMsgSelector);if(j.is(":visible")){j.fadeOut(g.fxSpeed,k)}else{k()}},function f(k){g.scrollToTop();var j=g.$el.find(g.datasetsSelector),l=g.createHdaView(i);g.hdaViews[i.id]=l;l.render().$el.hide().prependTo(j).slideDown(g.fxSpeed)}])},refreshHdas:function(g,f){if(this.model){return this.model.refresh(g,f)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(f){f.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(){this.storage.set("show_deleted",!this.storage.get("show_deleted"));this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(){this.storage.set("show_hidden",!this.storage.get("show_hidden"));this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(g){var h=this,k=".history-search-input";function j(l){h.searchFor=l;h.filters=[function(m){return m.matchesAll(h.searchFor)}];h.trigger("search:searching",l,h);h.renderHdas()}function f(l){if(h.model.hdas.haveDetails()){j(l);return}h.$el.find(k).searchInput("toggle-loading");h.model.hdas.fetchAllDetails({silent:true}).always(function(){h.$el.find(k).searchInput("toggle-loading")}).done(function(){j(l)})}function i(){h.searchFor="";h.filters=[];h.trigger("search:clear",h);h.renderHdas()}g.searchInput({initialVal:h.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:f,onsearch:j,onclear:i});return g},showSearchControls:function(g){g=(g===undefined)?(this.fxSpeed):(g);var f=this.$el.find(".history-search-controls"),h=f.find(".history-search-input");if(!h.children().size()){this.setUpSearchInput(h)}f.slideDown(g,function(){$(this).find("input").focus()})},hideSearchControls:function(f){f=(f===undefined)?(this.fxSpeed):(f);this.$el.find(".history-search-controls").slideUp(f)},toggleSearchControls:function(f){speed=(jQuery.type(f)==="number")?(f):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},showLoadingIndicator:function(g,f,h){f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},hideLoadingIndicator:function(f,g){f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},displayMessage:function(k,l,j){var h=this;this.scrollToTop();var i=this.$el.find(this.msgsSelector),f=$("<div/>").addClass(k+"message").html(l);if(!_.isEmpty(j)){var g=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(h._messageToModalOptions(k,l,j));return false});f.append(" ",g)}return i.html(f)},_messageToModalOptions:function(j,l,i){var f=this,k=$("<div/>"),h={title:"Details"};function g(m){m=_.omit(m,_.functions(m));return["<table>",_.map(m,function(o,n){o=(_.isObject(o))?(g(o)):(o);return'<tr><td style="vertical-align: top; color: grey">'+n+'</td><td style="padding-left: 8px">'+o+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(i)){h.body=k.append(g(i))}else{h.body=k.html(i)}h.buttons={Ok:function(){Galaxy.modal.hide();f.clearMessages()}};return h},clearMessages:function(){var f=this.$el.find(this.msgsSelector);f.empty()},scrollPosition:function(){return this.$el.scrollTop()},scrollTo:function(f){this.$el.scrollTop(f);return this},scrollToTop:function(){this.$el.scrollTop(0);return this},scrollIntoView:function(k,g){if(g===undefined){this.scrollTo(k);return this}var f=window,j=this.$el.parent(),i=$(f).innerHeight(),h=(i/2)-(g/2);this.scrollTo(k-h);return this},scrollToId:function(g){if((!g)||(!this.hdaViews[g])){return this}var f=this.hdaViews[g].$el;this.scrollIntoView(f.offset().top,f.outerHeight());return this},scrollToHid:function(f){var g=this.model.hdas.getByHid(f);if(!g){return this}return this.scrollToId(g.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});b.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{ReadOnlyHistoryPanel:b}});
\ No newline at end of file
+define(["mvc/history/history-model","mvc/dataset/hda-base"],function(e,a){var d=SessionStorageModel.extend({defaults:{expandedHdas:{},show_deleted:false,show_hidden:false},addExpandedHda:function(f){this.save("expandedHdas",_.extend(this.get("expandedHdas"),_.object([f],[true])))},removeExpandedHda:function(f){this.save("expandedHdas",_.omit(this.get("expandedHdas"),f))},toString:function(){return"HistoryPrefs("+this.id+")"}});d.historyStorageKey=function c(f){if(!f){throw new Error("HistoryPrefs.historyStorageKey needs valid id: "+f)}return("history:"+f)};var b=Backbone.View.extend(LoggableMixin).extend({HDAViewClass:a.HDABaseView,tagName:"div",className:"history-panel",fxSpeed:"fast",datasetsSelector:".datasets-list",msgsSelector:".message-container",emptyMsgSelector:".empty-history-message",emptyMsg:_l("This history is empty"),noneFoundMsg:_l("No matching datasets found"),initialize:function(f){f=f||{};if(f.logger){this.logger=f.logger}this.log(this+".initialize:",f);this.linkTarget=f.linkTarget||"_blank";this.fxSpeed=_.has(f,"fxSpeed")?(f.fxSpeed):(this.fxSpeed);this.hdaViews={};this.indicator=new LoadingIndicator(this.$el);this.filters=[];this.searchFor="";this._setUpListeners();if(this.model){if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(f.initiallyExpanded,f.show_deleted,f.show_hidden);this._setUpModelEventHandlers()}if(f.onready){f.onready.call(this)}},_setUpListeners:function(){this.on("error",function(g,j,f,i,h){this.errorHandler(g,j,f,i,h)});this.on("loading-history",function(){this.showLoadingIndicator("loading history...",40)});this.on("loading-done",function(){this.hideLoadingIndicator(40);if(_.isEmpty(this.hdaViews)){this.trigger("empty-history",this)}});this.once("rendered",function(){this.trigger("rendered:initial",this);return false});if(this.logger){this.on("all",function(f){this.log(this+"",arguments)},this)}},errorHandler:function(h,k,g,j,i){var f=this._parseErrorMessage(h,k,g,j,i);if(k&&k.status===0&&k.readyState===0){}else{if(k&&k.status===502){}else{if(!this.$el.find(this.msgsSelector).is(":visible")){this.once("rendered",function(){this.displayMessage("error",f.message,f.details)})}else{this.displayMessage("error",f.message,f.details)}}}},_parseErrorMessage:function(i,m,h,l,k){var g=Galaxy.currUser,f={message:this._bePolite(l),details:{user:(g instanceof User)?(g.toJSON()):(g+""),source:(i instanceof Backbone.Model)?(i.toJSON()):(i+""),xhr:m,options:(m)?(_.omit(h,"xhr")):(h)}};_.extend(f.details,k||{});if(m&&_.isFunction(m.getAllResponseHeaders)){var j=m.getAllResponseHeaders();j=_.compact(j.split("\n"));j=_.map(j,function(n){return n.split(": ")});f.details.xhr.responseHeaders=_.object(j)}return f},_bePolite:function(f){f=f||_l("An error occurred while getting updates from the server");return f+". "+_l("Please contact a Galaxy administrator if the problem persists.")},loadHistoryWithHDADetails:function(i,h,g,k){var f=this,j=function(l){return f.getExpandedHdaIds(l.id)};return this.loadHistory(i,h,g,k,j)},loadHistory:function(i,h,g,l,j){this.trigger("loading-history",this);h=h||{};var f=this;var k=e.History.getHistoryData(i,{historyFn:g,hdaFn:l,hdaDetailIds:h.initiallyExpanded||j});return this._loadHistoryFromXHR(k,h).fail(function(o,m,n){f.trigger("error",f,o,h,_l("An error was encountered while "+m),{historyId:i,history:n||{}})}).always(function(){f.trigger("loading-done",f)})},_loadHistoryFromXHR:function(h,g){var f=this;h.then(function(i,j){f.setModel(i,j,g)});h.fail(function(j,i){f.render()});return h},setModel:function(h,f,g){g=g||{};if(this.model){this.model.clearUpdateTimeout();this.stopListening(this.model);this.stopListening(this.model.hdas)}this.hdaViews={};if(Galaxy&&Galaxy.currUser){h.user=Galaxy.currUser.toJSON()}this.model=new e.History(h,f,g);if(this.logger){this.model.logger=this.logger}this._setUpWebStorage(g.initiallyExpanded,g.show_deleted,g.show_hidden);this._setUpModelEventHandlers();this.selectedHdaIds=[];this.trigger("new-model",this);this.render();return this},_setUpWebStorage:function(g,f,h){this.storage=new d({id:d.historyStorageKey(this.model.get("id"))});if(_.isObject(g)){this.storage.set("exandedHdas",g)}if(_.isBoolean(f)){this.storage.set("show_deleted",f)}if(_.isBoolean(h)){this.storage.set("show_hidden",h)}this.trigger("new-storage",this.storage,this);this.log(this+" (init'd) storage:",this.storage.get())},clearWebStorage:function(){for(var f in sessionStorage){if(f.indexOf("history:")===0){sessionStorage.removeItem(f)}}},getStoredOptions:function(g){if(!g||g==="current"){return(this.storage)?(this.storage.get()):({})}var f=sessionStorage.getItem(d.historyStorageKey(g));return(f===null)?({}):(JSON.parse(f))},getExpandedHdaIds:function(f){var g=this.getStoredOptions(f).expandedHdas;return((_.isEmpty(g))?([]):(_.keys(g)))},_setUpModelEventHandlers:function(){this.model.hdas.on("add",this.addHdaView,this);this.model.on("error error:hdas",function(g,i,f,h){this.errorHandler(g,i,f,h)},this)},render:function(h,i){h=(h===undefined)?(this.fxSpeed):(h);var f=this,g;if(this.model){g=this.renderModel()}else{g=this.renderWithoutModel()}$(f).queue("fx",[function(j){if(h&&f.$el.is(":visible")){f.$el.fadeOut(h,j)}else{j()}},function(j){f.$el.empty();if(g){f.$el.append(g.children())}j()},function(j){if(h&&!f.$el.is(":visible")){f.$el.fadeIn(h,j)}else{j()}},function(j){if(i){i.call(this)}f.trigger("rendered",this);j()}]);return this},renderWithoutModel:function(){var f=$("<div/>"),g=$("<div/>").addClass("message-container").css({"margin-left":"4px","margin-right":"4px"});return f.append(g)},renderModel:function(){var f=$("<div/>");f.append(b.templates.historyPanel(this.model.toJSON()));f.find(".history-secondary-actions").prepend(this._renderSearchButton());this._setUpBehaviours(f);this.renderHdas(f);return f},_renderSearchButton:function(f){return faIconButton({title:_l("Search datasets"),classes:"history-search-btn",faIcon:"fa-search"})},_setUpBehaviours:function(f){f=f||this.$el;f.find("[title]").tooltip({placement:"bottom"})},createHdaView:function(g){var f=g.get("id"),h=new this.HDAViewClass({model:g,linkTarget:this.linkTarget,expanded:this.storage.get("expandedHdas")[f],hasUser:this.model.ownedByCurrUser(),logger:this.logger});this._setUpHdaListeners(h);return h},_setUpHdaListeners:function(g){var f=this;g.on("body-expanded",function(h){f.storage.addExpandedHda(h)});g.on("body-collapsed",function(h){f.storage.removeExpandedHda(h)});g.on("error",function(i,k,h,j){f.errorHandler(i,k,h,j)})},renderHdas:function(g){g=g||this.$el;var f=this,i={},h=this.model.hdas.getVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"),this.filters);g.find(this.datasetsSelector).empty();if(h.length){h.each(function(k){var j=k.get("id"),l=f.createHdaView(k);i[j]=l;if(_.contains(f.selectedHdaIds,j)){l.selected=true}f.attachHdaView(l.render(),g)});g.find(this.emptyMsgSelector).hide()}else{g.find(this.emptyMsgSelector).text((this.model.hdas.length&&this.searchFor)?(this.noneFoundMsg):(this.emptyMsg)).show()}this.hdaViews=i;return this.hdaViews},attachHdaView:function(h,g){g=g||this.$el;var f=g.find(this.datasetsSelector);f.prepend(h.$el)},addHdaView:function(i){this.log("add."+this,i);var g=this;if(!i.isVisible(this.storage.get("show_deleted"),this.storage.get("show_hidden"))){return}$({}).queue([function h(k){var j=g.$el.find(g.emptyMsgSelector);if(j.is(":visible")){j.fadeOut(g.fxSpeed,k)}else{k()}},function f(k){g.scrollToTop();var j=g.$el.find(g.datasetsSelector),l=g.createHdaView(i);g.hdaViews[i.id]=l;l.render().$el.hide().prependTo(j).slideDown(g.fxSpeed)}])},refreshHdas:function(g,f){if(this.model){return this.model.refresh(g,f)}return $.when()},events:{"click .message-container":"clearMessages","click .history-search-btn":"toggleSearchControls"},collapseAllHdaBodies:function(){_.each(this.hdaViews,function(f){f.toggleBodyVisibility(null,false)});this.storage.set("expandedHdas",{})},toggleShowDeleted:function(f){f=(f!==undefined)?(f):(!this.storage.get("show_deleted"));this.storage.set("show_deleted",f);this.renderHdas();return this.storage.get("show_deleted")},toggleShowHidden:function(f){f=(f!==undefined)?(f):(!this.storage.get("show_hidden"));this.storage.set("show_hidden",f);this.renderHdas();return this.storage.get("show_hidden")},setUpSearchInput:function(g){var h=this,i=".history-search-input";function f(j){if(h.model.hdas.haveDetails()){h.searchHdas(j);return}h.$el.find(i).searchInput("toggle-loading");h.model.hdas.fetchAllDetails({silent:true}).always(function(){h.$el.find(i).searchInput("toggle-loading")}).done(function(){h.searchHdas(j)})}g.searchInput({initialVal:h.searchFor,name:"history-search",placeholder:"search datasets",classes:"history-search",onfirstsearch:f,onsearch:_.bind(this.searchHdas,this),onclear:_.bind(this.clearHdaSearch,this)});return g},showSearchControls:function(g){g=(g===undefined)?(this.fxSpeed):(g);var f=this.$el.find(".history-search-controls"),h=f.find(".history-search-input");if(!h.children().size()){this.setUpSearchInput(h)}f.slideDown(g,function(){$(this).find("input").focus()})},hideSearchControls:function(f){f=(f===undefined)?(this.fxSpeed):(f);this.$el.find(".history-search-controls").slideUp(f)},toggleSearchControls:function(f){speed=(jQuery.type(f)==="number")?(f):(this.fxSpeed);if(this.$el.find(".history-search-controls").is(":visible")){this.hideSearchControls(speed)}else{this.showSearchControls(speed)}},searchHdas:function(f){var g=this;this.searchFor=f;this.filters=[function(h){return h.matchesAll(g.searchFor)}];this.trigger("search:searching",f,this);this.renderHdas()},clearHdaSearch:function(f){this.searchFor="";this.filters=[];this.trigger("search:clear",this);this.renderHdas()},showLoadingIndicator:function(g,f,h){f=(f!==undefined)?(f):(this.fxSpeed);if(!this.indicator){this.indicator=new LoadingIndicator(this.$el,this.$el.parent())}if(!this.$el.is(":visible")){this.indicator.show(0,h)}else{this.$el.fadeOut(f);this.indicator.show(g,f,h)}},hideLoadingIndicator:function(f,g){f=(f!==undefined)?(f):(this.fxSpeed);if(this.indicator){this.indicator.hide(f,g)}},displayMessage:function(k,l,j){var h=this;this.scrollToTop();var i=this.$el.find(this.msgsSelector),f=$("<div/>").addClass(k+"message").html(l);if(!_.isEmpty(j)){var g=$('<a href="javascript:void(0)">Details</a>').click(function(){Galaxy.modal.show(h._messageToModalOptions(k,l,j));return false});f.append(" ",g)}return i.html(f)},_messageToModalOptions:function(j,l,i){var f=this,k=$("<div/>"),h={title:"Details"};function g(m){m=_.omit(m,_.functions(m));return["<table>",_.map(m,function(o,n){o=(_.isObject(o))?(g(o)):(o);return'<tr><td style="vertical-align: top; color: grey">'+n+'</td><td style="padding-left: 8px">'+o+"</td></tr>"}).join(""),"</table>"].join("")}if(_.isObject(i)){h.body=k.append(g(i))}else{h.body=k.html(i)}h.buttons={Ok:function(){Galaxy.modal.hide();f.clearMessages()}};return h},clearMessages:function(){var f=this.$el.find(this.msgsSelector);f.empty()},scrollPosition:function(){return this.$el.scrollTop()},scrollTo:function(f){this.$el.scrollTop(f);return this},scrollToTop:function(){this.$el.scrollTop(0);return this},scrollIntoView:function(k,g){if(g===undefined){this.scrollTo(k);return this}var f=window,j=this.$el.parent(),i=$(f).innerHeight(),h=(i/2)-(g/2);this.scrollTo(k-h);return this},scrollToId:function(g){if((!g)||(!this.hdaViews[g])){return this}var f=this.hdaViews[g].$el;this.scrollIntoView(f.offset().top,f.outerHeight());return this},scrollToHid:function(f){var g=this.model.hdas.getByHid(f);if(!g){return this}return this.scrollToId(g.id)},toString:function(){return"ReadOnlyHistoryPanel("+((this.model)?(this.model.get("name")):(""))+")"}});b.templates={historyPanel:Handlebars.templates["template-history-historyPanel"]};return{ReadOnlyHistoryPanel:b}});
\ No newline at end of file
diff -r c8b0a7759ef65205df26a8b685cbb64d32ce3cc4 -r afac236cffd149aaa68dcf08f73903e109d14e33 static/scripts/packed/mvc/ui.js
--- a/static/scripts/packed/mvc/ui.js
+++ b/static/scripts/packed/mvc/ui.js
@@ -1,1 +1,1 @@
-var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=jQuery.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&jQuery.type(o==="function")){return o.call(this.$element.get(0))}return undefined};jQuery.fn.extend({modeButton:function k(n){if(!this.size()){return this}if(jQuery.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");console.debug("first, button",p,o);if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&jQuery.type(n)==="string"){var q=n;if(o&&jQuery.type(o[q])==="function"){return o[q].apply(o,jQuery.makeArray(arguments).slice(1))}}return o}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}());
\ No newline at end of file
+var IconButton=Backbone.Model.extend({defaults:{title:"",icon_class:"",on_click:null,menu_options:null,is_menu_button:true,id:null,href:null,target:null,enabled:true,visible:true,tooltip_config:{}}});var IconButtonView=Backbone.View.extend({initialize:function(){this.model.attributes.tooltip_config={placement:"bottom"};this.model.bind("change",this.render,this)},render:function(){this.$el.tooltip("hide");var a=this.template(this.model.toJSON());a.tooltip(this.model.get("tooltip_config"));this.$el.replaceWith(a);this.setElement(a);return this},events:{click:"click"},click:function(a){if(_.isFunction(this.model.get("on_click"))){this.model.get("on_click")(a);return false}return true},template:function(b){var a='title="'+b.title+'" class="icon-button';if(b.is_menu_button){a+=" menu-button"}a+=" "+b.icon_class;if(!b.enabled){a+="_disabled"}a+='"';if(b.id){a+=' id="'+b.id+'"'}a+=' href="'+b.href+'"';if(b.target){a+=' target="'+b.target+'"'}if(!b.visible){a+=' style="display: none;"'}if(b.enabled){a="<a "+a+"/>"}else{a="<span "+a+"/>"}return $(a)}});var IconButtonCollection=Backbone.Collection.extend({model:IconButton});var IconButtonMenuView=Backbone.View.extend({tagName:"div",initialize:function(){this.render()},render:function(){var a=this;this.collection.each(function(d){var b=$("<a/>").attr("href","javascript:void(0)").attr("title",d.attributes.title).addClass("icon-button menu-button").addClass(d.attributes.icon_class).appendTo(a.$el).click(d.attributes.on_click);if(d.attributes.tooltip_config){b.tooltip(d.attributes.tooltip_config)}var c=d.get("options");if(c){make_popupmenu(b,c)}});return this}});var create_icon_buttons_menu=function(b,a){if(!a){a={}}var c=new IconButtonCollection(_.map(b,function(d){return new IconButton(_.extend(d,a))}));return new IconButtonMenuView({collection:c})};var Grid=Backbone.Collection.extend({});var GridView=Backbone.View.extend({});var PopupMenu=Backbone.View.extend({initialize:function(b,a){this.$button=b;if(!this.$button.size()){this.$button=$("<div/>")}this.options=a||[];var c=this;this.$button.click(function(d){$(".popmenu-wrapper").remove();c._renderAndShow(d);return false})},_renderAndShow:function(a){this.render();this.$el.appendTo("body").css(this._getShownPosition(a)).show();this._setUpCloseBehavior()},render:function(){this.$el.addClass("popmenu-wrapper").hide().css({position:"absolute"}).html(this.template(this.$button.attr("id"),this.options));if(this.options.length){var a=this;this.$el.find("li").each(function(c,b){var d=a.options[c];if(d.func){$(this).children("a.popupmenu-option").click(function(e){d.func.call(a,e,d)})}})}return this},template:function(b,a){return['<ul id="',b,'-menu" class="dropdown-menu">',this._templateOptions(a),"</ul>"].join("")},_templateOptions:function(a){if(!a.length){return"<li>(no options)</li>"}return _.map(a,function(d){if(d.divider){return'<li class="divider"></li>'}else{if(d.header){return['<li class="head"><a href="javascript:void(0);">',d.html,"</a></li>"].join("")}}var c=d.href||"javascript:void(0);",e=(d.target)?(' target="'+d.target+'"'):(""),b=(d.checked)?('<span class="fa fa-check"></span>'):("");return['<li><a class="popupmenu-option" href="',c,'"',e,">",b,d.html,"</a></li>"].join("")}).join("")},_getShownPosition:function(b){var c=this.$el.width();var a=b.pageX-c/2;a=Math.min(a,$(document).scrollLeft()+$(window).width()-c-5);a=Math.max(a,$(document).scrollLeft()+5);return{top:b.pageY,left:a}},_setUpCloseBehavior:function(){var c=this;function a(e){$(document).off("click.close_popup");if(window.parent!==window){try{$(window.parent.document).off("click.close_popup")}catch(d){}}else{try{$("iframe#galaxy_main").contents().off("click.close_popup")}catch(d){}}c.remove()}$("html").one("click.close_popup",a);if(window.parent!==window){try{$(window.parent.document).find("html").one("click.close_popup",a)}catch(b){}}else{try{$("iframe#galaxy_main").contents().one("click.close_popup",a)}catch(b){}}},addItem:function(b,a){a=(a>=0)?a:this.options.length;this.options.splice(a,0,b);return this},removeItem:function(a){if(a>=0){this.options.splice(a,1)}return this},findIndexByHtml:function(b){for(var a=0;a<this.options.length;a++){if(_.has(this.options[a],"html")&&(this.options[a].html===b)){return a}}return null},findItemByHtml:function(a){return this.options[(this.findIndexByHtml(a))]},toString:function(){return"PopupMenu"}});PopupMenu.create=function _create(b,a){return new PopupMenu(b,a)};PopupMenu.make_popupmenu=function(b,c){var a=[];_.each(c,function(f,d){var e={html:d};if(f===null){e.header=true}else{if(jQuery.type(f)==="function"){e.func=f}}a.push(e)});return new PopupMenu($(b),a)};PopupMenu.convertLinksToOptions=function(c,a){c=$(c);a=a||"a";var b=[];c.find(a).each(function(g,e){var f={},d=$(g);f.html=d.text();if(d.attr("href")){var j=d.attr("href"),k=d.attr("target"),h=d.attr("confirm");f.func=function(){if((h)&&(!confirm(h))){return}switch(k){case"_parent":window.parent.location=j;break;case"_top":window.top.location=j;break;default:window.location=j}}}b.push(f)});return b};PopupMenu.fromExistingDom=function(d,c,a){d=$(d);c=$(c);var b=PopupMenu.convertLinksToOptions(c,a);c.remove();return new PopupMenu(d,b)};PopupMenu.make_popup_menus=function(c,b,d){c=c||document;b=b||"div[popupmenu]";d=d||function(e,f){return"#"+e.attr("popupmenu")};var a=[];$(c).find(b).each(function(){var e=$(this),f=$(c).find(d(e,c));a.push(PopupMenu.fromDom(f,e));f.addClass("popup")});return a};var faIconButton=function(a){a=a||{};a.tooltipConfig=a.tooltipConfig||{placement:"bottom"};a.classes=["icon-btn"].concat(a.classes||[]);if(a.disabled){a.classes.push("disabled")}var b=['<a class="',a.classes.join(" "),'"',((a.title)?(' title="'+a.title+'"'):("")),((!a.disabled&&a.target)?(' target="'+a.target+'"'):("")),' href="',((!a.disabled&&a.href)?(a.href):("javascript:void(0);")),'">','<span class="fa ',a.faIcon,'"></span>',"</a>"].join("");var c=$(b).tooltip(a.tooltipConfig);if(_.isFunction(a.onclick)){c.click(a.onclick)}return c};function LoadingIndicator(a,c){var b=this;c=jQuery.extend({cover:false},c||{});function d(){var e=['<div class="loading-indicator">','<div class="loading-indicator-text">','<span class="fa fa-spinner fa-spin fa-lg"></span>','<span class="loading-indicator-message">loading...</span>',"</div>","</div>"].join("\n");var g=$(e).hide().css(c.css||{position:"fixed"}),f=g.children(".loading-indicator-text");if(c.cover){g.css({"z-index":2,top:a.css("top"),bottom:a.css("bottom"),left:a.css("left"),right:a.css("right"),opacity:0.5,"background-color":"white","text-align":"center"});f=g.children(".loading-indicator-text").css({"margin-top":"20px"})}else{f=g.children(".loading-indicator-text").css({margin:"12px 0px 0px 10px",opacity:"0.85",color:"grey"});f.children(".loading-indicator-message").css({margin:"0px 8px 0px 0px","font-style":"italic"})}return g}b.show=function(f,e,g){f=f||"loading...";e=e||"fast";b.$indicator=d().insertBefore(a);b.message(f);b.$indicator.fadeIn(e,g);return b};b.message=function(e){b.$indicator.find("i").text(e)};b.hide=function(e,f){e=e||"fast";if(b.$indicator&&b.$indicator.size()){b.$indicator.fadeOut(e,function(){b.$indicator.remove();if(f){f()}})}else{if(f){f()}}return b};return b}(function(){function a(j,p){var d=27,m=13,c=$(j),e=true,g={initialVal:"",name:"search",placeholder:"search",classes:"",onclear:function(){},onfirstsearch:null,onsearch:function(q){},minSearchLen:0,escWillClear:true,oninit:function(){}};function i(q){var r=$(this).parent().children("input");r.val("");r.trigger("clear:searchInput");p.onclear()}function o(r,q){$(this).trigger("search:searchInput",q);if(typeof p.onfirstsearch==="function"&&e){e=false;p.onfirstsearch(q)}else{p.onsearch(q)}}function f(){return['<input type="text" name="',p.name,'" placeholder="',p.placeholder,'" ','class="search-query ',p.classes,'" ',"/>"].join("")}function l(){return $(f()).focus(function(q){$(this).select()}).keyup(function(r){if(r.which===d&&p.escWillClear){i.call(this,r)}else{var q=$(this).val();if((r.which===m)||(p.minSearchLen&&q.length>=p.minSearchLen)){o.call(this,r,q)}else{if(!q.length){i.call(this,r)}}}}).val(p.initialVal)}function k(){return $(['<span class="search-clear fa fa-times-circle" ','title="',_l("clear search (esc)"),'"></span>'].join("")).tooltip({placement:"bottom"}).click(function(q){i.call(this,q)})}function n(){return $(['<span class="search-loading fa fa-spinner fa-spin" ','title="',_l("loading..."),'"></span>'].join("")).hide().tooltip({placement:"bottom"})}function h(){c.find(".search-loading").toggle();c.find(".search-clear").toggle()}if(jQuery.type(p)==="string"){if(p==="toggle-loading"){h()}return c}if(jQuery.type(p)==="object"){p=jQuery.extend(true,{},g,p)}return c.addClass("search-input").prepend([l(),k(),n()])}jQuery.fn.extend({searchInput:function b(c){return this.each(function(){return a(this,c)})}})}());(function(){function c(o,n){this.currModeIndex=0;return this._init(o,n)}c.prototype.DATA_KEY="mode-button";c.prototype.defaults={switchModesOnClick:true};c.prototype._init=function j(o,n){n=n||{};this.$element=$(o);this.options=jQuery.extend(true,{},this.defaults,n);if(!n.modes){throw new Error('ModeButton requires a "modes" array')}var q=this;this.$element.click(function p(r){q.callModeFn();if(q.options.switchModesOnClick){q._incModeIndex()}$(this).html(q.options.modes[q.currModeIndex].html)});return this.reset()};c.prototype._incModeIndex=function l(){this.currModeIndex+=1;if(this.currModeIndex>=this.options.modes.length){this.currModeIndex=0}return this};c.prototype._getModeIndex=function f(n){for(var o=0;o<this.options.modes.length;o+=1){if(this.options.modes[o].mode===n){return o}}throw new Error("mode not found: "+n)};c.prototype._setModeByIndex=function m(n){var o=this.options.modes[n];if(!o){throw new Error("mode index not found: "+n)}this.currModeIndex=n;if(o.html){this.$element.html(o.html)}return this};c.prototype.currentMode=function d(){return this.options.modes[this.currModeIndex]};c.prototype.current=function i(){return this.currentMode().mode};c.prototype.getMode=function g(n){if(!n){return this.currentMode()}return this.options.modes[(this._getModeIndex(n))]};c.prototype.hasMode=function b(n){try{return !!this.getMode(n)}catch(o){}return false};c.prototype.setMode=function a(n){return this._setModeByIndex(this._getModeIndex(n))};c.prototype.reset=function h(){this.currModeIndex=0;if(this.options.initialMode){this.currModeIndex=this._getModeIndex(this.options.initialMode)}return this._setModeByIndex(this.currModeIndex)};c.prototype.callModeFn=function e(n){var o=this.getMode(n).onclick;if(o&&jQuery.type(o==="function")){return o.call(this.$element.get(0))}return undefined};jQuery.fn.extend({modeButton:function k(n){if(!this.size()){return this}if(jQuery.type(n)==="object"){return this.map(function(){var r=$(this);r.data("mode-button",new c(r,n));return this})}var p=$(this[0]),o=p.data("mode-button");if(!o){throw new Error("modeButton needs an options object or string name of a function")}if(o&&jQuery.type(n)==="string"){var q=n;if(o&&jQuery.type(o[q])==="function"){return o[q].apply(o,jQuery.makeArray(arguments).slice(1))}}return o}})}());function dropDownSelect(b,c){c=c||((!_.isEmpty(b))?(b[0]):(""));var a=$(['<div class="dropdown-select btn-group">','<button type="button" class="btn btn-default">','<span class="dropdown-select-selected">'+c+"</span>","</button>","</div>"].join("\n"));if(b&&b.length>1){a.find("button").addClass("dropdown-toggle").attr("data-toggle","dropdown").append(' <span class="caret"></span>');a.append(['<ul class="dropdown-menu" role="menu">',_.map(b,function(e){return['<li><a href="javascript:void(0)">',e,"</a></li>"].join("")}).join("\n"),"</ul>"].join("\n"))}function d(g){var h=$(this),f=h.parents(".dropdown-select"),e=h.text();f.find(".dropdown-select-selected").text(e);f.trigger("change.dropdown-select",e)}a.find("a").click(d);return a}(function(){function e(k,j){return this.init(k,j)}e.prototype.DATA_KEY="filter-control";e.prototype.init=function g(k,j){j=j||{filters:[]};this.$element=$(k).addClass("filter-control btn-group");this.options=jQuery.extend(true,{},this.defaults,j);this.currFilter=this.options.filters[0];return this.render()};e.prototype.render=function d(){this.$element.empty().append([this._renderKeySelect(),this._renderOpSelect(),this._renderValueInput()]);return this};e.prototype._renderKeySelect=function a(){var j=this;var k=this.options.filters.map(function(l){return l.key});this.$keySelect=dropDownSelect(k,this.currFilter.key).addClass("filter-control-key").on("change.dropdown-select",function(m,l){j.currFilter=_.findWhere(j.options.filters,{key:l});j.render()._triggerChange()});return this.$keySelect};e.prototype._renderOpSelect=function i(){var j=this,k=this.currFilter.ops;this.$opSelect=dropDownSelect(k,k[0]).addClass("filter-control-op").on("change.dropdown-select",function(m,l){j._triggerChange()});return this.$opSelect};e.prototype._renderValueInput=function c(){var j=this;if(this.currFilter.values){this.$valueSelect=dropDownSelect(this.currFilter.values,this.currFilter.values[0]).on("change.dropdown-select",function(l,k){j._triggerChange()})}else{this.$valueSelect=$("<input/>").addClass("form-control").on("change",function(k,l){j._triggerChange()})}this.$valueSelect.addClass("filter-control-value");return this.$valueSelect};e.prototype.val=function b(){var k=this.$element.find(".filter-control-key .dropdown-select-selected").text(),m=this.$element.find(".filter-control-op .dropdown-select-selected").text(),j=this.$element.find(".filter-control-value"),l=(j.hasClass("dropdown-select"))?(j.find(".dropdown-select-selected").text()):(j.val());return{key:k,op:m,value:l}};e.prototype._triggerChange=function h(){this.$element.trigger("change.filter-control",this.val())};jQuery.fn.extend({filterControl:function f(k){var j=jQuery.makeArray(arguments).slice(1);return this.map(function(){var n=$(this),m=n.data(e.prototype.DATA_KEY);if(jQuery.type(k)==="object"){m=new e(n,k);n.data(e.prototype.DATA_KEY,m)}if(m&&jQuery.type(k)==="string"){var l=m[k];if(jQuery.type(l)==="function"){return l.apply(m,j)}}return this})}})}());(function(){function i(o,n){this.numPages=null;this.currPage=0;return this.init(o,n)}i.prototype.DATA_KEY="pagination";i.prototype.defaults={startingPage:0,perPage:20,totalDataSize:null,currDataSize:null};i.prototype.init=function g(n,o){o=o||{};this.$element=n;this.options=jQuery.extend(true,{},this.defaults,o);this.currPage=this.options.startingPage;if(this.options.totalDataSize!==null){this.numPages=Math.ceil(this.options.totalDataSize/this.options.perPage);if(this.currPage>=this.numPages){this.currPage=this.numPages-1}}this.$element.data(i.prototype.DATA_KEY,this);this._render();return this};function m(n){return $(['<li><a href="javascript:void(0);">',n,"</a></li>"].join(""))}i.prototype._render=function e(){if(this.options.totalDataSize===0){return this}if(this.numPages===1){return this}if(this.numPages>0){this._renderPages();this._scrollToActivePage()}else{this._renderPrevNext()}return this};i.prototype._renderPrevNext=function b(){var o=this,p=m("Prev"),n=m("Next"),q=$("<ul/>").addClass("pagination pagination-prev-next");if(this.currPage===0){p.addClass("disabled")}else{p.click(function(){o.prevPage()})}if((this.numPages&&this.currPage===(this.numPages-1))||(this.options.currDataSize&&this.options.currDataSize<this.options.perPage)){n.addClass("disabled")}else{n.click(function(){o.nextPage()})}this.$element.html(q.append([p,n]));return this.$element};i.prototype._renderPages=function a(){var n=this,q=$("<div>").addClass("pagination-scroll-container"),s=$("<ul/>").addClass("pagination pagination-page-list"),r=function(t){n.goToPage($(this).data("page"))};for(var o=0;o<this.numPages;o+=1){var p=m(o+1).attr("data-page",o).click(r);if(o===this.currPage){p.addClass("active")}s.append(p)}return this.$element.html(q.html(s))};i.prototype._scrollToActivePage=function l(){var p=this.$element.find(".pagination-scroll-container");if(!p.size()){return this}var o=this.$element.find("li.active"),n=p.width()/2;p.scrollLeft(p.scrollLeft()+o.position().left-n);return this};i.prototype.goToPage=function j(n){if(n<=0){n=0}if(this.numPages&&n>=this.numPages){n=this.numPages-1}if(n===this.currPage){return this}this.currPage=n;this.$element.trigger("pagination.page-change",this.currPage);this._render();return this};i.prototype.prevPage=function c(){return this.goToPage(this.currPage-1)};i.prototype.nextPage=function h(){return this.goToPage(this.currPage+1)};i.prototype.page=function f(){return this.currPage};i.create=function k(n,o){return new i(n,o)};jQuery.fn.extend({pagination:function d(o){var n=jQuery.makeArray(arguments).slice(1);if(jQuery.type(o)==="object"){return this.map(function(){i.create($(this),o);return this})}var q=$(this[0]),r=q.data(i.prototype.DATA_KEY);if(r){if(jQuery.type(o)==="string"){var p=r[o];if(jQuery.type(p)==="function"){return p.apply(r,n)}}else{return r}}return undefined}})}());(function(){var g={renameColumns:false,columnNames:[],commentChar:"#",hideCommentRows:false,includePrompts:true,topLeftContent:"Columns:"},s="peek-control.change",t="peek-control.rename",l="peek-control",v="control",f="control-prompt",c="selected",n="disabled",u="button",q="renamable-header",p="column-index",a="column-name";function i(w){if(w.disabled&&jQuery.type(w.disabled)!=="array"){throw new Error('"disabled" must be defined as an array of indeces: '+JSON.stringify(w))}if(w.multiselect&&w.selected&&jQuery.type(w.selected)!=="array"){throw new Error('Mulitselect rows need an array for "selected": '+JSON.stringify(w))}if(!w.label||!w.id){throw new Error("Peek controls need a label and id for each control row: "+JSON.stringify(w))}if(w.disabled&&w.disabled.indexOf(w.selected)!==-1){throw new Error("Selected column is in the list of disabled columns: "+JSON.stringify(w))}return w}function o(x,w){return $("<div/>").addClass(u).text(x.label)}function k(x,w){var y=$("<td/>").html(o(x,w)).attr("data-"+p,w);if(x.disabled&&x.disabled.indexOf(w)!==-1){y.addClass(n)}return y}function e(y,z,w){var x=y.children("."+u);if(y.hasClass(c)){x.html((z.selectedText!==undefined)?(z.selectedText):(z.label))}else{x.html((z.unselectedText!==undefined)?(z.unselectedText):(z.label))}}function h(z,x){var y=k(z,x);if(z.selected===x){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);if(!E.hasClass(c)){var A=E.parent().children("."+c).removeClass(c);A.each(function(){e($(this),z,x)});E.addClass(c);e(E,z,x);var C={},B=E.parent().attr("id"),F=E.data(p);C[B]=F;E.parents(".peek").trigger(s,C)}})}return y}function m(z,x){var y=k(z,x);if(z.selected&&z.selected.indexOf(x)!==-1){y.addClass(c)}e(y,z,x);if(!y.hasClass(n)){y.click(function w(D){var E=$(this);E.toggleClass(c);e(E,z,x);var C=E.parent().find("."+c).map(function(G,H){return $(H).data(p)});var B={},A=E.parent().attr("id"),F=jQuery.makeArray(C);B[A]=F;E.parents(".peek").trigger(s,B)})}return y}function j(y,z){var w=[];for(var x=0;x<y;x+=1){w.push(z.multiselect?m(z,x):h(z,x))}return w}function r(y,z,x){var A=$("<tr/>").attr("id",z.id).addClass(v);if(x){var w=$("<td/>").addClass(f).text(z.label+":");A.append(w)}A.append(j(y,z));return A}function b(E){E=jQuery.extend(true,{},g,E);var D=$(this).addClass(l),A=D.find("table"),z=A.find("th").size(),C=A.find("tr").size(),w=A.find("td[colspan]").map(function(H,F){var G=$(this);if(G.text()&&G.text().match(new RegExp("^"+E.commentChar))){return $(this).css("color","grey").parent().get(0)}return null});if(E.hideCommentRows){w.hide();C-=w.size()}if(E.includePrompts){var y=$("<th/>").addClass("top-left").text(E.topLeftContent).attr("rowspan",C);A.find("tr").first().prepend(y)}var B=A.find("th:not(.top-left)").each(function(G,I){var H=$(this),J=H.text().replace(/^\d+\.*/,""),F=E.columnNames[G]||J;H.attr("data-"+a,F).text((G+1)+((F)?("."+F):("")))});if(E.renameColumns){B.addClass(q).click(function x(){var G=$(this),F=G.index()+(E.includePrompts?0:1),I=G.data(a),H=prompt("New column name:",I);if(H!==null&&H!==I){G.text(F+(H?("."+H):"")).data(a,H).attr("data-",a,H);var J=jQuery.makeArray(G.parent().children("th:not(.top-left)").map(function(){return $(this).data(a)}));G.parents(".peek").trigger(t,J)}})}E.controls.forEach(function(G,F){i(G);var H=r(z,G,E.includePrompts);A.find("tbody").append(H)});return this}jQuery.fn.extend({peekControl:function d(w){return this.map(function(){return b.call(this,w)})}})}());
\ 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