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: Api: Ftp files return empty list instead of raising error if directory is missing
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d404a6f6d01e/
Changeset: d404a6f6d01e
User: guerler
Date: 2014-10-16 23:47:55+00:00
Summary: Api: Ftp files return empty list instead of raising error if directory is missing
Affected #: 1 file
diff -r eb28a9bcb4d9ca99613b667300095ce8a52f7ae3 -r d404a6f6d01e6af5cbd35a427c474cee47fe963a lib/galaxy/webapps/galaxy/api/ftp_files.py
--- a/lib/galaxy/webapps/galaxy/api/ftp_files.py
+++ b/lib/galaxy/webapps/galaxy/api/ftp_files.py
@@ -112,8 +112,7 @@
response.append( dict( path = path,
size = statinfo.st_size,
ctime = time.strftime( "%m/%d/%Y %I:%M:%S %p", time.localtime( statinfo.st_ctime ) ) ) )
- else:
- raise exceptions.ConfigDoesNotAllowException( 'The given directory does not exist.' )
+
# sort by path
response = sorted(response, key=itemgetter("path"))
return response
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: dannon: Tool's command might be separated by a newline, so we should use the general form split here, not specifically on spaces. Pointed out by @kellrott.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/eb28a9bcb4d9/
Changeset: eb28a9bcb4d9
User: dannon
Date: 2014-10-16 23:37:30+00:00
Summary: Tool's command might be separated by a newline, so we should use the general form split here, not specifically on spaces. Pointed out by @kellrott.
Affected #: 1 file
diff -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 -r eb28a9bcb4d9ca99613b667300095ce8a52f7ae3 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -699,7 +699,7 @@
def load_tooldir_tag_set(self, sub_elem, elems, tool_path, integrated_elems, load_panel_dict):
directory = os.path.join( tool_path, sub_elem.attrib.get("dir") )
- recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
+ recursive = string_as_bool( sub_elem.attrib.get("recursive", True) )
self.__watch_directory( directory, elems, integrated_elems, load_panel_dict, recursive )
def __watch_directory( self, directory, elems, integrated_elems, load_panel_dict, recursive):
@@ -825,7 +825,7 @@
tool_tup = ( os.path.abspath( tool.config_file ), os.path.split( tool.config_file )[-1] )
tarball_files.append( tool_tup )
# TODO: This feels hacky.
- tool_command = tool.command.strip().split( ' ' )[0]
+ tool_command = tool.command.strip().split()[0]
tool_path = os.path.dirname( os.path.abspath( tool.config_file ) )
# Add the tool XML to the tuple that will be used to populate the tarball.
if os.path.exists( os.path.join( tool_path, tool_command ) ):
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: jgoecks: Fix Circster background bug in Firefox by correctly specifying colors.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/d09b44c5f228/
Changeset: d09b44c5f228
User: jgoecks
Date: 2014-10-16 18:15:50+00:00
Summary: Fix Circster background bug in Firefox by correctly specifying colors.
Affected #: 3 files
diff -r 70c404e681a0f4c347eaca75d65f23a11edcb823 -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 client/galaxy/scripts/viz/circster.js
--- a/client/galaxy/scripts/viz/circster.js
+++ b/client/galaxy/scripts/viz/circster.js
@@ -404,11 +404,11 @@
/* ----------------------- Public Methods ------------------------- */
initialize: function(options) {
- this.bg_stroke = 'ddd';
+ this.bg_stroke = '#ddd';
// Fill color when loading data.
- this.loading_bg_fill = 'ffc';
+ this.loading_bg_fill = '#ffc';
// Fill color when data has been loaded.
- this.bg_fill = 'ddd';
+ this.bg_fill = '#ddd';
this.total_gap = options.total_gap;
this.track = options.track;
this.radius_bounds = options.radius_bounds;
@@ -688,8 +688,8 @@
// Use a single arc for rendering data.
this.innerRadius = this.radius_bounds[0];
this.radius_bounds[0] = this.radius_bounds[1];
- this.bg_stroke = 'fff';
- this.bg_fill = 'fff';
+ this.bg_stroke = '#fff';
+ this.bg_fill = '#fff';
// Minimum arc distance for labels to be applied.
this.min_arc_len = 0.05;
diff -r 70c404e681a0f4c347eaca75d65f23a11edcb823 -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 static/scripts/packed/viz/circster.js
--- a/static/scripts/packed/viz/circster.js
+++ b/static/scripts/packed/viz/circster.js
@@ -1,1 +1,1 @@
-require(["utils/utils","libs/farbtastic",],function(a){a.cssLoadFile("static/style/circster.css")});define(["libs/underscore","libs/d3","viz/visualization","utils/config"],function(h,m,j,c){var n=Backbone.Model.extend({is_visible:function(r,o){var p=r.getBoundingClientRect(),q=$("svg")[0].getBoundingClientRect();if(p.right<0||p.left>q.right||p.bottom<0||p.top>q.bottom){return false}return true}});var i={drawTicks:function(s,r,w,q,o){var v=s.append("g").selectAll("g").data(r).enter().append("g").selectAll("g").data(w).enter().append("g").attr("class","tick").attr("transform",function(x){return"rotate("+(x.angle*180/Math.PI-90)+")translate("+x.radius+",0)"});var u=[],t=[],p=function(x){return x.angle>Math.PI?"end":null};if(o){u=[0,0,0,-4];t=[4,0,"",".35em"];p=null}else{u=[1,0,4,0];t=[0,4,".35em",""]}v.append("line").attr("x1",u[0]).attr("y1",u[1]).attr("x2",u[2]).attr("y1",u[3]).style("stroke","#000");return v.append("text").attr("x",t[0]).attr("y",t[1]).attr("dx",t[2]).attr("dy",t[3]).attr("text-anchor",p).attr("transform",q).text(function(x){return x.label})},formatNum:function(p,o){if(o===undefined){o=2}if(p===null){return null}var r=null;if(Math.abs(p)<1){r=p.toPrecision(o)}else{var q=Math.round(p.toPrecision(o));p=Math.abs(p);if(p<1000){r=q}else{if(p<1000000){r=Math.round((q/1000).toPrecision(3)).toFixed(0)+"K"}else{if(p<1000000000){r=Math.round((q/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return r}};var d=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(o){this.genome=o.genome;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("drawables").on("add",this.add_track,this);this.model.get("drawables").on("remove",this.remove_track,this);var p=this.model.get("config");p.get("arc_dataset_height").on("change:value",this.update_track_bounds,this);p.get("track_gap").on("change:value",this.update_track_bounds,this)},get_circular_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var q=this.get_circular_tracks(),s=this.model.get("config").get_value("arc_dataset_height"),r=this.model.get("config").get_value("track_gap"),o=Math.min(this.$el.width(),this.$el.height())-20,u=o/2-q.length*(s+r)+r-this.label_arc_height,t=m.range(u,o/2,s+r);var p=this;return h.map(t,function(v){return[v,v+s]})},render:function(){var x=this,o=x.$el.width(),w=x.$el.height(),t=this.get_circular_tracks(),r=this.get_chord_tracks(),q=x.model.get("config").get_value("total_gap"),s=this.get_tracks_bounds(),p=m.select(x.$el[0]).append("svg").attr("width",o).attr("height",w).attr("pointer-events","all").append("svg:g").call(m.behavior.zoom().on("zoom",function(){var y=m.event.scale;p.attr("transform","translate("+m.event.translate+") scale("+y+")");if(x.scale!==y){if(x.zoom_drag_timeout){clearTimeout(x.zoom_drag_timeout)}x.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+o/2+","+w/2+")").append("svg:g").attr("class","tracks");this.circular_views=t.map(function(z,A){var y=new e({el:p.append("g")[0],track:z,radius_bounds:s[A],genome:x.genome,total_gap:q});y.render();return y});this.chords_views=r.map(function(z){var y=new k({el:p.append("g")[0],track:z,radius_bounds:s[0],genome:x.genome,total_gap:q});y.render();return y});var v=this.circular_views[this.circular_views.length-1].radius_bounds[1],u=[v,v+this.label_arc_height];this.label_track_view=new b({el:p.append("g")[0],track:new d(),radius_bounds:u,genome:x.genome,total_gap:q});this.label_track_view.render()},add_track:function(u){var p=this.model.get("config").get_value("total_gap");if(u.get("track_type")==="DiagonalHeatmapTrack"){var q=this.circular_views[0].radius_bounds,t=new k({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:q,genome:this.genome,total_gap:p});t.render();this.chords_views.push(t)}else{var s=this.get_tracks_bounds();h.each(this.circular_views,function(v,w){v.update_radius_bounds(s[w])});h.each(this.chords_views,function(v){v.update_radius_bounds(s[0])});var r=this.circular_views.length,o=new e({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:s[r],genome:this.genome,total_gap:p});o.render();this.circular_views.push(o)}},remove_track:function(p,r,q){var o=this.circular_views[q.index];this.circular_views.splice(q.index,1);o.$el.remove();var s=this.get_tracks_bounds();h.each(this.circular_views,function(t,u){t.update_radius_bounds(s[u])})},update_track_bounds:function(){var o=this.get_tracks_bounds();h.each(this.circular_views,function(p,q){p.update_radius_bounds(o[q])});h.each(this.chords_views,function(p){p.update_radius_bounds(o[0])})}});var l=Backbone.View.extend({tagName:"g",initialize:function(o){this.bg_stroke="ddd";this.loading_bg_fill="ffc";this.bg_fill="ddd";this.total_gap=o.total_gap;this.track=o.track;this.radius_bounds=o.radius_bounds;this.genome=o.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=m.select(this.$el[0])},get_fill_color:function(){var o=this.track.get("config").get_value("block_color");if(!o){o=this.track.get("config").get_value("color")}return o},render:function(){var s=this.parent_elt;var r=this.chroms_layout,u=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),o=s.selectAll("g").data(r).enter().append("svg:g"),q=o.append("path").attr("d",u).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);q.append("title").text(function(w){return w.data.chrom});var p=this,t=p.track.get("data_manager"),v=(t?t.data_is_ready():true);$.when(v).then(function(){$.when(p._render_data(s)).then(function(){q.style("fill",p.bg_fill);p.render_labels()})})},render_labels:function(){},update_radius_bounds:function(p){this.radius_bounds=p;var o=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",o);this._transition_chrom_data();this._transition_labels()},update_scale:function(r){var q=this.scale;this.scale=r;if(r<=q){return}var p=this,o=new n();this.parent_elt.selectAll("path.chrom-data").filter(function(t,s){return o.is_visible(this)}).each(function(y,u){var x=m.select(this),t=x.attr("chrom"),w=p.genome.get_chrom_region(t),v=p.track.get("data_manager"),s;if(!v.can_get_more_detailed_data(w)){return}s=p.track.get("data_manager").get_more_detailed_data(w,"Coverage",0,r);$.when(s).then(function(B){x.remove();p._update_data_bounds();var A=h.find(p.chroms_layout,function(C){return C.data.chrom===t});var z=p.get_fill_color();p._render_chrom_data(p.parent_elt,A,B).style("stroke",z).style("fill",z)})});return p},_transition_chrom_data:function(){var p=this.track,r=this.chroms_layout,o=this.parent_elt.selectAll("g>path.chrom-data"),s=o[0].length;if(s>0){var q=this;$.when(p.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){var u=h.reject(h.map(v,function(w,x){var y=null,z=q._get_path_function(r[x],w);if(z){y=z(w.data)}return y}),function(w){return w===null});var t=p.get("config").get_value("color");o.each(function(x,w){m.select(this).transition().duration(1000).style("stroke",t).style("fill",t).attr("d",u[w])})})}},_transition_labels:function(){},_update_data_bounds:function(p){var o=this.data_bounds;this.data_bounds=p||this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));this._transition_chrom_data()},_render_data:function(r){var q=this,p=this.chroms_layout,o=this.track,s=$.Deferred();$.when(o.get("data_manager").get_genome_wide_data(this.genome)).then(function(u){q.data_bounds=q.get_data_bounds(u);o.get("config").set_value("min_value",q.data_bounds[0],{silent:true});o.get("config").set_value("max_value",q.data_bounds[1],{silent:true});layout_and_data=h.zip(p,u),chroms_data_layout=h.map(layout_and_data,function(v){var w=v[0],x=v[1];return q._render_chrom_data(r,w,x)});var t=q.get_fill_color();q.parent_elt.selectAll("path.chrom-data").style("stroke",t).style("fill",t);s.resolve(r)});return s},_render_chrom_data:function(o,p,q){},_get_path_function:function(p,o){},_chroms_layout:function(){var p=this.genome.get_chroms_info(),r=m.layout.pie().value(function(t){return t.len}).sort(null),s=r(p),o=2*Math.PI*this.total_gap/p.length,q=h.map(s,function(v,u){var t=v.endAngle-o;v.endAngle=(t>v.startAngle?t:v.startAngle);return v});return q}});var b=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="fff";this.bg_fill="fff";this.min_arc_len=0.05},_render_data:function(q){var p=this,o=q.selectAll("g");o.selectAll("path").attr("id",function(u){return"label-"+u.data.chrom});o.append("svg:text").filter(function(u){return u.endAngle-u.startAngle>p.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("class","chrom-label").attr("xlink:href",function(u){return"#label-"+u.data.chrom}).attr("startOffset","25%").text(function(u){return u.data.chrom});var r=function(w){var u=(w.endAngle-w.startAngle)/w.value,v=m.range(0,w.value,25000000).map(function(x,y){return{radius:p.innerRadius,angle:x*u+w.startAngle,label:y===0?0:(y%3?null:p.formatNum(x))}});if(v.length<4){v[v.length-1].label=p.formatNum(Math.round((v[v.length-1].angle-w.startAngle)/u))}return v};var t=function(u){return u.angle>Math.PI?"rotate(180)translate(-16)":null};var s=h.filter(this.chroms_layout,function(u){return u.endAngle-u.startAngle>p.min_arc_len});this.drawTicks(this.parent_elt,s,r,t)}});h.extend(b.prototype,i);var g=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);var p=this.track.get("config");p.get("min_value").on("change:value",this._update_min_max,this);p.get("max_value").on("change:value",this._update_min_max,this);p.get("color").on("change:value",this._transition_chrom_data,this)},_update_min_max:function(){var p=this.track.get("config"),o=[p.get_value("min_value"),p.get_value("max_value")];this._update_data_bounds(o);this.parent_elt.selectAll(".min_max").text(function(r,q){return o[q]})},_quantile:function(p,o){p.sort(m.ascending);return m.quantile(p,o)},_render_chrom_data:function(o,r,p){var s=this._get_path_function(r,p);if(!s){return null}var q=o.datum(p.data),t=q.append("path").attr("class","chrom-data").attr("chrom",r.data.chrom).attr("d",s);return t},_get_path_function:function(r,q){if(typeof q==="string"||!q.data||q.data.length===0){return null}var o=m.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var s=m.scale.linear().domain([0,q.data.length]).range([r.startAngle,r.endAngle]);var p=m.svg.line.radial().interpolate("linear").radius(function(t){return o(t[1])}).angle(function(u,t){return s(t)});return m.svg.area.radial().interpolate(p.interpolate()).innerRadius(o(0)).outerRadius(p.radius()).angle(p.angle())},render_labels:function(){var o=this,q=function(){return"rotate(90)"};var p=this.drawTicks(this.parent_elt,[this.chroms_layout[0]],this._data_bounds_ticks_fn(),q,true).classed("min_max",true);h.each(p,function(r){$(r).click(function(){var s=new c.ConfigSettingCollectionView({collection:o.track.get("config")});s.render_in_modal("Configure Track")})})},_transition_labels:function(){if(this.data_bounds.length===0){return}var p=this,r=h.filter(this.chroms_layout,function(s){return s.endAngle-s.startAngle>0.08}),q=h.filter(r,function(t,s){return s%3===0}),o=h.flatten(h.map(q,function(s){return p._data_bounds_ticks_fn()(s)}));this.parent_elt.selectAll("g.tick").data(o).transition().attr("transform",function(s){return"rotate("+(s.angle*180/Math.PI-90)+")translate("+s.radius+",0)"})},_data_bounds_ticks_fn:function(){var o=this;visibleChroms=0;return function(p){return[{radius:o.radius_bounds[0],angle:p.startAngle,label:o.formatNum(o.data_bounds[0])},{radius:o.radius_bounds[1],angle:p.startAngle,label:o.formatNum(o.data_bounds[1])}]}},get_data_bounds:function(o){}});h.extend(g.prototype,i);var e=g.extend({get_data_bounds:function(p){var o=h.flatten(h.map(p,function(q){if(q){return h.map(q.data,function(r){return parseInt(r[1],10)||0})}else{return 0}}));return[h.min(o),this._quantile(o,0.98)||h.max(o)]}});var k=l.extend({render:function(){var o=this;$.when(o.track.get("data_manager").data_is_ready()).then(function(){$.when(o.track.get("data_manager").get_genome_wide_data(o.genome)).then(function(r){var q=[],p=o.genome.get_chroms_info();h.each(r,function(v,u){var s=p[u].chrom;var t=h.map(v.data,function(x){var w=o._get_region_angle(s,x[1]),y=o._get_region_angle(x[3],x[4]);return{source:{startAngle:w,endAngle:w+0.01},target:{startAngle:y,endAngle:y+0.01}}});q=q.concat(t)});o.parent_elt.append("g").attr("class","chord").selectAll("path").data(q).enter().append("path").style("fill",o.get_fill_color()).attr("d",m.svg.chord().radius(o.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(o){this.radius_bounds=o;this.parent_elt.selectAll("path").transition().attr("d",m.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(q,o){var p=h.find(this.chroms_layout,function(r){return r.data.chrom===q});return p.endAngle-((p.endAngle-p.startAngle)*(p.data.len-o)/p.data.len)}});var f=Backbone.View.extend({initialize:function(){var o=new j.Genome(galaxy_config.app.genome),p=new j.GenomeVisualization(galaxy_config.app.viz_config);p.get("config").add([{key:"arc_dataset_height",label:"Arc Dataset Height",type:"int",value:25,view:"circster"},{key:"track_gap",label:"Gap Between Tracks",type:"int",value:5,view:"circster"},{key:"total_gap",label:"Gap [0-1]",type:"float",value:0.4,view:"circster",hidden:true}]);var r=new a({el:$("#center .unified-panel-body"),genome:o,model:p});r.render();$("#center .unified-panel-header-inner").append(galaxy_config.app.viz_config.title+" "+galaxy_config.app.viz_config.dbkey);var q=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){j.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",p.get("dbkey"),function(s){p.add_tracks(s)})}},{icon_class:"gear",title:"Settings",on_click:function(){var s=new c.ConfigSettingCollectionView({collection:p.get("config")});s.render_in_modal("Configure Visualization")}},{icon_class:"disk--arrow",title:"Save",on_click:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});$.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:p.get("vis_id"),title:p.get("title"),dbkey:p.get("dbkey"),type:"trackster",vis_json:JSON.stringify(p)}}).success(function(s){Galaxy.modal.hide();p.set("vis_id",s.vis_id)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=galaxy_config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});q.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(q.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:f}});
\ No newline at end of file
+require(["utils/utils","libs/farbtastic",],function(a){a.cssLoadFile("static/style/circster.css")});define(["libs/underscore","libs/d3","viz/visualization","utils/config"],function(h,m,j,c){var n=Backbone.Model.extend({is_visible:function(r,o){var p=r.getBoundingClientRect(),q=$("svg")[0].getBoundingClientRect();if(p.right<0||p.left>q.right||p.bottom<0||p.top>q.bottom){return false}return true}});var i={drawTicks:function(s,r,w,q,o){var v=s.append("g").selectAll("g").data(r).enter().append("g").selectAll("g").data(w).enter().append("g").attr("class","tick").attr("transform",function(x){return"rotate("+(x.angle*180/Math.PI-90)+")translate("+x.radius+",0)"});var u=[],t=[],p=function(x){return x.angle>Math.PI?"end":null};if(o){u=[0,0,0,-4];t=[4,0,"",".35em"];p=null}else{u=[1,0,4,0];t=[0,4,".35em",""]}v.append("line").attr("x1",u[0]).attr("y1",u[1]).attr("x2",u[2]).attr("y1",u[3]).style("stroke","#000");return v.append("text").attr("x",t[0]).attr("y",t[1]).attr("dx",t[2]).attr("dy",t[3]).attr("text-anchor",p).attr("transform",q).text(function(x){return x.label})},formatNum:function(p,o){if(o===undefined){o=2}if(p===null){return null}var r=null;if(Math.abs(p)<1){r=p.toPrecision(o)}else{var q=Math.round(p.toPrecision(o));p=Math.abs(p);if(p<1000){r=q}else{if(p<1000000){r=Math.round((q/1000).toPrecision(3)).toFixed(0)+"K"}else{if(p<1000000000){r=Math.round((q/1000000).toPrecision(3)).toFixed(0)+"M"}}}}return r}};var d=Backbone.Model.extend({});var a=Backbone.View.extend({className:"circster",initialize:function(o){this.genome=o.genome;this.label_arc_height=50;this.scale=1;this.circular_views=null;this.chords_views=null;this.model.get("drawables").on("add",this.add_track,this);this.model.get("drawables").on("remove",this.remove_track,this);var p=this.model.get("config");p.get("arc_dataset_height").on("change:value",this.update_track_bounds,this);p.get("track_gap").on("change:value",this.update_track_bounds,this)},get_circular_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")!=="DiagonalHeatmapTrack"})},get_chord_tracks:function(){return this.model.get("drawables").filter(function(o){return o.get("track_type")==="DiagonalHeatmapTrack"})},get_tracks_bounds:function(){var q=this.get_circular_tracks(),s=this.model.get("config").get_value("arc_dataset_height"),r=this.model.get("config").get_value("track_gap"),o=Math.min(this.$el.width(),this.$el.height())-20,u=o/2-q.length*(s+r)+r-this.label_arc_height,t=m.range(u,o/2,s+r);var p=this;return h.map(t,function(v){return[v,v+s]})},render:function(){var x=this,o=x.$el.width(),w=x.$el.height(),t=this.get_circular_tracks(),r=this.get_chord_tracks(),q=x.model.get("config").get_value("total_gap"),s=this.get_tracks_bounds(),p=m.select(x.$el[0]).append("svg").attr("width",o).attr("height",w).attr("pointer-events","all").append("svg:g").call(m.behavior.zoom().on("zoom",function(){var y=m.event.scale;p.attr("transform","translate("+m.event.translate+") scale("+y+")");if(x.scale!==y){if(x.zoom_drag_timeout){clearTimeout(x.zoom_drag_timeout)}x.zoom_drag_timeout=setTimeout(function(){},400)}})).attr("transform","translate("+o/2+","+w/2+")").append("svg:g").attr("class","tracks");this.circular_views=t.map(function(z,A){var y=new e({el:p.append("g")[0],track:z,radius_bounds:s[A],genome:x.genome,total_gap:q});y.render();return y});this.chords_views=r.map(function(z){var y=new k({el:p.append("g")[0],track:z,radius_bounds:s[0],genome:x.genome,total_gap:q});y.render();return y});var v=this.circular_views[this.circular_views.length-1].radius_bounds[1],u=[v,v+this.label_arc_height];this.label_track_view=new b({el:p.append("g")[0],track:new d(),radius_bounds:u,genome:x.genome,total_gap:q});this.label_track_view.render()},add_track:function(u){var p=this.model.get("config").get_value("total_gap");if(u.get("track_type")==="DiagonalHeatmapTrack"){var q=this.circular_views[0].radius_bounds,t=new k({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:q,genome:this.genome,total_gap:p});t.render();this.chords_views.push(t)}else{var s=this.get_tracks_bounds();h.each(this.circular_views,function(v,w){v.update_radius_bounds(s[w])});h.each(this.chords_views,function(v){v.update_radius_bounds(s[0])});var r=this.circular_views.length,o=new e({el:m.select("g.tracks").append("g")[0],track:u,radius_bounds:s[r],genome:this.genome,total_gap:p});o.render();this.circular_views.push(o)}},remove_track:function(p,r,q){var o=this.circular_views[q.index];this.circular_views.splice(q.index,1);o.$el.remove();var s=this.get_tracks_bounds();h.each(this.circular_views,function(t,u){t.update_radius_bounds(s[u])})},update_track_bounds:function(){var o=this.get_tracks_bounds();h.each(this.circular_views,function(p,q){p.update_radius_bounds(o[q])});h.each(this.chords_views,function(p){p.update_radius_bounds(o[0])})}});var l=Backbone.View.extend({tagName:"g",initialize:function(o){this.bg_stroke="#ddd";this.loading_bg_fill="#ffc";this.bg_fill="#ddd";this.total_gap=o.total_gap;this.track=o.track;this.radius_bounds=o.radius_bounds;this.genome=o.genome;this.chroms_layout=this._chroms_layout();this.data_bounds=[];this.scale=1;this.parent_elt=m.select(this.$el[0])},get_fill_color:function(){var o=this.track.get("config").get_value("block_color");if(!o){o=this.track.get("config").get_value("color")}return o},render:function(){var s=this.parent_elt;var r=this.chroms_layout,u=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]),o=s.selectAll("g").data(r).enter().append("svg:g"),q=o.append("path").attr("d",u).attr("class","chrom-background").style("stroke",this.bg_stroke).style("fill",this.loading_bg_fill);q.append("title").text(function(w){return w.data.chrom});var p=this,t=p.track.get("data_manager"),v=(t?t.data_is_ready():true);$.when(v).then(function(){$.when(p._render_data(s)).then(function(){q.style("fill",p.bg_fill);p.render_labels()})})},render_labels:function(){},update_radius_bounds:function(p){this.radius_bounds=p;var o=m.svg.arc().innerRadius(this.radius_bounds[0]).outerRadius(this.radius_bounds[1]);this.parent_elt.selectAll("g>path.chrom-background").transition().duration(1000).attr("d",o);this._transition_chrom_data();this._transition_labels()},update_scale:function(r){var q=this.scale;this.scale=r;if(r<=q){return}var p=this,o=new n();this.parent_elt.selectAll("path.chrom-data").filter(function(t,s){return o.is_visible(this)}).each(function(y,u){var x=m.select(this),t=x.attr("chrom"),w=p.genome.get_chrom_region(t),v=p.track.get("data_manager"),s;if(!v.can_get_more_detailed_data(w)){return}s=p.track.get("data_manager").get_more_detailed_data(w,"Coverage",0,r);$.when(s).then(function(B){x.remove();p._update_data_bounds();var A=h.find(p.chroms_layout,function(C){return C.data.chrom===t});var z=p.get_fill_color();p._render_chrom_data(p.parent_elt,A,B).style("stroke",z).style("fill",z)})});return p},_transition_chrom_data:function(){var p=this.track,r=this.chroms_layout,o=this.parent_elt.selectAll("g>path.chrom-data"),s=o[0].length;if(s>0){var q=this;$.when(p.get("data_manager").get_genome_wide_data(this.genome)).then(function(v){var u=h.reject(h.map(v,function(w,x){var y=null,z=q._get_path_function(r[x],w);if(z){y=z(w.data)}return y}),function(w){return w===null});var t=p.get("config").get_value("color");o.each(function(x,w){m.select(this).transition().duration(1000).style("stroke",t).style("fill",t).attr("d",u[w])})})}},_transition_labels:function(){},_update_data_bounds:function(p){var o=this.data_bounds;this.data_bounds=p||this.get_data_bounds(this.track.get("data_manager").get_genome_wide_data(this.genome));this._transition_chrom_data()},_render_data:function(r){var q=this,p=this.chroms_layout,o=this.track,s=$.Deferred();$.when(o.get("data_manager").get_genome_wide_data(this.genome)).then(function(u){q.data_bounds=q.get_data_bounds(u);o.get("config").set_value("min_value",q.data_bounds[0],{silent:true});o.get("config").set_value("max_value",q.data_bounds[1],{silent:true});layout_and_data=h.zip(p,u),chroms_data_layout=h.map(layout_and_data,function(v){var w=v[0],x=v[1];return q._render_chrom_data(r,w,x)});var t=q.get_fill_color();q.parent_elt.selectAll("path.chrom-data").style("stroke",t).style("fill",t);s.resolve(r)});return s},_render_chrom_data:function(o,p,q){},_get_path_function:function(p,o){},_chroms_layout:function(){var p=this.genome.get_chroms_info(),r=m.layout.pie().value(function(t){return t.len}).sort(null),s=r(p),o=2*Math.PI*this.total_gap/p.length,q=h.map(s,function(v,u){var t=v.endAngle-o;v.endAngle=(t>v.startAngle?t:v.startAngle);return v});return q}});var b=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);this.innerRadius=this.radius_bounds[0];this.radius_bounds[0]=this.radius_bounds[1];this.bg_stroke="#fff";this.bg_fill="#fff";this.min_arc_len=0.05},_render_data:function(q){var p=this,o=q.selectAll("g");o.selectAll("path").attr("id",function(u){return"label-"+u.data.chrom});o.append("svg:text").filter(function(u){return u.endAngle-u.startAngle>p.min_arc_len}).attr("text-anchor","middle").append("svg:textPath").attr("class","chrom-label").attr("xlink:href",function(u){return"#label-"+u.data.chrom}).attr("startOffset","25%").text(function(u){return u.data.chrom});var r=function(w){var u=(w.endAngle-w.startAngle)/w.value,v=m.range(0,w.value,25000000).map(function(x,y){return{radius:p.innerRadius,angle:x*u+w.startAngle,label:y===0?0:(y%3?null:p.formatNum(x))}});if(v.length<4){v[v.length-1].label=p.formatNum(Math.round((v[v.length-1].angle-w.startAngle)/u))}return v};var t=function(u){return u.angle>Math.PI?"rotate(180)translate(-16)":null};var s=h.filter(this.chroms_layout,function(u){return u.endAngle-u.startAngle>p.min_arc_len});this.drawTicks(this.parent_elt,s,r,t)}});h.extend(b.prototype,i);var g=l.extend({initialize:function(o){l.prototype.initialize.call(this,o);var p=this.track.get("config");p.get("min_value").on("change:value",this._update_min_max,this);p.get("max_value").on("change:value",this._update_min_max,this);p.get("color").on("change:value",this._transition_chrom_data,this)},_update_min_max:function(){var p=this.track.get("config"),o=[p.get_value("min_value"),p.get_value("max_value")];this._update_data_bounds(o);this.parent_elt.selectAll(".min_max").text(function(r,q){return o[q]})},_quantile:function(p,o){p.sort(m.ascending);return m.quantile(p,o)},_render_chrom_data:function(o,r,p){var s=this._get_path_function(r,p);if(!s){return null}var q=o.datum(p.data),t=q.append("path").attr("class","chrom-data").attr("chrom",r.data.chrom).attr("d",s);return t},_get_path_function:function(r,q){if(typeof q==="string"||!q.data||q.data.length===0){return null}var o=m.scale.linear().domain(this.data_bounds).range(this.radius_bounds).clamp(true);var s=m.scale.linear().domain([0,q.data.length]).range([r.startAngle,r.endAngle]);var p=m.svg.line.radial().interpolate("linear").radius(function(t){return o(t[1])}).angle(function(u,t){return s(t)});return m.svg.area.radial().interpolate(p.interpolate()).innerRadius(o(0)).outerRadius(p.radius()).angle(p.angle())},render_labels:function(){var o=this,q=function(){return"rotate(90)"};var p=this.drawTicks(this.parent_elt,[this.chroms_layout[0]],this._data_bounds_ticks_fn(),q,true).classed("min_max",true);h.each(p,function(r){$(r).click(function(){var s=new c.ConfigSettingCollectionView({collection:o.track.get("config")});s.render_in_modal("Configure Track")})})},_transition_labels:function(){if(this.data_bounds.length===0){return}var p=this,r=h.filter(this.chroms_layout,function(s){return s.endAngle-s.startAngle>0.08}),q=h.filter(r,function(t,s){return s%3===0}),o=h.flatten(h.map(q,function(s){return p._data_bounds_ticks_fn()(s)}));this.parent_elt.selectAll("g.tick").data(o).transition().attr("transform",function(s){return"rotate("+(s.angle*180/Math.PI-90)+")translate("+s.radius+",0)"})},_data_bounds_ticks_fn:function(){var o=this;visibleChroms=0;return function(p){return[{radius:o.radius_bounds[0],angle:p.startAngle,label:o.formatNum(o.data_bounds[0])},{radius:o.radius_bounds[1],angle:p.startAngle,label:o.formatNum(o.data_bounds[1])}]}},get_data_bounds:function(o){}});h.extend(g.prototype,i);var e=g.extend({get_data_bounds:function(p){var o=h.flatten(h.map(p,function(q){if(q){return h.map(q.data,function(r){return parseInt(r[1],10)||0})}else{return 0}}));return[h.min(o),this._quantile(o,0.98)||h.max(o)]}});var k=l.extend({render:function(){var o=this;$.when(o.track.get("data_manager").data_is_ready()).then(function(){$.when(o.track.get("data_manager").get_genome_wide_data(o.genome)).then(function(r){var q=[],p=o.genome.get_chroms_info();h.each(r,function(v,u){var s=p[u].chrom;var t=h.map(v.data,function(x){var w=o._get_region_angle(s,x[1]),y=o._get_region_angle(x[3],x[4]);return{source:{startAngle:w,endAngle:w+0.01},target:{startAngle:y,endAngle:y+0.01}}});q=q.concat(t)});o.parent_elt.append("g").attr("class","chord").selectAll("path").data(q).enter().append("path").style("fill",o.get_fill_color()).attr("d",m.svg.chord().radius(o.radius_bounds[0])).style("opacity",1)})})},update_radius_bounds:function(o){this.radius_bounds=o;this.parent_elt.selectAll("path").transition().attr("d",m.svg.chord().radius(this.radius_bounds[0]))},_get_region_angle:function(q,o){var p=h.find(this.chroms_layout,function(r){return r.data.chrom===q});return p.endAngle-((p.endAngle-p.startAngle)*(p.data.len-o)/p.data.len)}});var f=Backbone.View.extend({initialize:function(){var o=new j.Genome(galaxy_config.app.genome),p=new j.GenomeVisualization(galaxy_config.app.viz_config);p.get("config").add([{key:"arc_dataset_height",label:"Arc Dataset Height",type:"int",value:25,view:"circster"},{key:"track_gap",label:"Gap Between Tracks",type:"int",value:5,view:"circster"},{key:"total_gap",label:"Gap [0-1]",type:"float",value:0.4,view:"circster",hidden:true}]);var r=new a({el:$("#center .unified-panel-body"),genome:o,model:p});r.render();$("#center .unified-panel-header-inner").append(galaxy_config.app.viz_config.title+" "+galaxy_config.app.viz_config.dbkey);var q=create_icon_buttons_menu([{icon_class:"plus-button",title:"Add tracks",on_click:function(){j.select_datasets(galaxy_config.root+"visualization/list_current_history_datasets",galaxy_config.root+"api/datasets",p.get("dbkey"),function(s){p.add_tracks(s)})}},{icon_class:"gear",title:"Settings",on_click:function(){var s=new c.ConfigSettingCollectionView({collection:p.get("config")});s.render_in_modal("Configure Visualization")}},{icon_class:"disk--arrow",title:"Save",on_click:function(){Galaxy.modal.show({title:"Saving...",body:"progress"});$.ajax({url:galaxy_config.root+"visualization/save",type:"POST",dataType:"json",data:{id:p.get("vis_id"),title:p.get("title"),dbkey:p.get("dbkey"),type:"trackster",vis_json:JSON.stringify(p)}}).success(function(s){Galaxy.modal.hide();p.set("vis_id",s.vis_id)}).error(function(){Galaxy.modal.show({title:"Could Not Save",body:"Could not save visualization. Please try again later.",buttons:{Cancel:function(){Galaxy.modal.hide()}}})})}},{icon_class:"cross-circle",title:"Close",on_click:function(){window.location=galaxy_config.root+"visualization/list"}}],{tooltip_config:{placement:"bottom"}});q.$el.attr("style","float: right");$("#center .unified-panel-header-inner").append(q.$el);$(".menu-button").tooltip({placement:"bottom"})}});return{GalaxyApp:f}});
\ No newline at end of file
diff -r 70c404e681a0f4c347eaca75d65f23a11edcb823 -r d09b44c5f22839e1b87f5673bdd1615b67b3ca51 static/scripts/viz/circster.js
--- a/static/scripts/viz/circster.js
+++ b/static/scripts/viz/circster.js
@@ -404,11 +404,11 @@
/* ----------------------- Public Methods ------------------------- */
initialize: function(options) {
- this.bg_stroke = 'ddd';
+ this.bg_stroke = '#ddd';
// Fill color when loading data.
- this.loading_bg_fill = 'ffc';
+ this.loading_bg_fill = '#ffc';
// Fill color when data has been loaded.
- this.bg_fill = 'ddd';
+ this.bg_fill = '#ddd';
this.total_gap = options.total_gap;
this.track = options.track;
this.radius_bounds = options.radius_bounds;
@@ -688,8 +688,8 @@
// Use a single arc for rendering data.
this.innerRadius = this.radius_bounds[0];
this.radius_bounds[0] = this.radius_bounds[1];
- this.bg_stroke = 'fff';
- this.bg_fill = 'fff';
+ this.bg_stroke = '#fff';
+ this.bg_fill = '#fff';
// Minimum arc distance for labels to be applied.
this.min_arc_len = 0.05;
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: dannon: S3ObjectStore will create the bucket for you when possible if it does not exist.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/70c404e681a0/
Changeset: 70c404e681a0
User: dannon
Date: 2014-10-16 17:54:46+00:00
Summary: S3ObjectStore will create the bucket for you when possible if it does not exist.
Affected #: 1 file
diff -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 -r 70c404e681a0f4c347eaca75d65f23a11edcb823 lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -167,8 +167,12 @@
log.debug("Using cloud object store with bucket '%s'" % bucket.name)
return bucket
except S3ResponseError:
- log.debug("Could not get bucket '%s', attempt %s/5" % (bucket_name, i + 1))
- time.sleep(2)
+ try:
+ log.debug("Bucket not found, creating s3 bucket with handle '%s'" % bucket_name)
+ self.conn.create_bucket(bucket_name)
+ except S3ResponseError:
+ log.exception("Could not get bucket '%s', attempt %s/5" % (bucket_name, i + 1))
+ time.sleep(2)
# All the attempts have been exhausted and connection was not established,
# raise error
raise S3ResponseError
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/921aa1c775b5/
Changeset: 921aa1c775b5
User: dannon
Date: 2014-10-16 17:41:10+00:00
Summary: Slightly better handling of s3 object store conf, allowing connection element to be optional
Affected #: 1 file
diff -r 9f5491972e72ee38e011d49e891303e47bca29d9 -r 921aa1c775b54911c149fe3c8a1dc9645945a83d lib/galaxy/objectstore/s3.py
--- a/lib/galaxy/objectstore/s3.py
+++ b/lib/galaxy/objectstore/s3.py
@@ -77,7 +77,11 @@
b_xml = config_xml.findall('bucket')[0]
self.bucket = b_xml.get('name')
self.use_rr = b_xml.get('use_reduced_redundancy', False)
- cn_xml = config_xml.findall('connection')[0]
+ cn_xml = config_xml.findall('connection')
+ if not cn_xml:
+ cn_xml = {}
+ else:
+ cn_xml = cn_xml[0]
self.host = cn_xml.get('host', None)
self.port = int(cn_xml.get('port', 6000))
self.is_secure = cn_xml.get('is_secure', True)
https://bitbucket.org/galaxy/galaxy-central/commits/b1d9b4f49abb/
Changeset: b1d9b4f49abb
User: dannon
Date: 2014-10-16 17:41:22+00:00
Summary: Merge.
Affected #: 65 files
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/collection/collection-li.js
--- a/client/galaxy/scripts/mvc/collection/collection-li.js
+++ b/client/galaxy/scripts/mvc/collection/collection-li.js
@@ -100,8 +100,6 @@
/** add the DCE class to the list item */
className : ListItemView.prototype.className + " dataset-collection-element",
- /** jq fx speed for this view */
- fxSpeed : 'fast',
/** set up */
initialize : function( attributes ){
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/history/history-structure-view.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/history/history-structure-view.js
@@ -0,0 +1,421 @@
+define([
+ 'mvc/job/job-model',
+ 'mvc/job/job-li',
+ 'mvc/history/history-content-model',
+ 'mvc/history/job-dag',
+ 'mvc/base-mvc',
+ 'utils/localization',
+ 'libs/d3'
+], function( JOB, JOB_LI, HISTORY_CONTENT, JobDAG, BASE_MVC, _l ){
+// ============================================================================
+/* TODO:
+change component = this to something else
+
+*/
+// ============================================================================
+/**
+ *
+ */
+var HistoryStructureComponent = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ //logger : console,
+
+ className : 'history-structure-component',
+
+ initialize : function( attributes ){
+ this.log( this + '(HistoryStructureComponent).initialize:', attributes );
+ this.component = attributes.component;
+
+ this._jobLiMap = {};
+ this._createJobModels();
+
+ this.layout = this._createLayout( attributes.layoutOptions );
+ },
+
+ _createJobModels : function(){
+ var view = this;
+ view.component.eachVertex( function( vertex ){
+ var jobJSON = vertex.data.job,
+ job = new JOB.Job( jobJSON );
+
+ // get the models of the outputs for this job from the history
+ var outputModels = _.map( job.get( 'outputs' ), function( output ){
+ //note: output is { src: 'hda/dataset_collection', id: <some id> }
+ // job output doesn't *quite* match up to normal typeId
+ var type = output.src === 'hda'? 'dataset' : 'dataset_collection',
+ typeId = HISTORY_CONTENT.typeIdStr( type, output.id );
+ return view.model.contents.get( typeId );
+ });
+ // set the collection (HistoryContents) for the job to that json (setting historyId for proper ajax urls)
+ job.outputCollection.reset( outputModels );
+ job.outputCollection.historyId = view.model.id;
+ //this.debug( job.outputCollection );
+
+ // create the bbone view for the job (to be positioned later accrd. to the layout) and cache
+ var li = new JOB_LI.JobListItemView({ model: job });
+ //var li = new JOB_LI.JobListItemView({ model: job });
+ li.render( 0 ).$el.appendTo( view.$el );
+ view._jobLiMap[ job.id ] = li;
+ view._setUpJobListeners( li );
+
+ });
+ return view.jobs;
+ },
+
+ _setUpJobListeners : function( jobLi ){
+ // update the layout during expansion and collapsing of job and output li's
+ jobLi.on( 'expanding expanded collapsing collapsed', this.render, this );
+ jobLi.foldout.on( 'view:expanding view:expanded view:collapsing view:collapsed', this.render, this );
+ },
+
+ layoutDefaults : {
+ paddingTop : 8,
+ paddingLeft : 20,
+ linkSpacing : 16,
+ jobHeight : 308,
+ jobWidthSpacing : 320,
+ linkAdjX : 4,
+ linkAdjY : 0
+ },
+
+ _createLayout : function( options ){
+ options = _.defaults( _.clone( options || {} ), this.layoutDefaults );
+ var view = this,
+ vertices = _.values( view.component.vertices ),
+ layout = _.extend( options, {
+ nodeMap : {},
+ links : [],
+ el : { width: 0, height: 0 },
+ svg : { width: 0, height: 0, top: 0, left: 0 }
+ });
+
+ vertices.forEach( function( v, j ){
+ var node = { name: v.name, x: 0, y: 0 };
+ layout.nodeMap[ v.name ] = node;
+ });
+
+ view.component.edges( function( e ){
+ var link = {
+ source: e.source,
+ target: e.target
+ };
+ layout.links.push( link );
+ });
+ //this.debug( JSON.stringify( layout, null, ' ' ) );
+ return layout;
+ },
+
+ _updateLayout : function(){
+ var view = this,
+ layout = view.layout;
+
+ layout.svg.height = layout.paddingTop + ( layout.linkSpacing * _.size( layout.nodeMap ) );
+ layout.el.height = layout.svg.height + layout.jobHeight;
+
+//TODO:?? can't we just alter the component v and e's directly?
+ // layout the job views putting jobWidthSpacing btwn each
+ var x = layout.paddingLeft,
+ y = layout.svg.height;
+ _.each( layout.nodeMap, function( node, jobId ){
+ //this.debug( node, jobId );
+ node.x = x;
+ node.y = y;
+ x += layout.jobWidthSpacing;
+ });
+ layout.el.width = layout.svg.width = Math.max( layout.el.width, x );
+
+ // layout the links - connecting each job by it's main coords (currently)
+//TODO: somehow adjust the svg height based on the largest distance the longest connection needs
+ layout.links.forEach( function( link ){
+ var source = layout.nodeMap[ link.source ],
+ target = layout.nodeMap[ link.target ];
+ link.x1 = source.x + layout.linkAdjX;
+ link.y1 = source.y + layout.linkAdjY;
+ link.x2 = target.x + layout.linkAdjX;
+ link.y2 = target.y + layout.linkAdjY;
+ });
+ //this.debug( JSON.stringify( layout, null, ' ' ) );
+ return this.layout;
+ },
+
+ render : function( options ){
+ this.debug( this + '.render:', options );
+ var view = this;
+
+ function _render(){
+ view._updateLayout();
+ // set up the display containers
+ view.$el
+ .width( view.layout.el.width )
+ .height( view.layout.el.height );
+ view.renderSVG();
+
+ // position the job views accrd. to the layout
+ view.component.eachVertex( function( v ){
+//TODO:? liMap needed - can't we attach to vertex?
+ var li = view._jobLiMap[ v.name ],
+ position = view.layout.nodeMap[ li.model.id ];
+ //this.debug( position );
+ li.$el.css({ top: position.y, left: position.x });
+ });
+ }
+//TODO: hack - li's invisible in updateLayout without this delay
+ if( !this.$el.is( ':visible' ) ){
+ _.delay( _render, 0 );
+ } else {
+ _render();
+ }
+ return this;
+ },
+
+ renderSVG : function(){
+ var view = this,
+ layout = view.layout;
+
+ var svg = d3.select( this.el ).select( 'svg' );
+ if( svg.empty() ){
+ svg = d3.select( this.el ).append( 'svg' );
+ }
+
+ svg
+ .attr( 'width', layout.svg.width )
+ .attr( 'height', layout.svg.height );
+
+ function highlightConnect( d ){
+ d3.select( this ).classed( 'highlighted', true );
+ view._jobLiMap[ d.source ].$el.addClass( 'highlighted' );
+ view._jobLiMap[ d.target ].$el.addClass( 'highlighted' );
+ }
+
+ function unhighlightConnect( d ){
+ d3.select( this ).classed( 'highlighted', false );
+ view._jobLiMap[ d.source ].$el.removeClass( 'highlighted' );
+ view._jobLiMap[ d.target ].$el.removeClass( 'highlighted' );
+ }
+
+ var connections = svg.selectAll( '.connection' )
+ .data( layout.links );
+
+ connections
+ .enter().append( 'path' )
+ .attr( 'class', 'connection' )
+ .attr( 'id', function( d ){ return d.source + '-' + d.target; })
+ .on( 'mouseover', highlightConnect )
+ .on( 'mouseout', unhighlightConnect );
+
+ connections
+ .attr( 'd', function( d ){ return view._connectionPath( d ); });
+
+//TODO: ? can we use tick here to update the links?
+
+ return svg.node();
+ },
+
+ _connectionPath : function( d ){
+ var CURVE_X = 0,
+ controlY = ( ( d.x2 - d.x1 ) / this.layout.svg.width ) * this.layout.svg.height;
+ return [
+ 'M', d.x1, ',', d.y1, ' ',
+ 'C',
+ d.x1 + CURVE_X, ',', d.y1 - controlY, ' ',
+ d.x2 - CURVE_X, ',', d.y2 - controlY, ' ',
+ d.x2, ',', d.y2
+ ].join( '' );
+ },
+
+ events : {
+ 'mouseover .job.list-item' : function( ev ){ this.highlightConnected( ev.currentTarget, true ); },
+ 'mouseout .job.list-item' : function( ev ){ this.highlightConnected( ev.currentTarget, false ); }
+ },
+
+ highlightConnected : function( jobElement, highlight ){
+ highlight = highlight !== undefined? highlight : true;
+
+ var view = this,
+ component = view.component,
+ jobClassFn = highlight? jQuery.prototype.addClass : jQuery.prototype.removeClass,
+ connectionClass = highlight? 'connection highlighted' : 'connection';
+
+ //console.debug( 'mouseover', this );
+ var $jobs = jobClassFn.call( $( jobElement ), 'highlighted' ),
+ id = $jobs.attr( 'id' ).replace( 'job-', '' );
+
+ // immed. ancestors
+ component.edges({ target: id }).forEach( function( edge ){
+ jobClassFn.call( view.$( '#job-' + edge.source ), 'highlighted' );
+ view.$( '#' + edge.source + '-' + id ).attr( 'class', connectionClass );
+ });
+ // descendants
+ component.vertices[ id ].eachEdge( function( edge ){
+ jobClassFn.call( view.$( '#job-' + edge.target ), 'highlighted' );
+ view.$( '#' + id + '-' + edge.target ).attr( 'class', connectionClass );
+ });
+ },
+
+ toString : function(){
+ return 'HistoryStructureComponent(' + this.model.id + ')';
+ }
+});
+
+
+// ============================================================================
+/**
+ *
+ */
+var VerticalHistoryStructureComponent = HistoryStructureComponent.extend({
+
+ //logger : console,
+
+ className : HistoryStructureComponent.prototype.className + ' vertical',
+
+ layoutDefaults : {
+ paddingTop : 8,
+ paddingLeft : 20,
+ linkSpacing : 16,
+ jobWidth : 308,
+ jobHeight : 308,
+ initialSpacing : 64,
+ jobSpacing : 16,
+ linkAdjX : 0,
+ linkAdjY : 4
+ },
+
+//TODO: how can we use the dom height of the job li's - they're not visible when this is called?
+ _updateLayout : function(){
+ var view = this,
+ layout = view.layout;
+ //this.info( this.cid, '_updateLayout' )
+
+ layout.svg.width = layout.paddingLeft + ( layout.linkSpacing * _.size( layout.nodeMap ) );
+ layout.el.width = layout.svg.width + layout.jobWidth;
+
+ // reset height - we'll get the max Y below to assign to it
+ layout.el.height = 0;
+
+//TODO:?? can't we just alter the component v and e's directly?
+ var x = layout.svg.width,
+ y = layout.paddingTop;
+ _.each( layout.nodeMap, function( node, jobId ){
+ //this.debug( node, jobId );
+ node.x = x;
+ node.y = y;
+ var li = view._jobLiMap[ jobId ];
+ if( li.$el.is( ':visible' ) ){
+ y += li.$el.height() + layout.jobSpacing;
+ } else {
+ y += layout.initialSpacing + layout.jobSpacing;
+ }
+ });
+ layout.el.height = layout.svg.height = Math.max( layout.el.height, y );
+
+ // layout the links - connecting each job by it's main coords (currently)
+ layout.links.forEach( function( link ){
+ var source = layout.nodeMap[ link.source ],
+ target = layout.nodeMap[ link.target ];
+ link.x1 = source.x + layout.linkAdjX;
+ link.y1 = source.y + layout.linkAdjY;
+ link.x2 = target.x + layout.linkAdjX;
+ link.y2 = target.y + layout.linkAdjY;
+ view.debug( 'link:', link.x1, link.y1, link.x2, link.y2, link );
+ });
+ //this.debug( JSON.stringify( layout, null, ' ' ) );
+ view.debug( 'el:', layout.el );
+ view.debug( 'svg:', layout.svg );
+ return layout;
+ },
+
+ _connectionPath : function( d ){
+ var CURVE_Y = 0,
+ controlX = ( ( d.y2 - d.y1 ) / this.layout.svg.height ) * this.layout.svg.width;
+ return [
+ 'M', d.x1, ',', d.y1, ' ',
+ 'C',
+ d.x1 - controlX, ',', d.y1 + CURVE_Y, ' ',
+ d.x2 - controlX, ',', d.y2 - CURVE_Y, ' ',
+ d.x2, ',', d.y2
+ ].join( '' );
+ },
+
+ toString : function(){
+ return 'VerticalHistoryStructureComponent(' + this.model.id + ')';
+ }
+});
+
+
+// ============================================================================
+/**
+ *
+ */
+var HistoryStructureView = Backbone.View.extend( BASE_MVC.LoggableMixin ).extend({
+
+ //logger : console,
+
+ className : 'history-structure',
+
+ initialize : function( attributes ){
+ this.log( this + '(HistoryStructureView).initialize:', attributes, this.model );
+//TODO: to model
+ this.jobs = attributes.jobs;
+ this._createDAG();
+ },
+
+ _createDAG : function(){
+ this.dag = new JobDAG({
+ historyContents : this.model.contents.toJSON(),
+ jobs : this.jobs,
+ excludeSetMetadata : true,
+ excludeErroredJobs : true
+ });
+//window.dag = this.dag;
+ this.log( this + '.dag:', this.dag );
+
+ this._createComponents();
+ },
+
+ _createComponents : function(){
+ this.log( this + '._createComponents' );
+ var structure = this;
+//window.structure = structure;
+
+ structure.componentViews = structure.dag.weakComponentGraphArray().map( function( componentGraph ){
+ return structure._createComponent( componentGraph );
+ });
+ },
+
+ _createComponent : function( component ){
+ this.log( this + '._createComponent:', component );
+ //return new HistoryStructureComponent({
+ return new VerticalHistoryStructureComponent({
+ model : this.model,
+ component : component
+ });
+ },
+
+ render : function( options ){
+ this.log( this + '.render:', options );
+ var structure = this;
+
+ structure.$el.html([
+ '<div class="controls"></div>',
+ '<div class="components"></div>'
+ ].join( '' ));
+
+ structure.componentViews.forEach( function( component ){
+ component.render().$el.appendTo( structure.$components() );
+ });
+ return structure;
+ },
+
+ $components : function(){
+ return this.$( '.components' );
+ },
+
+ toString : function(){
+ return 'HistoryStructureView(' + ')';
+ }
+});
+
+
+// ============================================================================
+ return HistoryStructureView;
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/history/job-dag.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/history/job-dag.js
@@ -0,0 +1,219 @@
+define([
+ 'utils/graph',
+ 'utils/add-logging'
+],function( GRAPH, addLogging ){
+// ============================================================================
+var _super = GRAPH.Graph;
+/** A Directed acyclic Graph built from a history's job data.
+ * Reads in job json, filters and process that json, and builds a graph
+ * using the connections between job inputs and outputs.
+ */
+var JobDAG = function( options ){
+ var self = this;
+ //this.logger = console;
+
+ // instance vars
+//TODO: needed?
+ self._historyContentsMap = {};
+ self.filters = [];
+
+ self._idMap = {};
+ self.noInputJobs = [];
+ self.noOutputJobs = [];
+
+//TODO: save these?
+ self.filteredSetMetadata = [];
+ self.filteredErroredJobs = [];
+
+ _super.call( self, true, null, options );
+};
+JobDAG.prototype = new GRAPH.Graph();
+JobDAG.prototype.constructor = JobDAG;
+
+// add logging ability - turn off/on using the this.logger statement above
+addLogging( JobDAG );
+
+// ----------------------------------------------------------------------------
+/** process jobs, options, filters, and any history data, then create the graph */
+JobDAG.prototype.init = function _init( options ){
+ options = options || {};
+ _super.prototype.init.call( this, options );
+
+ var self = this,
+ historyContentsJSON = options.historyContents || [];
+ jobsJSON = options.jobs || [];
+
+ historyContentsJSON.forEach( function( content, i ){
+ self._historyContentsMap[ content.id ] = _.clone( content );
+ });
+
+ self.options = _.defaults( _.omit( options, 'historyContents', 'jobs' ), {
+ excludeSetMetadata : false
+ });
+ self.filters = self._initFilters();
+
+//TODO: O( 3N )
+ self.preprocessJobs( _.clone( jobsJSON ) );
+ self.createGraph();
+
+ return self;
+};
+
+/** add job filters based on options */
+JobDAG.prototype._initFilters = function __initFilters(){
+ var self = this,
+ filters = [];
+
+ if( self.options.excludeSetMetadata ){
+ self.filteredSetMetadata = [];
+ filters.push( function filterSetMetadata( jobData ){
+ if( jobData.job.tool_id !== '__SET_METADATA__' ){ return true; }
+ self.filteredSetMetadata.push( jobData.job.id );
+ return false;
+ });
+ }
+
+ if( self.options.excludeErroredJobs ){
+ self.filteredErroredJobs = [];
+ filters.push( function filterErrored( jobData ){
+ if( jobData.job.state !== 'error' ){ return true; }
+ self.filteredErroredJobs.push( jobData.job.id );
+ return false;
+ });
+ }
+
+ // all outputs deleted
+ // all outputs hidden
+
+ if( _.isArray( self.options.filters ) ){
+ filters = filters.concat( self.options.filters );
+ }
+ self.debug( 'filters len:', filters.length );
+ return filters;
+};
+
+/** sort the jobs and cache any that pass all filters into _idMap by job.id */
+JobDAG.prototype.preprocessJobs = function _preprocessJobs( jobs ){
+ this.info( 'processing jobs' );
+
+ var self = this;
+//TODO:? sorting neccessary?
+ self.sort( jobs ).forEach( function( job, i ){
+ var jobData = self.preprocessJob( job, i );
+ if( jobData ){
+ self._idMap[ job.id ] = jobData;
+ }
+ });
+ return self;
+};
+
+/** sort the jobs based on update time */
+JobDAG.prototype.sort = function _sort( jobs ){
+ function cmpCreate( a, b ){
+ if( a.update_time > b.update_time ){ return 1; }
+ if( a.update_time < b.update_time ){ return -1; }
+ return 0;
+ }
+ return jobs.sort( cmpCreate );
+};
+
+/** proces input/output, filter based on job data returning data if passing, null if not */
+JobDAG.prototype.preprocessJob = function _preprocessJob( job, index ){
+ //this.info( 'preprocessJob', job, index );
+ var self = this,
+ jobData = { index: index, job: job };
+
+ jobData.inputs = self.datasetMapToIdArray( job.inputs, function( dataset, nameInJob ){
+ //TODO:? store output name in self._datasets[ output.id ] from creating job?
+ });
+ if( jobData.inputs.length === 0 ){
+ self.noInputJobs.push( job.id );
+ }
+ jobData.outputs = self.datasetMapToIdArray( job.outputs, function( dataset, nameInJob ){
+
+ });
+ if( jobData.outputs.length === 0 ){
+ self.noOutputJobs.push( job.id );
+ }
+
+ //self.debug( JSON.stringify( jobData, null, ' ' ) );
+ // apply filters after processing job allowing access to the additional data above in the filters
+ for( var i=0; i<self.filters.length; i++ ){
+ if( !self.filters[i].call( self, jobData ) ){
+ self.debug( 'job', job.id, ' has been filtered out by function:\n', self.filters[i] );
+ return null;
+ }
+ }
+
+ //self.info( 'preprocessJob returning', jobData );
+ return jobData;
+};
+
+/** make verbose input/output lists more concise, sanity checking along the way
+ * processFn is called on each input/output and passed the dataset obj (id,src) and the input/output name.
+ */
+JobDAG.prototype.datasetMapToIdArray = function _datasetMapToIdArray( datasetMap, processFn ){
+ var self = this;
+ return _.map( datasetMap, function( dataset, nameInJob ){
+ if( !dataset.id ){
+ throw new Error( 'No id on datasetMap: ', JSON.stringify( dataset ) );
+ }
+ if( !dataset.src || dataset.src !== 'hda' ){
+ throw new Error( 'Bad src on datasetMap: ', JSON.stringify( dataset ) );
+ }
+ processFn.call( self, dataset, nameInJob );
+ return dataset.id;
+ });
+};
+
+/** Walk all the jobs (vertices), attempting to find connections
+ * between datasets used as both inputs and outputs (edges)
+ */
+JobDAG.prototype.createGraph = function _createGraph(){
+ var self = this;
+ self.debug( 'connections:' );
+
+ _.each( self._idMap, function( sourceJobData, sourceJobId ){
+ self.debug( '\t', sourceJobId, sourceJobData );
+ self.createVertex( sourceJobId, sourceJobData );
+
+ sourceJobData.usedIn = [];
+ _.each( sourceJobData.outputs, function( outputDatasetId ){
+//TODO: O(n^2)
+ _.each( self._idMap, function( targetJobData, targetJobId ){
+ if( targetJobData === sourceJobData ){ return; }
+
+ if( targetJobData.inputs.indexOf( outputDatasetId ) !== -1 ){
+ self.info( '\t\t\t found connection: ', sourceJobId, targetJobId );
+ sourceJobData.usedIn.push({ job: targetJobId, output: outputDatasetId });
+
+ self.createVertex( targetJobId, targetJobData );
+
+ self.createEdge( sourceJobId, targetJobId, self.directed, {
+ dataset : outputDatasetId
+ });
+ }
+ });
+ });
+ });
+ self.debug( 'job data: ', JSON.stringify( self._idMap, null, ' ' ) );
+ return self;
+};
+
+/** Override to re-sort (ugh) jobs in each component by update time */
+Graph.prototype.weakComponentGraphArray = function(){
+ return this.weakComponents().map( function( component ){
+//TODO: this seems to belong above (in sort) - why isn't it preserved?
+ component.vertices.sort( function cmpCreate( a, b ){
+ if( a.data.job.update_time > b.data.job.update_time ){ return 1; }
+ if( a.data.job.update_time < b.data.job.update_time ){ return -1; }
+ return 0;
+ });
+ return new Graph( this.directed, component );
+ });
+};
+
+
+// ============================================================================
+ return JobDAG;
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/job/job-li.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/job/job-li.js
@@ -0,0 +1,129 @@
+define([
+ 'mvc/list/list-item',
+ 'mvc/dataset/dataset-list',
+ "mvc/base-mvc",
+ "utils/localization"
+], function( LIST_ITEM, DATASET_LIST, BASE_MVC, _l ){
+//==============================================================================
+var _super = LIST_ITEM.FoldoutListItemView;
+/** @class A job view used from within a larger list of jobs.
+ * Each job itself is a foldout panel of history contents displaying the outputs of this job.
+ */
+var JobListItemView = _super.extend(/** @lends JobListItemView.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+
+ className : _super.prototype.className + " job",
+ id : function(){
+ return [ 'job', this.model.get( 'id' ) ].join( '-' );
+ },
+
+ foldoutPanelClass : DATASET_LIST.DatasetList,
+
+ /** Set up: instance vars, options, and event handlers */
+ initialize : function( attributes ){
+ if( attributes.logger ){ this.logger = this.model.logger = attributes.logger; }
+ this.log( this + '.initialize:', attributes );
+ _super.prototype.initialize.call( this, attributes );
+
+ /** where should pages from links be displayed? (default to new tab/window) */
+ this.linkTarget = attributes.linkTarget || '_blank';
+ },
+
+ /** In this override, add the state as a class for use with state-based CSS */
+ _swapNewRender : function( $newRender ){
+ _super.prototype._swapNewRender.call( this, $newRender );
+ if( this.model.has( 'state' ) ){
+ this.$el.addClass( 'state-' + this.model.get( 'state' ) );
+ }
+ return this.$el;
+ },
+
+ /** Stub to return proper foldout panel options */
+ _getFoldoutPanelOptions : function(){
+ var options = _super.prototype._getFoldoutPanelOptions.call( this );
+ return _.extend( options, {
+ collection : this.model.outputCollection,
+ selecting : false
+ });
+ },
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ return 'JobListItemView(' + this.model + ')';
+ }
+});
+
+// ............................................................................ TEMPLATES
+/** underscore templates */
+JobListItemView.prototype.templates = (function(){
+//TODO: move to require text! plugin
+
+ var elTemplate = BASE_MVC.wrapTemplate([
+ '<div class="list-element">',
+ '<div class="id"><%= model.id %></div>',
+ // errors, messages, etc.
+ '<div class="warnings"></div>',
+
+ // multi-select checkbox
+ '<div class="selector">',
+ '<span class="fa fa-2x fa-square-o"></span>',
+ '</div>',
+ // space for title bar buttons - gen. floated to the right
+ '<div class="primary-actions"></div>',
+ '<div class="title-bar"></div>',
+
+ // expandable area for more details
+ '<div class="details"></div>',
+ '</div>'
+ ]);
+
+ var titleBarTemplate = BASE_MVC.wrapTemplate([
+ // adding a tabindex here allows focusing the title bar and the use of keydown to expand the dataset display
+ '<div class="title-bar clear" tabindex="0">',
+ //'<span class="state-icon"></span>',
+ '<div class="title">',
+ '<span class="name"><%- job.tool_id %></span>',
+ '</div>',
+ '<div class="subtitle"></div>',
+ '</div>'
+ ], 'job' );
+
+ //var subtitleTemplate = BASE_MVC.wrapTemplate([
+ // // override this
+ // '<div class="subtitle">',
+ // _l( 'Created' ), ': <%= new Date( job.create_time ).toString() %>, ',
+ // _l( 'Updated' ), ': <%= new Date( job.update_time ).toString() %>',
+ // '</div>'
+ //], 'job' );
+ //
+ //var detailsTemplate = BASE_MVC.wrapTemplate([
+ // '<div class="details">',
+ // '<div class="params">',
+ // '<% _.each( job.params, function( param, paramName ){ %>',
+ // '<div class="param">',
+ // '<label class="prompt"><%= paramName %></label>',
+ // '<span class="value"><%= param %></span>',
+ // '</div>',
+ // '<% }) %>',
+ // '</div>',
+ // '</div>'
+ //], 'job' );
+
+ return _.extend( {}, _super.prototype.templates, {
+ //el : elTemplate,
+ titleBar : titleBarTemplate,
+ //subtitle : subtitleTemplate,
+ //details : detailsTemplate
+ });
+}());
+
+
+//=============================================================================
+ return {
+ JobListItemView : JobListItemView
+ };
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/job/job-model.js
--- /dev/null
+++ b/client/galaxy/scripts/mvc/job/job-model.js
@@ -0,0 +1,203 @@
+define([
+ "mvc/history/history-contents",
+ "mvc/dataset/states",
+ "utils/ajax-queue",
+ "mvc/base-mvc",
+ "utils/localization"
+], function( HISTORY_CONTENTS, STATES, AJAX_QUEUE, BASE_MVC, _l ){
+//==============================================================================
+var searchableMixin = BASE_MVC.SearchableModelMixin;
+/** @class Represents a job running or ran on the server job handlers.
+ */
+var Job = Backbone.Model.extend( BASE_MVC.LoggableMixin ).extend(
+ BASE_MVC.mixin( searchableMixin, /** @lends Job.prototype */{
+
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** default attributes for a model */
+ defaults : {
+ model_class : 'Job',
+
+ tool : null,
+ exit_code : null,
+
+ inputs : {},
+ outputs : {},
+ params : {},
+
+ create_time : null,
+ update_time : null,
+ state : STATES.NEW
+ },
+
+ /** instance vars and listeners */
+ initialize : function( attributes, options ){
+ this.debug( this + '(Job).initialize', attributes, options );
+ this.outputCollection = attributes.outputCollection || new HISTORY_CONTENTS.HistoryContents([]);
+ this._setUpListeners();
+ },
+
+ /** set up any event listeners
+ * event: state:ready fired when this DA moves into/is already in a ready state
+ */
+ _setUpListeners : function(){
+ // if the state has changed and the new state is a ready state, fire an event
+ this.on( 'change:state', function( currModel, newState ){
+ this.log( this + ' has changed state:', currModel, newState );
+ if( this.inReadyState() ){
+ this.trigger( 'state:ready', currModel, newState, this.previous( 'state' ) );
+ }
+ });
+ },
+
+ // ........................................................................ common queries
+ /** Is this job in a 'ready' state; where 'Ready' states are states where no
+ * processing is left to do on the server.
+ */
+ inReadyState : function(){
+ return _.contains( STATES.READY_STATES, this.get( 'state' ) );
+ },
+
+ /** Does this model already contain detailed data (as opposed to just summary level data)? */
+ hasDetails : function(){
+ //?? this may not be reliable
+ return _.isEmpty( this.get( 'outputs' ) );
+ },
+
+ // ........................................................................ ajax
+ /** root api url */
+ urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' )) + 'api/jobs',
+ //url : function(){ return this.urlRoot; },
+
+ // ........................................................................ searching
+ // see base-mvc, SearchableModelMixin
+ /** what attributes of an Job will be used in a text search */
+ searchAttributes : [
+ 'tool'
+ ],
+
+ // ........................................................................ misc
+ /** String representation */
+ toString : function(){
+ return [ 'Job(', this.get( 'id' ), ':', this.get( 'tool_id' ), ')' ].join( '' );
+ }
+}));
+
+
+//==============================================================================
+/** @class Backbone collection for Jobs.
+ */
+var JobCollection = Backbone.Collection.extend( BASE_MVC.LoggableMixin ).extend(
+/** @lends JobCollection.prototype */{
+ model : Job,
+
+ /** logger used to record this.log messages, commonly set to console */
+ //logger : console,
+
+ /** root api url */
+ urlRoot : (( window.galaxy_config && galaxy_config.root )?( galaxy_config.root ):( '/' )) + 'api/jobs',
+ url : function(){ return this.urlRoot; },
+
+ intialize : function( models, options ){
+ console.debug( models, options );
+ },
+
+ // ........................................................................ common queries
+ /** Get the ids of every item in this collection
+ * @returns array of encoded ids
+ */
+ ids : function(){
+ return this.map( function( item ){ return item.get( 'id' ); });
+ },
+
+ /** Get jobs that are not ready
+ * @returns array of content models
+ */
+ notReady : function(){
+ return this.filter( function( job ){
+ return !job.inReadyState();
+ });
+ },
+
+ /** return true if any jobs don't have details */
+ haveDetails : function(){
+ return this.all( function( job ){ return job.hasDetails(); });
+ },
+
+ // ........................................................................ ajax
+ /** fetches all details for each job in the collection using a queue */
+ queueDetailFetching : function(){
+ var collection = this,
+ queue = new AJAX_QUEUE.AjaxQueue( this.map( function( job ){
+ return function(){
+ return job.fetch({ silent: true });
+ };
+ }));
+ queue.done( function(){
+ collection.trigger( 'details-loaded' );
+ });
+ return queue;
+ },
+
+ //toDAG : function(){
+ // return new JobDAG( this.toJSON() );
+ //},
+
+ // ........................................................................ sorting/filtering
+ /** return a new collection of jobs whose attributes contain the substring matchesWhat */
+ matches : function( matchesWhat ){
+ return this.filter( function( job ){
+ return job.matches( matchesWhat );
+ });
+ },
+
+ // ........................................................................ misc
+ /** override to get a correct/smarter merge when incoming data is partial */
+ set : function( models, options ){
+ // arrrrrrrrrrrrrrrrrg...
+ // (e.g. stupid backbone)
+ // w/o this partial models from the server will fill in missing data with model defaults
+ // and overwrite existing data on the client
+ // see Backbone.Collection.set and _prepareModel
+ var collection = this;
+ models = _.map( models, function( model ){
+ if( !collection.get( model.id ) ){ return model; }
+
+ // merge the models _BEFORE_ calling the superclass version
+ var merged = existing.toJSON();
+ _.extend( merged, model );
+ return merged;
+ });
+ // now call superclass when the data is filled
+ Backbone.Collection.prototype.set.call( this, models, options );
+ },
+
+ /** String representation. */
+ toString : function(){
+ return ([ 'JobCollection(', this.length, ')' ].join( '' ));
+ }
+
+//----------------------------------------------------------------------------- class vars
+}, {
+ /** class level fn for fetching the job details for all jobs in a history */
+ fromHistory : function( historyId ){
+ console.debug( this );
+ var Collection = this,
+ collection = new Collection([]);
+ collection.fetch({ data: { history_id: historyId }})
+ .done( function(){
+ window.queue = collection.queueDetailFetching();
+
+ });
+ return collection;
+ }
+});
+
+
+//=============================================================================
+ return {
+ Job : Job,
+ JobCollection : JobCollection
+ };
+});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/list/list-item.js
--- a/client/galaxy/scripts/mvc/list/list-item.js
+++ b/client/galaxy/scripts/mvc/list/list-item.js
@@ -16,8 +16,8 @@
initialize : function( attributes ){
/** are the details of this view expanded/shown or not? */
this.expanded = attributes.expanded || false;
- //this.log( '\t expanded:', this.expanded );
- this.fxSpeed = attributes.fxSpeed || this.fxSpeed;
+ this.log( '\t expanded:', this.expanded );
+ this.fxSpeed = attributes.fxSpeed !== undefined? attributes.fxSpeed : this.fxSpeed;
},
// ........................................................................ render main
@@ -70,7 +70,9 @@
/** empty out the current el, move the $newRender's children in */
_swapNewRender : function( $newRender ){
- return this.$el.empty().attr( 'class', this.className ).append( $newRender.children() );
+ return this.$el.empty()
+ .attr( 'class', _.isFunction( this.className )? this.className(): this.className )
+ .append( $newRender.children() );
},
/** set up js behaviors, event handlers for elements within the given container
@@ -117,15 +119,8 @@
*/
expand : function(){
var view = this;
- return view._fetchModelDetails()
- .always(function(){
- var $newDetails = view._renderDetails();
- view.$details().replaceWith( $newDetails );
- // needs to be set after the above or the slide will not show
- view.expanded = true;
- view.$details().slideDown( view.fxSpeed, function(){
- view.trigger( 'expanded', view );
- });
+ return view._fetchModelDetails().always( function(){
+ view._expand();
});
},
@@ -139,6 +134,24 @@
return jQuery.when();
},
+ /** Inner fn called when expand (public) has fetched the details */
+ _expand : function(){
+ var view = this,
+ $newDetails = view._renderDetails();
+ view.$details().replaceWith( $newDetails );
+ // needs to be set after the above or the slide will not show
+ view.expanded = true;
+ view.$details().slideDown({
+ duration : view.fxSpeed,
+ step: function(){
+ view.trigger( 'expanding', view );
+ },
+ complete: function(){
+ view.trigger( 'expanded', view );
+ }
+ });
+ },
+
/** Hide the body/details of an HDA.
* @fires collapsed when a body has been collapsed
*/
@@ -146,8 +159,14 @@
this.debug( this + '(ExpandableView).collapse' );
var view = this;
view.expanded = false;
- this.$details().slideUp( view.fxSpeed, function(){
- view.trigger( 'collapsed', view );
+ this.$details().slideUp({
+ duration : view.fxSpeed,
+ step: function(){
+ view.trigger( 'collapsing', view );
+ },
+ complete: function(){
+ view.trigger( 'collapsed', view );
+ }
});
}
@@ -204,7 +223,7 @@
$newRender.children( '.warnings' ).replaceWith( this._renderWarnings() );
$newRender.children( '.title-bar' ).replaceWith( this._renderTitleBar() );
$newRender.children( '.primary-actions' ).append( this._renderPrimaryActions() );
- $newRender.find( '.title-bar .subtitle' ).replaceWith( this._renderSubtitle() );
+ $newRender.find( '> .title-bar .subtitle' ).replaceWith( this._renderSubtitle() );
return $newRender;
},
@@ -375,11 +394,13 @@
* disrespect attributes.expanded if drilldown
*/
initialize : function( attributes ){
- ListItemView.prototype.initialize.call( this, attributes );
//TODO: hackish
if( this.foldoutStyle === 'drilldown' ){ this.expanded = false; }
this.foldoutStyle = attributes.foldoutStyle || this.foldoutStyle;
this.foldoutPanelClass = attributes.foldoutPanelClass || this.foldoutPanelClass;
+
+ ListItemView.prototype.initialize.call( this, attributes );
+ this.foldout = this._createFoldoutPanel();
},
//TODO:?? override to exclude foldout scope?
@@ -393,7 +414,7 @@
//TODO: hackish
if( this.foldoutStyle === 'drilldown' ){ return $(); }
var $newDetails = ListItemView.prototype._renderDetails.call( this );
- return this._attachFoldout( this._createFoldoutPanel(), $newDetails );
+ return this._attachFoldout( this.foldout, $newDetails );
},
/** In this override, handle collection expansion. */
@@ -417,7 +438,8 @@
_getFoldoutPanelOptions : function(){
return {
// propagate foldout style down
- foldoutStyle : this.foldoutStyle
+ foldoutStyle : this.foldoutStyle,
+ fxSpeed : this.fxSpeed
};
},
@@ -436,25 +458,13 @@
return view._fetchModelDetails()
.always(function(){
if( view.foldoutStyle === 'foldout' ){
- view._expandByFoldout();
+ view._expand();
} else if( view.foldoutStyle === 'drilldown' ){
view._expandByDrilldown();
}
});
},
- /** For foldout, call render details then slide down */
- _expandByFoldout : function(){
- var view = this;
- var $newDetails = view._renderDetails();
- view.$details().replaceWith( $newDetails );
- // needs to be set after the above or the slide will not show
- view.expanded = true;
- view.$details().slideDown( view.fxSpeed, function(){
- view.trigger( 'expanded', view );
- });
- },
-
/** For drilldown, set up close handler and fire expanded:drilldown
* containing views can listen to this and handle other things
* (like hiding themselves) by listening for expanded/collapsed:drilldown
@@ -462,7 +472,6 @@
_expandByDrilldown : function(){
var view = this;
// attachment and rendering done by listener
- view.foldout = this._createFoldoutPanel();
view.foldout.on( 'close', function(){
view.trigger( 'collapsed:drilldown', view, view.foldout );
});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-content.js
--- a/client/galaxy/scripts/mvc/tools/tools-content.js
+++ b/client/galaxy/scripts/mvc/tools/tools-content.js
@@ -22,11 +22,16 @@
// get history summary
Utils.get({
- url : self.base_url + '?deleted=false',
+ url : self.base_url + '?deleted=false&state=ok',
success : function(response) {
// backup summary
self.summary = response;
+ // sort by id
+ self.summary.sort(function(a, b) {
+ return a.hid > b.hid ? -1 : (a.hid < b.hid ? 1 : 0);
+ });
+
// log
console.debug('tools-content::initialize() - Completed.');
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -27,10 +27,8 @@
this.modal = new Ui.Modal.View();
}
- // link model/inputs and all options
- this.options = options;
- this.model = options.model;
- this.inputs = options.model.inputs;
+ // link options
+ this.options = options;
// set element
this.setElement('<div/>');
@@ -53,9 +51,13 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize contents
+ // for now the initial tool model is parsed through the mako
+ this.model = this.options;
+ this.inputs = this.options.inputs;
+
+ // request history content and build form
this.content = new ToolContent({
- history_id : this.options.history_id,
+ history_id : self.options.history_id,
success : function() {
self._buildForm();
}
@@ -89,6 +91,51 @@
console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
+ // build tool model through api call
+ _buildModel: function() {
+ // link this
+ var self = this;
+
+ // construct url
+ var model_url = galaxy_config.root + 'api/tools/' + this.options.id + '/build?';
+ if (this.options.job_id) {
+ model_url += 'job_id=' + this.options.job_id;
+ } else {
+ if (this.options.dataset_id) {
+ model_url += 'dataset_id=' + this.options.dataset_id;
+ } else {
+ var loc = top.location.href;
+ var pos = loc.indexOf('?');
+ if (loc.indexOf('tool_id=') != -1 && pos !== -1) {
+ model_url += loc.slice(pos + 1);
+ }
+ }
+ }
+
+ // get initial model
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ success : function(response) {
+ // link model data update options
+ self.options = $.extend(self.options, response);
+ self.model = response;
+ self.inputs = response.inputs;
+
+ // log success
+ console.debug('tools-form::initialize() - Initial tool model ready.');
+ console.debug(response);
+
+ // build form
+ self._buildForm();
+ },
+ error : function(response) {
+ console.debug('tools-form::initialize() - Initial tool model request failed.');
+ console.debug(response);
+ }
+ });
+ },
+
// refresh form data
_refreshForm: function() {
// link this
@@ -97,7 +144,7 @@
// finalize data
var current_state = this.tree.finalize({
data : function(dict) {
- if (dict.values.length > 0 && dict.values[0].src === 'hda') {
+ if (dict.values.length > 0 && dict.values[0] && dict.values[0].src === 'hda') {
return self.content.get({id: dict.values[0].id}).dataset_id;
}
return null;
@@ -111,7 +158,7 @@
// post job
Utils.request({
type : 'GET',
- url : galaxy_config.root + 'tool_runner/index?tool_id=' + this.options.id + '&form_refresh=True',
+ url : galaxy_config.root + 'api/tools/' + this.options.id + '/build',
data : current_state,
success : function(response) {
console.debug('tools-form::_refreshForm() - Refreshed inputs/states.');
@@ -132,28 +179,31 @@
// button menu
var menu = new Ui.ButtonMenu({
icon : 'fa-gear',
- tooltip : 'Click to see a list of available operations.'
+ tooltip : 'Click to see a list of options.'
});
- // add question option
- menu.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
- }
- });
+ // configure button selection
+ if(this.options.biostar_url) {
+ // add question option
+ menu.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
+ }
+ });
+ };
// create share button
menu.addMenu({
@@ -185,11 +235,11 @@
});
// switch to classic tool form mako if the form definition is incompatible
- //if (this.incompatible) {
+ if (this.incompatible) {
this.$el.hide();
$('#tool-form-classic').show();
return;
- //}
+ }
// create portlet
this.portlet = new Portlet.View({
@@ -213,12 +263,6 @@
}
});
- // configure button selection
- if(!this.options.biostar_url) {
- button_question.$el.hide();
- button_search.$el.hide();
- }
-
// append form
this.$el.append(this.portlet.$el);
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-jobs.js
--- a/client/galaxy/scripts/mvc/tools/tools-jobs.js
+++ b/client/galaxy/scripts/mvc/tools/tools-jobs.js
@@ -37,7 +37,7 @@
console.debug(job_def);
// show progress modal
- this.app.modal.show({title: 'Please wait...', body: 'progress', buttons: { 'Close' : function () {self.app.modal.hide();} }});
+ this.app.modal.show({title: 'Please wait...', body: 'progress', closing_events: true, buttons: { 'Close' : function () {self.app.modal.hide();} }});
// post job
Utils.request({
@@ -55,10 +55,20 @@
var error_messages = self.app.tree.matchResponse(response.message.data);
for (var input_id in error_messages) {
self._foundError(input_id, error_messages[input_id]);
+ break;
}
} else {
// show error message with details
console.debug(response);
+ self.app.modal.show({
+ title : 'Job submission failed',
+ body : ToolTemplate.error(job_def),
+ buttons : {
+ 'Close' : function() {
+ self.app.modal.hide();
+ }
+ }
+ });
}
}
});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-section.js
--- a/client/galaxy/scripts/mvc/tools/tools-section.js
+++ b/client/galaxy/scripts/mvc/tools/tools-section.js
@@ -529,22 +529,12 @@
/** Slider field
*/
_fieldSlider: function(input_def) {
- // set min/max
- input_def.min = input_def.min || 0;
- input_def.max = input_def.max || 100000;
-
- // calculate step size
- var step = 1;
- if (input_def.type == 'float') {
- step = (input_def.max - input_def.min) / 10000;
- }
-
// create slider
return new Ui.Slider.View({
id : 'field-' + input_def.id,
+ precise : input_def.type == 'float',
min : input_def.min,
- max : input_def.max,
- step : step
+ max : input_def.max
});
},
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-select-content.js
--- a/client/galaxy/scripts/mvc/tools/tools-select-content.js
+++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js
@@ -40,7 +40,7 @@
var dataset_options = [];
for (var i in datasets) {
dataset_options.push({
- label: datasets[i].name,
+ label: datasets[i].hid + ': ' + datasets[i].name,
value: datasets[i].id
});
}
@@ -67,7 +67,7 @@
var collection_options = [];
for (var i in collections) {
collection_options.push({
- label: collections[i].name,
+ label: collections[i].hid + ': ' + collections[i].name,
value: collections[i].id
});
}
@@ -103,20 +103,36 @@
},
/** Return the currently selected dataset values */
- value : function () {
- // identify select element
- var select = null;
- switch(this.current) {
- case 'hda':
- select = this.select_datasets;
- break;
- case 'hdca':
- select = this.select_collection;
- break;
+ value : function (dict) {
+ // update current value
+ if (dict !== undefined) {
+ try {
+ // set source
+ this.current = dict.values[0].src;
+ this.refresh();
+
+ // create list
+ var list = [];
+ for (var i in dict.values) {
+ list.push(dict.values[i].id);
+ }
+
+ // identify select element
+ switch(this.current) {
+ case 'hda':
+ this.select_datasets.value(list);
+ break;
+ case 'hdca':
+ this.select_collection.value(list[0]);
+ break;
+ }
+ } catch (err) {
+ console.debug('tools-select-content::value() - Skipped.');
+ }
}
// transform into an array
- var id_list = select.value();
+ var id_list = this._select().value();
if (!(id_list instanceof Array)) {
id_list = [id_list];
}
@@ -142,12 +158,7 @@
/** Validate current selection
*/
validate: function() {
- switch(this.current) {
- case 'hda':
- return this.select_datasets.validate();
- case 'hdca':
- return this.select_collection.validate();
- }
+ return this._select().validate();
},
/** Refreshes data selection view */
@@ -162,6 +173,16 @@
this.select_collection.$el.fadeIn();
break;
}
+ },
+
+ /** Assists in selecting the current field */
+ _select: function() {
+ switch(this.current) {
+ case 'hdca':
+ return this.select_collection;
+ default:
+ return this.select_datasets;
+ }
}
});
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/tools/tools-template.js
--- a/client/galaxy/scripts/mvc/tools/tools-template.js
+++ b/client/galaxy/scripts/mvc/tools/tools-template.js
@@ -49,7 +49,7 @@
error: function(job_def) {
return '<div>' +
'<p>' +
- 'Sorry, the server could not complete the request. Please contact the Galaxy Team if this error is persistent.' +
+ 'The server could not complete the request. Please contact the Galaxy Team if this error persists.' +
'</p>' +
'<textarea class="ui-textarea" disabled style="color: black;" rows="6">' +
JSON.stringify(job_def, undefined, 4) +
diff -r 921aa1c775b54911c149fe3c8a1dc9645945a83d -r b1d9b4f49abb5f27bf54e01901fc37fe2fe20681 client/galaxy/scripts/mvc/ui/ui-slider.js
--- a/client/galaxy/scripts/mvc/ui/ui-slider.js
+++ b/client/galaxy/scripts/mvc/ui/ui-slider.js
@@ -6,9 +6,11 @@
// options
optionsDefault: {
value : '',
- min : 1,
- max : 100,
- step : 1
+ min : null,
+ max : null,
+ step : null,
+ precise : false,
+ split : 10000
},
// initialize
@@ -18,19 +20,35 @@
// configure options
this.options = Utils.merge(options, this.optionsDefault);
-
+
// create new element
this.setElement(this._template(this.options));
- // backup slider
- this.$slider = this.$el.find('#slider');
+ // determine wether to use the slider
+ this.useslider = this.options.max !== null && this.options.min !== null && this.options.max > this.options.min;
+
+ // set default step size
+ if (this.options.step === null) {
+ this.options.step = 1;
+ if (this.options.precise && this.useslider) {
+ this.options.step = (this.options.max - this.options.min) / this.options.split;
+ }
+ }
+
+ // create slider if min and max are defined properly
+ if (this.useslider) {
+ this.$slider = this.$el.find('#slider');
+ this.$slider.slider(this.options);
+ this.$slider.on('slide', function (event, ui) {
+ self.value(ui.value);
+ });
+ } else {
+ this.$el.find('.ui-form-slider-text').css('width', '100%');
+ }
// backup integer field
this.$text = this.$el.find('#text');
- // load slider plugin
- this.$slider.slider(this.options);
-
// add text field event
this.$text.on('change', function () {
self.value($(this).val());
@@ -39,24 +57,23 @@
// add text field event
this.$text.on('keydown', function (event) {
var v = event.which;
- console.log(v);
if (!(v == 8 || v == 9 || v == 13 || v == 37 || v == 39 || v == 189 || (v >= 48 && v <= 57)
- || (self.options.step != 1 && $(this).val().indexOf('.') == -1) && v == 190)) {
+ || (self.options.precise && $(this).val().indexOf('.') == -1) && v == 190)) {
event.preventDefault();
}
});
-
- // add slider event
- this.$slider.on('slide', function (event, ui) {
- self.value(ui.value);
- });
},
// value
value : function (new_val) {
if (new_val !== undefined) {
- // limit
- new_val = Math.max(Math.min(new_val, this.options.max), this.options.min);
+ // apply limit
+ if (this.options.max !== null) {
+ new_val = Math.min(new_val, this.options.max);
+ }
+ if (this.options.min !== null) {
+ new_val = Math.max(new_val, this.options.min);
+ }
// trigger on change event
if (this.options.onchange) {
@@ -64,7 +81,7 @@
}
// set values
- this.$slider.slider('value', new_val);
+ this.$slider && this.$slider.slider('value', new_val);
this.$text.val(new_val);
}
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: SelectToolParameter: Fix type check before split operation.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/20882e294f92/
Changeset: 20882e294f92
User: guerler
Date: 2014-10-16 17:42:17+00:00
Summary: SelectToolParameter: Fix type check before split operation.
Affected #: 1 file
diff -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 -r 20882e294f925cb4c895e194d508bc15306e4403 lib/galaxy/tools/parameters/basic.py
--- a/lib/galaxy/tools/parameters/basic.py
+++ b/lib/galaxy/tools/parameters/basic.py
@@ -818,7 +818,7 @@
if value == '':
value = None
else:
- if not isinstance( value, list ):
+ if isinstance( value, basestring ):
# Split on all whitespace. This not only provides flexibility
# in interpreting values but also is needed because many browsers
# use \r\n to separate lines.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: natefoo: Update tag latest_2014.10.06 for changeset e1404e285ccb
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/78c9a97be4b6/
Changeset: 78c9a97be4b6
Branch: stable
User: natefoo
Date: 2014-10-16 17:00:13+00:00
Summary: Update tag latest_2014.10.06 for changeset e1404e285ccb
Affected #: 1 file
diff -r e1404e285ccb9e52bd09c5827934cd0da1974acc -r 78c9a97be4b6bfe55136b055477fd1b9f22fd848 .hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -20,4 +20,4 @@
ca45b78adb4152fc6e7395514d46eba6b7d0b838 release_2014.08.11
548ab24667d6206780237bd807f7d857a484c461 latest_2014.08.11
2092948937ac30ef82f71463a235c66d34987088 release_2014.10.06
-1744b7d8e9ab619d78c0516f9ccb093b0a814163 latest_2014.10.06
+e1404e285ccb9e52bd09c5827934cd0da1974acc latest_2014.10.06
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: ToolForm: Move dictionary building methods from mako to api.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/0d44e35432ab/
Changeset: 0d44e35432ab
User: guerler
Date: 2014-10-16 16:43:39+00:00
Summary: ToolForm: Move dictionary building methods from mako to api.
Affected #: 15 files
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 client/galaxy/scripts/mvc/tools/tools-content.js
--- a/client/galaxy/scripts/mvc/tools/tools-content.js
+++ b/client/galaxy/scripts/mvc/tools/tools-content.js
@@ -22,7 +22,7 @@
// get history summary
Utils.get({
- url : self.base_url + '?deleted=false',
+ url : self.base_url + '?deleted=false&state=ok',
success : function(response) {
// backup summary
self.summary = response;
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -27,10 +27,8 @@
this.modal = new Ui.Modal.View();
}
- // link model/inputs and all options
- this.options = options;
- this.model = options.model;
- this.inputs = options.model.inputs;
+ // link options
+ this.options = options;
// set element
this.setElement('<div/>');
@@ -53,9 +51,13 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize contents
+ // for now the initial tool model is parsed through the mako
+ this.model = this.options;
+ this.inputs = this.options.inputs;
+
+ // request history content and build form
this.content = new ToolContent({
- history_id : this.options.history_id,
+ history_id : self.options.history_id,
success : function() {
self._buildForm();
}
@@ -89,6 +91,51 @@
console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
+ // build tool model through api call
+ _buildModel: function() {
+ // link this
+ var self = this;
+
+ // construct url
+ var model_url = galaxy_config.root + 'api/tools/' + this.options.id + '/build?';
+ if (this.options.job_id) {
+ model_url += 'job_id=' + this.options.job_id;
+ } else {
+ if (this.options.dataset_id) {
+ model_url += 'dataset_id=' + this.options.dataset_id;
+ } else {
+ var loc = top.location.href;
+ var pos = loc.indexOf('?');
+ if (loc.indexOf('tool_id=') != -1 && pos !== -1) {
+ model_url += loc.slice(pos + 1);
+ }
+ }
+ }
+
+ // get initial model
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ success : function(response) {
+ // link model data update options
+ self.options = $.extend(self.options, response);
+ self.model = response;
+ self.inputs = response.inputs;
+
+ // log success
+ console.debug('tools-form::initialize() - Initial tool model ready.');
+ console.debug(response);
+
+ // build form
+ self._buildForm();
+ },
+ error : function(response) {
+ console.debug('tools-form::initialize() - Initial tool model request failed.');
+ console.debug(response);
+ }
+ });
+ },
+
// refresh form data
_refreshForm: function() {
// link this
@@ -111,7 +158,7 @@
// post job
Utils.request({
type : 'GET',
- url : galaxy_config.root + 'tool_runner/index?tool_id=' + this.options.id + '&form_refresh=True',
+ url : galaxy_config.root + 'api/tools/' + this.options.id + '/build',
data : current_state,
success : function(response) {
console.debug('tools-form::_refreshForm() - Refreshed inputs/states.');
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 client/galaxy/scripts/mvc/tools/tools-select-content.js
--- a/client/galaxy/scripts/mvc/tools/tools-select-content.js
+++ b/client/galaxy/scripts/mvc/tools/tools-select-content.js
@@ -106,17 +106,17 @@
value : function (dict) {
// update current value
if (dict !== undefined) {
- if (dict.values.length > 0 && dict.values[0] && dict.values[0].src) {
+ try {
+ // set source
+ this.current = dict.values[0].src;
+ this.refresh();
+
// create list
var list = [];
for (var i in dict.values) {
list.push(dict.values[i].id);
}
- // set source
- this.current = dict.values[0].src;
- this.refresh();
-
// identify select element
switch(this.current) {
case 'hda':
@@ -126,6 +126,8 @@
this.select_collection.value(list[0]);
break;
}
+ } catch (err) {
+ console.debug('tools-select-content::value() - Skipped.');
}
}
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/tools/__init__.py
--- a/lib/galaxy/tools/__init__.py
+++ b/lib/galaxy/tools/__init__.py
@@ -2175,7 +2175,7 @@
for expanded_incoming in expanded_incomings:
state, state_new = self.__fetch_state( trans, expanded_incoming, history, all_pages=all_pages )
all_states.append( state )
- if state_new and "form_refresh" not in incoming:
+ if state_new:
# This feels a bit like a hack. It allows forcing full processing
# of inputs even when there is no state in the incoming dictionary
# by providing either 'runtool_btn' (the name of the submit button
@@ -2358,7 +2358,7 @@
message='Your upload was interrupted. If this was uninentional, please retry it.',
refresh_frames=[], cont=None )
- def populate_state( self, trans, inputs, state, incoming, history, source, prefix="", context=None ):
+ def populate_state( self, trans, inputs, state, incoming, history=None, source="html", prefix="", context=None ):
errors = dict()
# Push this level onto the context stack
context = ExpressionContext( state, context )
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/webapps/galaxy/api/tools.py
--- a/lib/galaxy/webapps/galaxy/api/tools.py
+++ b/lib/galaxy/webapps/galaxy/api/tools.py
@@ -10,8 +10,13 @@
from galaxy.visualization.genomes import GenomeRegion
from galaxy.util.json import dumps
from galaxy.visualization.data_providers.genome import *
-
+from galaxy.tools.parameters import params_to_incoming
+from galaxy.tools.parameters import visit_input_values
+from galaxy.tools.parameters.meta import expand_meta_parameters
from galaxy.managers.collections_util import dictify_dataset_collection_instance
+from galaxy.model import HistoryDatasetAssociation
+from galaxy.util.expressions import ExpressionContext
+from collections import Iterable
import galaxy.queue_worker
@@ -61,6 +66,15 @@
tool = self._get_tool( id )
return tool.to_dict( trans, io_details=io_details, link_details=link_details )
+ @_future_expose_api_anonymous
+ def build( self, trans, id, **kwd ):
+ """
+ GET /api/tools/{tool_id}/build
+ Returns a tool model including dynamic parameters and updated values, repeats block etc.
+ """
+ tool = self._get_tool( id )
+ return self._build_dict(trans, tool, kwd)
+
@_future_expose_api
@web.require_admin
def reload( self, trans, tool_id, **kwd ):
@@ -464,3 +478,174 @@
dataset_dict[ 'id' ] = trans.security.encode_id( dataset_dict[ 'id' ] )
dataset_dict[ 'track_config' ] = self.get_new_track_config( trans, output_dataset )
return dataset_dict
+
+ def _build_dict(self, trans, tool, kwd={}):
+ """
+ Recursively creates a tool dictionary containing repeats, dynamic options and updated states.
+ """
+ job_id = kwd.get('job_id', None)
+ dataset_id = kwd.get('dataset_id', None)
+
+ # load job details if provided
+ job = None
+ if job_id:
+ try:
+ job_id = trans.security.decode_id( job_id )
+ job = trans.sa_session.query( trans.app.model.Job ).get( job_id )
+ except Exception, exception:
+ trans.response.status = 500
+ return { 'error': 'Failed to retrieve job.' }
+ elif dataset_id:
+ try:
+ dataset_id = trans.security.decode_id( dataset_id )
+ data = trans.sa_session.query( trans.app.model.HistoryDatasetAssociation ).get( dataset_id )
+ if not ( trans.user_is_admin() or trans.app.security_agent.can_access_dataset( trans.get_current_user_roles(), data.dataset ) ):
+ trans.response.status = 500
+ return { 'error': 'User has no access to dataset.' }
+ job = data.creating_job
+ if not job:
+ trans.response.status = 500
+ return { 'error': 'Creating job not found.' }
+ except Exception, exception:
+ trans.response.status = 500
+ return { 'error': 'Failed to get job information.' }
+
+ # check if job was identified
+ if job:
+ try:
+ job_params = job.get_param_values( trans.app, ignore_errors = True )
+ job_messages = tool.check_and_update_param_values( job_params, trans, update_values=False )
+ params_to_incoming( kwd, tool.inputs, job_params, trans.app )
+ except Exception, exception:
+ trans.response.status = 500
+ return { 'error': str( exception ) }
+
+ # create parameter object
+ params = galaxy.util.Params( kwd, sanitize = False )
+
+ # convert value to jsonifiable value
+ def convert(v):
+ # check if value is numeric
+ isnumber = False
+ try:
+ float(v)
+ isnumber = True
+ except Exception:
+ pass
+
+ # fix hda parsing
+ if isinstance(v, HistoryDatasetAssociation):
+ return {
+ 'id' : trans.security.encode_id(v.id),
+ 'src' : 'hda'
+ }
+ elif isinstance(v, basestring) or isnumber:
+ return v
+ else:
+ return None
+
+ # ensures that input dictionary is jsonifiable
+ def sanitize(dict):
+ # get current value
+ value = dict['value'] if 'value' in dict else None
+
+ # identify lists
+ if dict['type'] == 'data':
+ if isinstance(value, list):
+ value = [ convert(v) for v in value ]
+ else:
+ value = [ convert(value) ]
+ value = {
+ 'batch' : dict['multiple'],
+ 'values' : value
+ }
+ elif isinstance(value, list):
+ value = [ convert(v) for v in value ]
+ else:
+ value = convert(value)
+
+ # update and return
+ dict['value'] = value
+ return dict
+
+ # build model
+ def iterate(group_inputs, inputs, tool_state, errors, other_values=None):
+ other_values = ExpressionContext( tool_state, other_values )
+ for input_index, input in enumerate( inputs.itervalues() ):
+ # create model dictionary
+ group_inputs[input_index] = input.to_dict(trans)
+
+ # identify stat for subsection/group
+ group_state = tool_state[input.name]
+
+ # iterate and update values
+ if input.type == 'repeat':
+ group_cache = group_inputs[input_index]['cache'] = {}
+ for i in range( len( group_state ) ):
+ group_cache[i] = {}
+ group_errors = errors[input.name][i] if input.name in errors else dict()
+ iterate( group_cache[i], input.inputs, group_state[i], group_errors, other_values )
+ elif input.type == 'conditional':
+ # TODO: loop over all cases
+ try:
+ test_param = group_inputs[input_index]['test_param']
+ test_param['value'] = group_state[test_param['name']]
+ except Exception:
+ pass
+ i = group_state['__current_case__']
+ group_errors = errors.get( input.name, {} )
+ iterate(group_inputs[input_index]['cases'][i]['inputs'], input.cases[i].inputs, group_state, group_errors, other_values)
+ else:
+ # create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options
+ try:
+ group_inputs[input_index] = input.to_dict(trans, other_values=other_values)
+ except Exception:
+ pass
+
+ # update input value from tool state
+ try:
+ group_inputs[input_index]['value'] = tool_state[group_inputs[input_index]['name']]
+ except Exception:
+ pass
+
+ # sanitize if value exists
+ if group_inputs[input_index]['value']:
+ group_inputs[input_index] = sanitize(group_inputs[input_index])
+
+ # do param translation here, used by datasource tools
+ if tool.input_translator:
+ tool.input_translator.translate( params )
+
+ # create tool state
+ state = tool.new_state(trans, all_pages=True)
+ errors = tool.populate_state( trans, tool.inputs, state.inputs, params.__dict__ )
+
+ # create basic tool model
+ tool_model = tool.to_dict(trans)
+ tool_model['inputs'] = {}
+
+ # build tool model
+ iterate(tool_model['inputs'], tool.inputs, state.inputs, errors, '')
+
+ # load tool help
+ tool_help = ''
+ if tool.help:
+ tool_help = tool.help
+ tool_help = tool_help.render( static_path=web.url_for( '/static' ), host_url=web.url_for('/', qualified=True) )
+ if type( tool_help ) is not unicode:
+ tool_help = unicode( tool_help, 'utf-8')
+
+ # check if citations exist
+ tool_citations = False
+ if tool.citations:
+ tool_citations = True
+
+ # add additional properties
+ tool_model.update({
+ 'help' : tool_help,
+ 'citations' : tool_citations,
+ 'biostar_url' : trans.app.config.biostar_url
+ })
+
+ # return enriched tool model
+ return tool_model
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/webapps/galaxy/buildapp.py
--- a/lib/galaxy/webapps/galaxy/buildapp.py
+++ b/lib/galaxy/webapps/galaxy/buildapp.py
@@ -180,6 +180,7 @@
webapp.mapper.resource( 'ftp_file', 'ftp_files', path_prefix='/api' )
webapp.mapper.resource( 'group', 'groups', path_prefix='/api' )
webapp.mapper.resource_with_deleted( 'quota', 'quotas', path_prefix='/api' )
+ webapp.mapper.connect( '/api/tools/{id:.+?}/build', action='build', controller="tools" )
webapp.mapper.connect( '/api/tools/{id:.+?}/reload', action='reload', controller="tools" )
webapp.mapper.connect( '/api/tools/{id:.+?}/citations', action='citations', controller="tools" )
webapp.mapper.connect( '/api/tools/{id:.+?}/download', action='download', controller="tools" )
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 lib/galaxy/webapps/galaxy/controllers/tool_runner.py
--- a/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
+++ b/lib/galaxy/webapps/galaxy/controllers/tool_runner.py
@@ -60,9 +60,6 @@
# so the default selected option should be the most recent version of the tool. The following
# check will mae sure this occurs.
refreshed_on_change = kwd.get( 'refresh', False )
- # This is the new tool forms equivalent to the 'refresh' parameter of the classic tool form
- form_refresh = kwd.get( 'form_refresh', False )
- process_state = "populate" if form_refresh else "update"
tool_version_select_field, tools, tool = self.__get_tool_components( tool_id,
tool_version=None,
get_loaded_tools_by_lineage=False,
@@ -90,7 +87,7 @@
# We may be visiting Galaxy for the first time ( e.g., sending data from UCSC ),
# so make sure to create a new history if we've never had one before.
history = tool.get_default_history_by_trans( trans, create=True )
- template, vars = tool.handle_input( trans, params.__dict__, process_state=process_state)
+ template, vars = tool.handle_input( trans, params.__dict__ )
if len( params ) > 0:
trans.log_event( "Tool params: %s" % ( str( params ) ), tool_id=tool_id )
add_frame = AddFrameData()
@@ -98,8 +95,6 @@
if from_noframe is not None:
add_frame.wiki_url = trans.app.config.wiki_url
add_frame.from_noframe = True
- if form_refresh:
- template = "tool_form_refresh.mako"
return trans.fill_template( template,
history=history,
toolbox=self.get_toolbox(),
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/mvc/tools/tools-content.js
--- a/static/scripts/mvc/tools/tools-content.js
+++ b/static/scripts/mvc/tools/tools-content.js
@@ -22,7 +22,7 @@
// get history summary
Utils.get({
- url : self.base_url + '?deleted=false',
+ url : self.base_url + '?deleted=false&state=ok',
success : function(response) {
// backup summary
self.summary = response;
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -27,10 +27,8 @@
this.modal = new Ui.Modal.View();
}
- // link model/inputs and all options
- this.options = options;
- this.model = options.model;
- this.inputs = options.model.inputs;
+ // link options
+ this.options = options;
// set element
this.setElement('<div/>');
@@ -53,9 +51,13 @@
// reset input element list, which contains the dom elements of each input element (includes also the input field)
this.element_list = {};
- // initialize contents
+ // for now the initial tool model is parsed through the mako
+ this.model = this.options;
+ this.inputs = this.options.inputs;
+
+ // request history content and build form
this.content = new ToolContent({
- history_id : this.options.history_id,
+ history_id : self.options.history_id,
success : function() {
self._buildForm();
}
@@ -89,6 +91,51 @@
console.debug('tools-form::refresh() - Recreated data structure. Refresh.');
},
+ // build tool model through api call
+ _buildModel: function() {
+ // link this
+ var self = this;
+
+ // construct url
+ var model_url = galaxy_config.root + 'api/tools/' + this.options.id + '/build?';
+ if (this.options.job_id) {
+ model_url += 'job_id=' + this.options.job_id;
+ } else {
+ if (this.options.dataset_id) {
+ model_url += 'dataset_id=' + this.options.dataset_id;
+ } else {
+ var loc = top.location.href;
+ var pos = loc.indexOf('?');
+ if (loc.indexOf('tool_id=') != -1 && pos !== -1) {
+ model_url += loc.slice(pos + 1);
+ }
+ }
+ }
+
+ // get initial model
+ Utils.request({
+ type : 'GET',
+ url : model_url,
+ success : function(response) {
+ // link model data update options
+ self.options = $.extend(self.options, response);
+ self.model = response;
+ self.inputs = response.inputs;
+
+ // log success
+ console.debug('tools-form::initialize() - Initial tool model ready.');
+ console.debug(response);
+
+ // build form
+ self._buildForm();
+ },
+ error : function(response) {
+ console.debug('tools-form::initialize() - Initial tool model request failed.');
+ console.debug(response);
+ }
+ });
+ },
+
// refresh form data
_refreshForm: function() {
// link this
@@ -111,7 +158,7 @@
// post job
Utils.request({
type : 'GET',
- url : galaxy_config.root + 'tool_runner/index?tool_id=' + this.options.id + '&form_refresh=True',
+ url : galaxy_config.root + 'api/tools/' + this.options.id + '/build',
data : current_state,
success : function(response) {
console.debug('tools-form::_refreshForm() - Refreshed inputs/states.');
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/mvc/tools/tools-select-content.js
--- a/static/scripts/mvc/tools/tools-select-content.js
+++ b/static/scripts/mvc/tools/tools-select-content.js
@@ -106,17 +106,17 @@
value : function (dict) {
// update current value
if (dict !== undefined) {
- if (dict.values.length > 0 && dict.values[0] && dict.values[0].src) {
+ try {
+ // set source
+ this.current = dict.values[0].src;
+ this.refresh();
+
// create list
var list = [];
for (var i in dict.values) {
list.push(dict.values[i].id);
}
- // set source
- this.current = dict.values[0].src;
- this.refresh();
-
// identify select element
switch(this.current) {
case 'hda':
@@ -126,6 +126,8 @@
this.select_collection.value(list[0]);
break;
}
+ } catch (err) {
+ console.debug('tools-select-content::value() - Skipped.');
}
}
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/packed/mvc/tools/tools-content.js
--- a/static/scripts/packed/mvc/tools/tools-content.js
+++ b/static/scripts/packed/mvc/tools/tools-content.js
@@ -1,1 +1,1 @@
-define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.base_url=galaxy_config.root+"api/histories/"+c.history_id+"/contents";this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:b.base_url+"?deleted=false",success:function(e){b.summary=e;b.summary.sort(function(g,f){return g.hid>f.hid?-1:(g.hid<f.hid?1:0)});console.debug("tools-content::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-content::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-content::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];var g="dataset";if(c.src=="hdca"){g="dataset_collection"}for(var d in this.summary){var e=this.summary[d];var f=false;for(var d in c.extensions){if(this._matchType(c.extensions[d],e.extension)){f=true;break}}if((e.history_content_type===g)&&(f||!c.extensions)){b.push(e)}}return b},get:function(b){return _.findWhere(this.summary,b)||{}},getDetails:function(b){if(!b.id||b.id==="null"){b.success&&b.success();return}var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){b.success&&b.success();console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-content::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})});
\ No newline at end of file
+define(["utils/utils"],function(a){return Backbone.Model.extend({initialize:function(c){this.base_url=galaxy_config.root+"api/histories/"+c.history_id+"/contents";this.datatypes={};this.summary={};var b=this;a.get({url:galaxy_config.root+"api/datatypes/mapping",cache:true,success:function(d){b.datatypes=d;a.get({url:b.base_url+"?deleted=false&state=ok",success:function(e){b.summary=e;b.summary.sort(function(g,f){return g.hid>f.hid?-1:(g.hid<f.hid?1:0)});console.debug("tools-content::initialize() - Completed.");c.success&&c.success()},error:function(e){console.debug("tools-content::initialize() - Ajax request for summary failed.");console.debug(e)}})},error:function(d){console.debug("tools-content::initialize() - Ajax request for datatypes failed.");console.debug(d)}})},filterType:function(c){c=c||{};var b=[];var g="dataset";if(c.src=="hdca"){g="dataset_collection"}for(var d in this.summary){var e=this.summary[d];var f=false;for(var d in c.extensions){if(this._matchType(c.extensions[d],e.extension)){f=true;break}}if((e.history_content_type===g)&&(f||!c.extensions)){b.push(e)}}return b},get:function(b){return _.findWhere(this.summary,b)||{}},getDetails:function(b){if(!b.id||b.id==="null"){b.success&&b.success();return}var c=this.base_url+"/datasets/"+b.id;if(b.src=="hdca"){c=this.base_url+"/dataset_collections/"+b.id}a.get({url:c,success:function(d){b.success&&b.success(d)},error:function(d){b.success&&b.success();console.debug("tools-content::getDetails() - Ajax request for content failed.");console.debug(d)}})},_matchType:function(f,b){var c=this.datatypes.ext_to_class_name[f];if(!c){console.debug("tools-content::_matchType() - Specific target class unavailable. Accepting all formats.");return true}var d=this.datatypes.ext_to_class_name[b];if(!d){console.debug("tools-content::_matchType() - Specific reference class unavailable. Accepting all formats.");return true}var e=this.datatypes.class_to_classes[d];if(e[c]){return true}return false}})});
\ No newline at end of file
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/packed/mvc/tools/tools-form.js
--- a/static/scripts/packed/mvc/tools/tools-form.js
+++ b/static/scripts/packed/mvc/tools/tools-form.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,h,l,j,a,e,d,f,k,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.model=n.model;this.inputs=n.model.inputs;this.setElement("<div/>");$(this.container).append(this.$el);this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.content=new f({history_id:this.options.history_id,success:function(){m._buildForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_refreshForm:function(){var m=this;var n=this.tree.finalize({data:function(o){if(o.values.length>0&&o.values[0]&&o.values[0].src==="hda"){return m.content.get({id:o.values[0].id}).dataset_id}return null}});console.debug("tools-form::_refreshForm() - Refreshing inputs/states.");console.debug(n);i.request({type:"GET",url:galaxy_config.root+"tool_runner/index?tool_id="+this.options.id+"&form_refresh=True",data:n,success:function(o){console.debug("tools-form::_refreshForm() - Refreshed inputs/states.");console.debug(o)},error:function(o){console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(o)}})},_buildForm:function(){var n=this;var p=new l.ButtonMenu({icon:"fa-gear",tooltip:"Click to see a list of options."});if(this.options.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+n.options.id)}});if(Galaxy.currUser.get("is_admin")){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.section=new k.View(n,{inputs:this.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new h.View({icon:"fa-wrench",title:"<b>"+this.model.name+"</b> "+this.model.description,operations:{menu:p},buttons:{execute:new l.Button({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){n.job_handler.submit()}})}});this.$el.append(this.portlet.$el);if(this.options.help!=""){this.$el.append(d.help(this.options.help))}if(this.options.citations){this.$el.append(d.citations());var m=new j.ToolCitationCollection();m.tool_id=this.options.id;var o=new a.CitationListView({collection:m});o.render();m.fetch()}this.portlet.append(this.section.$el);this.refresh()}});return{View:b}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,h,l,j,a,e,d,f,k,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.setElement("<div/>");$(this.container).append(this.$el);this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.model=this.options;this.inputs=this.options.inputs;this.content=new f({history_id:m.options.history_id,success:function(){m._buildForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_buildModel:function(){var m=this;var n=galaxy_config.root+"api/tools/"+this.options.id+"/build?";if(this.options.job_id){n+="job_id="+this.options.job_id}else{if(this.options.dataset_id){n+="dataset_id="+this.options.dataset_id}else{var o=top.location.href;var p=o.indexOf("?");if(o.indexOf("tool_id=")!=-1&&p!==-1){n+=o.slice(p+1)}}}i.request({type:"GET",url:n,success:function(q){m.options=$.extend(m.options,q);m.model=q;m.inputs=q.inputs;console.debug("tools-form::initialize() - Initial tool model ready.");console.debug(q);m._buildForm()},error:function(q){console.debug("tools-form::initialize() - Initial tool model request failed.");console.debug(q)}})},_refreshForm:function(){var m=this;var n=this.tree.finalize({data:function(o){if(o.values.length>0&&o.values[0]&&o.values[0].src==="hda"){return m.content.get({id:o.values[0].id}).dataset_id}return null}});console.debug("tools-form::_refreshForm() - Refreshing inputs/states.");console.debug(n);i.request({type:"GET",url:galaxy_config.root+"api/tools/"+this.options.id+"/build",data:n,success:function(o){console.debug("tools-form::_refreshForm() - Refreshed inputs/states.");console.debug(o)},error:function(o){console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(o)}})},_buildForm:function(){var n=this;var p=new l.ButtonMenu({icon:"fa-gear",tooltip:"Click to see a list of options."});if(this.options.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+n.options.id)}});if(Galaxy.currUser.get("is_admin")){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.section=new k.View(n,{inputs:this.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new h.View({icon:"fa-wrench",title:"<b>"+this.model.name+"</b> "+this.model.description,operations:{menu:p},buttons:{execute:new l.Button({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){n.job_handler.submit()}})}});this.$el.append(this.portlet.$el);if(this.options.help!=""){this.$el.append(d.help(this.options.help))}if(this.options.citations){this.$el.append(d.citations());var m=new j.ToolCitationCollection();m.tool_id=this.options.id;var o=new a.CitationListView({collection:m});o.render();m.fetch()}this.portlet.append(this.section.$el);this.refresh()}});return{View:b}});
\ No newline at end of file
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 static/scripts/packed/mvc/tools/tools-select-content.js
--- a/static/scripts/packed/mvc/tools/tools-select-content.js
+++ b/static/scripts/packed/mvc/tools/tools-select-content.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.content.filterType({src:"hda",extensions:h.extensions});var k=[];for(var j in l){k.push({label:l[j].hid+": "+l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.content.filterType({src:"hdca",extensions:h.extensions});var f=[];for(var j in m){f.push({label:m[j].hid+": "+m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(k){if(k!==undefined){if(k.values.length>0&&k.values[0]&&k.values[0].src){var j=[];for(var g in k.values){j.push(k.values[g].id)}this.current=k.values[0].src;this.refresh();switch(this.current){case"hda":this.select_datasets.value(j);break;case"hdca":this.select_collection.value(j[0]);break}}}var h=this._select().value();if(!(h instanceof Array)){h=[h]}var f={batch:!this.options.multiple,values:[]};for(var g in h){f.values.push({id:h[g],src:this.current})}return f},validate:function(){return this._select().validate()},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}},_select:function(){switch(this.current){case"hdca":return this.select_collection;default:return this.select_datasets}}});return{View:d}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-misc","mvc/ui/ui-tabs","mvc/tools/tools-template"],function(c,e,b,a){var d=Backbone.View.extend({initialize:function(n,h){this.options=h;var g=this;this.setElement("<div/>");this.current="hda";this.button_new=new e.RadioButton.View({value:this.current,data:[{icon:"fa-file-o",label:"Select datasets",value:"hda"},{icon:"fa-files-o",label:"Select a collection",value:"hdca"}],onchange:function(i){g.current=i;g.refresh();g.trigger("change")}});var l=n.content.filterType({src:"hda",extensions:h.extensions});var k=[];for(var j in l){k.push({label:l[j].hid+": "+l[j].name,value:l[j].id})}this.select_datasets=new e.Select.View({multiple:true,data:k,value:k[0]&&k[0].value,onchange:function(){g.trigger("change")}});var m=n.content.filterType({src:"hdca",extensions:h.extensions});var f=[];for(var j in m){f.push({label:m[j].hid+": "+m[j].name,value:m[j].id})}this.select_collection=new e.Select.View({data:f,value:f[0]&&f[0].value,onchange:function(){g.trigger("change")}});this.$el.append(c.wrap(this.button_new.$el));this.$el.append(this.select_datasets.$el);this.$el.append(this.select_collection.$el);if(!this.options.multiple){this.$el.append(a.batchMode())}this.refresh();this.on("change",function(){if(h.onchange){h.onchange(g.value())}})},value:function(l){if(l!==undefined){try{this.current=l.values[0].src;this.refresh();var k=[];for(var g in l.values){k.push(l.values[g].id)}switch(this.current){case"hda":this.select_datasets.value(k);break;case"hdca":this.select_collection.value(k[0]);break}}catch(j){console.debug("tools-select-content::value() - Skipped.")}}var h=this._select().value();if(!(h instanceof Array)){h=[h]}var f={batch:!this.options.multiple,values:[]};for(var g in h){f.values.push({id:h[g],src:this.current})}return f},validate:function(){return this._select().validate()},refresh:function(){switch(this.current){case"hda":this.select_datasets.$el.fadeIn();this.select_collection.$el.hide();break;case"hdca":this.select_datasets.$el.hide();this.select_collection.$el.fadeIn();break}},_select:function(){switch(this.current){case"hdca":return this.select_collection;default:return this.select_datasets}}});return{View:d}});
\ No newline at end of file
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 templates/webapps/galaxy/tool_form.mako
--- a/templates/webapps/galaxy/tool_form.mako
+++ b/templates/webapps/galaxy/tool_form.mako
@@ -1,16 +1,27 @@
<%inherit file="/base.mako"/>
-## initialize configuration
-<%namespace name="tool_form_refresh" file="./webapps/galaxy/tool_form_refresh.mako" import="*" />
-${tool_form_refresh.init()}
-
## new tool form
+<%
+ ## TEMPORARY: create tool dictionary in mako while both tool forms are in use.
+ ## This avoids making two separate requests since the classic form requires the mako anyway.
+ from galaxy.webapps.galaxy.api.tools import ToolsController
+ controller = ToolsController(trans.app)
+ params = dict(trans.request.params)
+ if 'id' in params:
+ params['dataset_id'] = params['id']
+ self.form_config = controller._build_dict(trans, tool, params)
+ self.form_config.update({
+ 'id' : tool.id,
+ 'job_id' : trans.security.encode_id( job.id ) if job else None,
+ 'history_id' : trans.security.encode_id( trans.history.id )
+ })
+%>
${h.js("libs/bibtex", "libs/jquery/jquery-ui")}
${h.css('base', 'jquery-ui/smoothness/jquery-ui')}
<script>
require(['mvc/tools/tools-form'], function(ToolsForm){
$(function(){
- var form = new ToolsForm.View(${ h.dumps(tool_form_refresh.form_config) });
+ var form = new ToolsForm.View(${ h.dumps(self.form_config) });
});
});
</script>
diff -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 -r 0d44e35432abe4071aa073d1eb4cad074b7fc067 templates/webapps/galaxy/tool_form_refresh.mako
--- a/templates/webapps/galaxy/tool_form_refresh.mako
+++ /dev/null
@@ -1,138 +0,0 @@
-<%def name="init()">
-<%
- ## create basic tool model
- tool_model = tool.to_dict(trans)
- tool_model['inputs'] = {}
-
- ## convert value to jsonifiable value
- def convert(v):
- # check if value is numeric
- isnumber = False
- try:
- float(v)
- isnumber = True
- except Exception:
- pass
-
- ## fix hda parsing
- if isinstance(v, HistoryDatasetAssociation):
- return {
- 'id' : trans.security.encode_id(v.id),
- 'src' : 'hda'
- }
- elif isinstance(v, basestring) or isnumber:
- return v
- else:
- return None
-
- ## ensures that input dictionary is jsonifiable
- from collections import Iterable
- from galaxy.model import HistoryDatasetAssociation
- def sanitize(dict):
- ## quotations for Infinity so its jsonifiable
- for name in dict:
- if dict[name] == Infinity:
- dict[name] = 'Infinity'
-
- ## get current value
- value = dict['value'] if 'value' in dict else None
-
- ## identify lists
- if dict['type'] == 'data':
- if isinstance(value, list):
- value = [ convert(v) for v in value ]
- else:
- value = [ convert(value) ]
- value = {
- 'batch' : dict['multiple'],
- 'values' : value
- }
- elif isinstance(value, list):
- value = [ convert(v) for v in value ]
- else:
- value = convert(value)
-
- ## update and return
- dict['value'] = value
- return dict
-
- ## build model
- def build(group_inputs, inputs, tool_state, errors, other_values=None):
- from galaxy.util.expressions import ExpressionContext
- other_values = ExpressionContext( tool_state, other_values )
- for input_index, input in enumerate( inputs.itervalues() ):
- ## create model dictionary
- group_inputs[input_index] = input.to_dict(trans)
-
- ## identify stat for subsection/group
- group_state = tool_state[input.name]
-
- ## iterate and update values
- if input.type == "repeat":
- group_cache = group_inputs[input_index]['cache'] = {}
- for i in range( len( group_state ) ):
- group_cache[i] = {}
- group_errors = errors[input.name][i] if input.name in errors else dict()
- build( group_cache[i], input.inputs, group_state[i], group_errors, other_values )
- elif input.type == "conditional":
- try:
- test_param = group_inputs[input_index]['test_param']
- test_param['value'] = group_state[test_param['name']]
- except Exception:
- pass
- i = group_state['__current_case__']
- group_errors = errors.get( input.name, {} )
- build(group_inputs[input_index]['cases'][i]['inputs'], input.cases[i].inputs, group_state, group_errors, other_values)
- else:
- ## create input dictionary, try to pass other_values if to_dict function supports it e.g. dynamic options
- try:
- group_inputs[input_index] = input.to_dict(trans, other_values=other_values)
- except Exception:
- pass
-
- ## update input value from tool state
- try:
- group_inputs[input_index]['value'] = tool_state[group_inputs[input_index]['name']]
- group_inputs[input_index] = sanitize(group_inputs[input_index])
- except Exception:
- pass
- endif
- endfor
- build(tool_model['inputs'], tool.inputs, tool_state.inputs, errors, "")
-
- # load tool help
- tool_help = ''
- if tool.help:
- if tool.has_multiple_pages:
- tool_help = tool.help_by_page[tool_state.page]
- else:
- tool_help = tool.help
-
- # Help is Mako template, so render using current static path.
- tool_help = tool_help.render( static_path=h.url_for( '/static' ), host_url=h.url_for('/', qualified=True) )
-
- # Convert to unicode to display non-ascii characters.
- if type( tool_help ) is not unicode:
- tool_help = unicode( tool_help, 'utf-8')
- endif
-
- # check if citations exist
- tool_citations = False
- if tool.citations:
- tool_citations = True
-
- # form configuration
- self.form_config = {
- 'id' : tool.id,
- 'model' : tool_model,
- 'help' : tool_help,
- 'citations' : tool_citations,
- 'biostar_url' : trans.app.config.biostar_url,
- 'history_id' : trans.security.encode_id( trans.history.id ),
- 'job_id' : trans.security.encode_id( job.id ) if job else None
- }
-%>
-</%def>
-
-${ init() }
-${ h.dumps(self.form_config) }
\ 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: jmchilton: Fix for datatypes consuming output extra files path for the change in d781366.
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e1404e285ccb/
Changeset: e1404e285ccb
Branch: stable
User: jmchilton
Date: 2014-10-15 16:57:10+00:00
Summary: Fix for datatypes consuming output extra files path for the change in d781366.
That change forced $output.extra_files_path to be the same thing as $output.files_path. See rational in changeset.
Some datatypes however consume this path when generated metadata - post d781366 these datatypes would be accessing the wrong directory. This fixes them.
The suggested best practice I would put forward is $input.extra_files_path and $output.files_path. $output.extra_files_path redirects to $output.files_path for newer Galaxy versions (August 2014+) so that Galaxy configurations requiring this directory be in the jobs working directory work. Datatypes consuming dataset.extra_files_path for these outputs will be broken when used with $output.files_path for the August release of Galaxy - but if this changeset is back-ported to the October 2014 release then these types and tools will work going forward (without modification).
It can be verified that the older releases are broken with the following existing test (fixed with this changeset).
./run_functional_tests.sh -framework -id composite_output
Affected #: 2 files
diff -r cdd3a8a9cd7d5d71705843d2fa448462c7ed0675 -r e1404e285ccb9e52bd09c5827934cd0da1974acc lib/galaxy/model/__init__.py
--- a/lib/galaxy/model/__init__.py
+++ b/lib/galaxy/model/__init__.py
@@ -1332,6 +1332,7 @@
self.purged = False
self.purgable = purgable
self.external_filename = external_filename
+ self.external_extra_files_path = None
self._extra_files_path = extra_files_path
self.file_size = file_size
if uuid is None:
@@ -1355,9 +1356,20 @@
else:
self.external_filename = filename
file_name = property( get_file_name, set_file_name )
- @property
- def extra_files_path( self ):
- return self.object_store.get_filename( self, dir_only=True, extra_dir=self._extra_files_path or "dataset_%d_files" % self.id )
+ def get_extra_files_path( self ):
+ # Unlike get_file_name - extrnal_extra_files_path is not backed by an
+ # actual database column so if SA instantiates this object - the
+ # attribute won't exist yet.
+ if not getattr( self, "external_extra_files_path", None ):
+ return self.object_store.get_filename( self, dir_only=True, extra_dir=self._extra_files_path or "dataset_%d_files" % self.id )
+ else:
+ return os.path.abspath( self.external_extra_files_path )
+ def set_extra_files_path( self, extra_files_path ):
+ if not extra_files_path:
+ self.external_extra_files_path = None
+ else:
+ self.external_extra_files_path = extra_files_path
+ extra_files_path = property( get_extra_files_path, set_extra_files_path)
def _calculate_size( self ):
if self.external_filename:
try:
diff -r cdd3a8a9cd7d5d71705843d2fa448462c7ed0675 -r e1404e285ccb9e52bd09c5827934cd0da1974acc scripts/set_metadata.py
--- a/scripts/set_metadata.py
+++ b/scripts/set_metadata.py
@@ -120,6 +120,8 @@
dataset = cPickle.load( open( filename_in ) ) # load DatasetInstance
if dataset_filename_override:
dataset.dataset.external_filename = dataset_filename_override
+ files_path = os.path.abspath(os.path.join( tool_job_working_directory, "dataset_%s_files" % (dataset.dataset.id) ))
+ dataset.dataset.external_extra_files_path = files_path
if dataset.dataset.id in existing_job_metadata_dict:
dataset.extension = existing_job_metadata_dict[ dataset.dataset.id ].get( 'ext', dataset.extension )
# Metadata FileParameter types may not be writable on a cluster node, and are therefore temporarily substituted with MetadataTempFiles
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: ToolForm: Fix options menu
by commits-noreply@bitbucket.org 16 Oct '14
by commits-noreply@bitbucket.org 16 Oct '14
16 Oct '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9b09297ed0db/
Changeset: 9b09297ed0db
User: guerler
Date: 2014-10-16 14:48:18+00:00
Summary: ToolForm: Fix options menu
Affected #: 3 files
diff -r 6e605c5d9feff984bfb5e67f2c36a400abdcae85 -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 client/galaxy/scripts/mvc/tools/tools-form.js
--- a/client/galaxy/scripts/mvc/tools/tools-form.js
+++ b/client/galaxy/scripts/mvc/tools/tools-form.js
@@ -135,25 +135,28 @@
tooltip : 'Click to see a list of options.'
});
- // add question option
- menu.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
- }
- });
+ // configure button selection
+ if(this.options.biostar_url) {
+ // add question option
+ menu.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
+ }
+ });
+ };
// create share button
menu.addMenu({
@@ -213,12 +216,6 @@
}
});
- // configure button selection
- if(!this.options.biostar_url) {
- button_question.$el.hide();
- button_search.$el.hide();
- }
-
// append form
this.$el.append(this.portlet.$el);
diff -r 6e605c5d9feff984bfb5e67f2c36a400abdcae85 -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 static/scripts/mvc/tools/tools-form.js
--- a/static/scripts/mvc/tools/tools-form.js
+++ b/static/scripts/mvc/tools/tools-form.js
@@ -135,25 +135,28 @@
tooltip : 'Click to see a list of options.'
});
- // add question option
- menu.addMenu({
- icon : 'fa-question-circle',
- title : 'Question?',
- tooltip : 'Ask a question about this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/p/new/post/');
- }
- });
-
- // create search button
- menu.addMenu({
- icon : 'fa-search',
- title : 'Search',
- tooltip : 'Search help for this tool (Biostar)',
- onclick : function() {
- window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
- }
- });
+ // configure button selection
+ if(this.options.biostar_url) {
+ // add question option
+ menu.addMenu({
+ icon : 'fa-question-circle',
+ title : 'Question?',
+ tooltip : 'Ask a question about this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/p/new/post/');
+ }
+ });
+
+ // create search button
+ menu.addMenu({
+ icon : 'fa-search',
+ title : 'Search',
+ tooltip : 'Search help for this tool (Biostar)',
+ onclick : function() {
+ window.open(self.options.biostar_url + '/t/' + self.options.id + '/');
+ }
+ });
+ };
// create share button
menu.addMenu({
@@ -213,12 +216,6 @@
}
});
- // configure button selection
- if(!this.options.biostar_url) {
- button_question.$el.hide();
- button_search.$el.hide();
- }
-
// append form
this.$el.append(this.portlet.$el);
diff -r 6e605c5d9feff984bfb5e67f2c36a400abdcae85 -r 9b09297ed0dbf506d5de13b6f91bbbd334b86238 static/scripts/packed/mvc/tools/tools-form.js
--- a/static/scripts/packed/mvc/tools/tools-form.js
+++ b/static/scripts/packed/mvc/tools/tools-form.js
@@ -1,1 +1,1 @@
-define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,h,l,j,a,e,d,f,k,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.model=n.model;this.inputs=n.model.inputs;this.setElement("<div/>");$(this.container).append(this.$el);this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.content=new f({history_id:this.options.history_id,success:function(){m._buildForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_refreshForm:function(){var m=this;var n=this.tree.finalize({data:function(o){if(o.values.length>0&&o.values[0]&&o.values[0].src==="hda"){return m.content.get({id:o.values[0].id}).dataset_id}return null}});console.debug("tools-form::_refreshForm() - Refreshing inputs/states.");console.debug(n);i.request({type:"GET",url:galaxy_config.root+"tool_runner/index?tool_id="+this.options.id+"&form_refresh=True",data:n,success:function(o){console.debug("tools-form::_refreshForm() - Refreshed inputs/states.");console.debug(o)},error:function(o){console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(o)}})},_buildForm:function(){var n=this;var p=new l.ButtonMenu({icon:"fa-gear",tooltip:"Click to see a list of options."});p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}});p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+n.options.id)}});if(Galaxy.currUser.get("is_admin")){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.section=new k.View(n,{inputs:this.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new h.View({icon:"fa-wrench",title:"<b>"+this.model.name+"</b> "+this.model.description,operations:{menu:p},buttons:{execute:new l.Button({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){n.job_handler.submit()}})}});if(!this.options.biostar_url){button_question.$el.hide();button_search.$el.hide()}this.$el.append(this.portlet.$el);if(this.options.help!=""){this.$el.append(d.help(this.options.help))}if(this.options.citations){this.$el.append(d.citations());var m=new j.ToolCitationCollection();m.tool_id=this.options.id;var o=new a.CitationListView({collection:m});o.render();m.fetch()}this.portlet.append(this.section.$el);this.refresh()}});return{View:b}});
\ No newline at end of file
+define(["utils/utils","mvc/ui/ui-portlet","mvc/ui/ui-misc","mvc/citation/citation-model","mvc/citation/citation-view","mvc/tools","mvc/tools/tools-template","mvc/tools/tools-content","mvc/tools/tools-section","mvc/tools/tools-tree","mvc/tools/tools-jobs"],function(i,h,l,j,a,e,d,f,k,c,g){var b=Backbone.View.extend({container:"body",initialize:function(n){console.debug(n);var m=this;if(parent.Galaxy&&parent.Galaxy.modal){this.modal=parent.Galaxy.modal}else{this.modal=new l.Modal.View()}this.options=n;this.model=n.model;this.inputs=n.model.inputs;this.setElement("<div/>");$(this.container).append(this.$el);this.tree=new c(this);this.job_handler=new g(this);this.field_list={};this.input_list={};this.element_list={};this.content=new f({history_id:this.options.history_id,success:function(){m._buildForm()}})},message:function(m){$(this.container).empty();$(this.container).append(m)},reset:function(){for(var m in this.element_list){this.element_list[m].reset()}},refresh:function(){this.tree.refresh();for(var m in this.field_list){this.field_list[m].trigger("change")}console.debug("tools-form::refresh() - Recreated data structure. Refresh.")},_refreshForm:function(){var m=this;var n=this.tree.finalize({data:function(o){if(o.values.length>0&&o.values[0]&&o.values[0].src==="hda"){return m.content.get({id:o.values[0].id}).dataset_id}return null}});console.debug("tools-form::_refreshForm() - Refreshing inputs/states.");console.debug(n);i.request({type:"GET",url:galaxy_config.root+"tool_runner/index?tool_id="+this.options.id+"&form_refresh=True",data:n,success:function(o){console.debug("tools-form::_refreshForm() - Refreshed inputs/states.");console.debug(o)},error:function(o){console.debug("tools-form::_refreshForm() - Refresh request failed.");console.debug(o)}})},_buildForm:function(){var n=this;var p=new l.ButtonMenu({icon:"fa-gear",tooltip:"Click to see a list of options."});if(this.options.biostar_url){p.addMenu({icon:"fa-question-circle",title:"Question?",tooltip:"Ask a question about this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/p/new/post/")}});p.addMenu({icon:"fa-search",title:"Search",tooltip:"Search help for this tool (Biostar)",onclick:function(){window.open(n.options.biostar_url+"/t/"+n.options.id+"/")}})}p.addMenu({icon:"fa-share",title:"Share",tooltip:"Share this tool",onclick:function(){prompt("Copy to clipboard: Ctrl+C, Enter",window.location.origin+galaxy_config.root+"root?tool_id="+n.options.id)}});if(Galaxy.currUser.get("is_admin")){p.addMenu({icon:"fa-download",title:"Download",tooltip:"Download this tool",onclick:function(){window.location.href=galaxy_config.root+"api/tools/"+n.options.id+"/download"}})}this.section=new k.View(n,{inputs:this.inputs,cls:"ui-table-plain"});if(this.incompatible){this.$el.hide();$("#tool-form-classic").show();return}this.portlet=new h.View({icon:"fa-wrench",title:"<b>"+this.model.name+"</b> "+this.model.description,operations:{menu:p},buttons:{execute:new l.Button({icon:"fa-check",tooltip:"Execute the tool",title:"Execute",cls:"btn btn-primary",floating:"clear",onclick:function(){n.job_handler.submit()}})}});this.$el.append(this.portlet.$el);if(this.options.help!=""){this.$el.append(d.help(this.options.help))}if(this.options.citations){this.$el.append(d.citations());var m=new j.ToolCitationCollection();m.tool_id=this.options.id;var o=new a.CitationListView({collection:m});o.render();m.fetch()}this.portlet.append(this.section.$el);this.refresh()}});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